JavaScript
gif
GIFアニメ
Cesium
セシウム

Cesiumで動的にオブジェクトを追加する(見せかけ)

More than 1 year has passed since last update.

Cesiumで遊んだ記録

用意するもの

  • ここからダウンロード
  • コンソールを開いて
python -m SimpleHTTPServer
test.html
<!DOCTYPE html>
<html lang="jp">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
  <title>mapping</title>
  <script src="Build/Cesium/Cesium.js"></script>
  <style>
      @import url(Build/Cesium/Widgets/widgets.css);
  </style>
</head>
<body>
  <div id="cesiumContainer"></div>
  <script>
  var viewer = new Cesium.Viewer('cesiumContainer');
  </script>
</body>
</html>

earth1.PNG

わぁ!?なんかしゅごいね!しゅごい!ああっこれしゅごいのおぉ!
マウスでクルクル回せるしマップを切り替えられるし・・・これは遊べる!!...

いろいろオブジェクトを追加できるみたい 一覧
適当に日本の上に円柱を立ててみる

test.html
var viewer = new Cesium.Viewer('cesiumContainer' , {navigationHelpButton: true, animation: false, timeline: false, infoBox: false, fullscreenButton: true,});

//object sample
viewer.entities.add({name : 'Cylinder',position: Cesium.Cartesian3.fromDegrees(139.691717, 35.689568, 2000000),cylinder : {length : 4000000,topRadius : 100000, bottomRadius : 100000,material : Cesium.Color.BROWN.withAlpha(0.5),}});

e2.PNG

これをアニメーションみたいな動かせたら面白い
ここでドキュメントのアニメーションを見るとガッカリするので見ないこと!

本題

アニメーション風にオブジェクトを追加したい
本当はczmlを使うらしい データを作るのが面倒そう
せや!1秒毎に呼び出せばいいや(´・_・`)
データはどうしようかな・・・Apacheのアクセスログ使ったろ

準備

コード

<!DOCTYPE html>
<html lang="jp">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
  <title>mapping</title>
  <script src="Build/Cesium/Cesium.js"></script>
  <style>
      @import url(Build/Cesium/Widgets/widgets.css);
      @import url(mapping.css);
      html, body, #cesiumContainer {
          width: 100%; height: 100%; margin: 0; padding: 0; overflow: hidden;
      }
  </style>
</head>
<body>
  <div id="buttonContainer">
  <input type="number" name="jikan" size=3 id="jikan" value="1000"  step="10" min="1" max="10000">
  <button onclick="start_animation()" class="cesium-button">Start Animation</button>
  </div>
  <div id="cesiumContainer"></div>
  <script>
//cesium
var viewer = new Cesium.Viewer('cesiumContainer' , {navigationHelpButton: true, animation: false, timeline: false, infoBox: false, fullscreenButton: true,});
var defLen = 10000;

function start_animation() {
    var cc_cnt = {}
    loopSleep(cc_list.length-1, document.getElementById ('jikan').value, function(i) {
        try {
            var cc_s = new String(cc_list[i]).split(',');
            console.log(cc_s);
            for (var i in cc_s) {
                var cc = cc_s[i];
                var c_code = wl[cc_s[i]].split(',');
                var lat = c_code[1];
                var lon = c_code[0];
                console.log(lat + "," + lon);
                if (cc in cc_cnt) {
                    tl = cc_cnt[cc] + defLen;
                    cc_cnt[cc] = tl;
                } else {
                    cc_cnt[cc] = defLen;
                }
                var center = cc_cnt[cc];
                var len = center * 2;
                ent = {id : cc,position: Cesium.Cartesian3.fromDegrees(lat, lon, center),cylinder : {length : len,topRadius : 100000, bottomRadius : 100000,material : Cesium.Color.BROWN.withAlpha(0.5),}}
                try {
                    viewer.entities.add(ent);
                }catch(e){
                    et = viewer.entities.getById(cc);
                    viewer.entities.remove(et);
                    viewer.entities.add(ent);
                }
            }
        }catch(e){}
    });
}

function loopSleep(_loopLimit,_interval, _mainFunc) {
    var loopLimit = _loopLimit;
    var interval = _interval;
    var mainFunc = _mainFunc;
    var i = 0;
    var loopFunc = function () {
        var result = mainFunc(i);
        if (result === false) {return;}
        i = i + 1;
        if (i < loopLimit) {setTimeout(loopFunc, interval);}
    }
    loopFunc();
}

//load cc data
var cc_list = []
function load_cc(file_name){
    var req = new XMLHttpRequest();
    req.open("get", file_name, true);
    req.send(null);
    req.onload = function(){
        var tmp = req.responseText.split("\n");
        for (var i = 0; i < tmp.length; i++) {
            cc_list[i] = tmp[i].split(',');
            //console.log(tmp[i].split(',')[2]);
        }
    }
}
load_cc('demo.csv')

//load location data
var wl = {}
function load_wl(file_name) {
    var req = new XMLHttpRequest();
    req.open("get", file_name, true);
    req.send(null);
    req.onload = function() {
        var tmp = req.responseText.split("\n");
        for (var i = 0; i < tmp.length; i++) {
            var ch = tmp[i].split(",");
            wl[ch[0]] = ch[1] + "," + ch[2];
        }
    }
}
load_wl('world_location.csv');

  </script>
</body>
</html>

左上のStart Animationのボタンを押すとCSVを左の数値ミリ秒毎読み込み累積するように表示する
e5.gif

地球儀を回転させたい

ほぼこぴぺ以下を追加

  <div id="buttonContainer">
  <input type="number" name="sokudo" size=3 id="sokudo" value="0.5" step="0.1" min="0.1" max="10">
  <button onclick="start_rotation()" class="cesium-button">Start Rotation</button>
  <button onclick="stop_rotation()" class="cesium-button">Stop Rotation</button>
  <br>
  <input type="number" name="jikan" size=3 id="jikan" value="1000"  step="10" min="1" max="10000">
  <button onclick="start_animation()" class="cesium-button">Start Animation</button>
  </div>

var camera = viewer.camera;
var clock = viewer.clock;
var eventHelper = new Cesium.EventHelper();
var removeCallback;
var rot_flag = false;
var defLen = 10000;

function start_rotation() {
    if (!rot_flag) {
        rot_flag = true;
        removeCallback = eventHelper.add(clock.onTick, onTick);
    }
}

function stop_rotation() {
    if (rot_flag) {
        removeCallback();
        rot_flag = false;
    }
}

function onTick() {
    var horizontalDegrees = document.getElementById ('sokudo').value;
    var viewRect = camera.computeViewRectangle();
    if (Cesium.defined(viewRect)) {
        horizontalDegrees *= Cesium.Math.toDegrees(viewRect.east - viewRect.west) / 360.0;
    }
    camera.rotateRight(Cesium.Math.toRadians(horizontalDegrees));
}

Start Rotationで回転Stop Rotationで停止
左の数値で回転速度の調整
e6.gif

以上です。すぐに遊べるようGitに一式うp

余談

みんなgifアニメーションってどうやってるんだろう・・・って思って自分なりの確立したやり方書きます
環境はwindows10

  • win + g

無1.png
を表示させ、はい、これを・・・にチェックを入れる

  • 再びwin + g

無2.png
で赤いボタンを押して録画開始

  • 必要に応じてAviUtlなど使って画面を切り取る
  • mp4ファイルをgifに変換する
  • 最初はConvertioを使って20MB程度にしてアップしたが再生されず
  • Free Video to GIF Converterを使い画像サイズを小さくしたり、不要な画像を削除したりして作成しました