こちら<\/A> は requestAnimationFrame のクールなチュートリアルです。<\/P><\/P>
3Dマップを扱うときはアニメーションを扱っています。詳細を気にする必要はありませんが、3Dマップと同期して何かをしたい場合は requestAnimationFrame に慣れておくべきです。<\/P>
<\/P>
Scheduler はこれを助けてくれます。<\/P>
<\/P>
私の古いサンプルではまだ setInterval<\/SPAN> に頼っていたので、ここではすべて Scheduler で行う方法を示します。<\/P><\/P>require([\n "esri\/[0mMap",
"esri\/[0mviews\/[0mSceneView",
"esri\/[0mcore\/[0mwatchUtils",
"esri\/[0mcore\/[0mScheduler",
"dojo\/[0mon",
\/\/_ Widget items
'dojo\/_base/declare',
'dojo/dom-class',
'dijit/_WidgetBase',
'dijit/_TemplatedMixin',
"dojo/domReady!"
], function (Map, SceneView, watchUtils, Scheduler, on, declare, domClass, _WidgetBase, _TemplatedMixin){
var template = '' +
'<div>'+
' <input class="camera-slider" data-dojo-attach-point="slider"'+
' type="range" min="1" max="1" step="1" value="1">'+
' <a href="javascript:void(0)" data-dojo-attach-point="reverseBtn"'+
' data-dojo-attach-event="click:playReverse"'+
' title="Play views in reverse"'+
' class="btn btn-info btn-fab btn-raised mdi-av-fast-rewind"></a>'+
' <a href="javascript:void(0)" data-dojo-attach-point="playBtn"'+
' data-dojo-attach-event="click:play"'+
' title="Play views"'+
' class="btn btn-info btn-fab btn-raised mdi-av-play-arrow"></a>'+
' <a href="javascript:void(0)" data-dojo-attach-point="stopBtn"'+
' data-dojo-attach-event="click:stop"'+
' title="Pause recording view"'+
' class="btn btn-info btn-fab btn-raised mdi-av-pause"></a>'+
'</div>';
var CameraRecorder = declare([_WidgetBase, _TemplatedMixin], {
templateString: template,
constructor: function() {
this.cameras = [null];
this.timer = null;
this.watcher = null;
this.handler = null;
this.isPlaying = false;
},
clear: function() {
 .&nbpsp;if (this.watcher) {
 .&nbpsp.&nbpsp.&nbpspthis.watcher.remove();
.&nbpsp.&nbpsp}
.&nbpsp.&nbpspif (this.handler) {
.&nbpsp.&nbpsp.&nbpspthis.handler.remove();
.&nbpsp.&nbpsp}
.&nbpsp.&nbpspif (this.timer) {
.&nbpsp.&nbpsp.&nbpspthis.timer.remove();
.&nbpsp.&nbpsp}
.&nbpsp.&nbpspthis.recordStart();
},
clear: function() {
if (this.watcher) {
this.watcher.remove();
}
if (this.handler) {
this.handler.remove();
}
if (this.timer) {
this.timer.remove();
}
this.recordStart();
},
scheduleStart: function() {
if (this.isPlaying || this.isPaused) {
return;
}
this.timer = Scheduler.schedule(function() {
this._cameraWatch();
this._sliderWatch();
}.bind(this));
},
scheduleStart: function() {
if (this.isPlaying || this.isPaused) {
return;
}
this.timer = Scheduler.schedule(function() {
this._cameraWatch();
this._sliderWatch();
}.bind(this));
},play: function() {\n if (this.isPlaying) {\n return;\n }\n domClass.toggle(this.playBtn, 'btn-info btn-success');
scheduleStart: function() {
scheduleStart: function() {
scheduleStart: function() {
scheduleStart: function() {
scheduleStart: function() {}}}}}}}}}}}} }
}
}.bind(this)});
}
});
var map = new Map({
basemap: "dark-gray"
});
var view = new SceneView({
container: "viewDiv",
map: map,
scale: 240000000
});
var camRecorder = new CameraRecorder(
{ view: view }, document.getElementById('recorder')
);
view.then(function() {
camRecorder.recordStart();
});
});
ここで私がやっていることは二つあります。
ここではScheduler.schedule()を使って、次のフレームでいくつかのメソッドをスケジュールしています。これらのメソッドはカメラやスライダーの変更を記録してビューを保存するためのものです。
そして、記録されたカメラビューを順番に再生するときに、Scheduler.addFrameTask({update: function(){}})を使って、ビューが更新される(基本的にレンダリングされる)ときに関数を追加しています。addFrameTaskには内部的なライフサイクルの仕組みがありますが、ここではざっくりとupdateにフックするものとして扱っています。
このようにアニメーションに関わる操作を同期しないと、マップがカクついてしまいます。このアプリの最初のドラフトはプロパティの変化を監視するだけでしたが、それだとアプリが不安定になりました。今はずっとスムーズになっています。
こちらで