You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

365 lines
9.8 KiB
JavaScript

/**
* @fileoverview 视角轨迹动画
* 主入口类是<a href="example/index.html">TrackAnimation</a>
* 基于Baidu Map API GL 1.0
*
* @author Baidu Map Api Group
* @version 1.0
*/
/**
* @namespace BMapGL的所有library类均放在BMapGLLib命名空间下
*/
var BMapGLLib = window.BMapGLLib = BMapGLLib || {};
(function () {
var DELTA_ZOOM = 1;
var DEFAULT_TILT = 55;
var DEFAULT_HEADING = 0;
var DEFAULT_DURATION = 10000;
var DEFAULT_DELAY = 0;
var DEFAULT_OVERALLVIEW = true;
var PLAY = 1;
var CANCEL = 2;
var PAUSE = 3;
var start = 0;
var TrackAnimation =
/**
* 构造函数
*
* @param {BMapGL.Map} map 地图实例
* @param {Polyline} polyline 折线实例
* @param {TrackAnimationOptions} opts 配置
* {
* zoom
* tilt
* duration
* delay
* overallView
* }
*/
BMapGLLib.TrackAnimation = function (map, polyline, opts) {
this._map = map;
this._polyline = polyline;
this._totalPath = polyline.getPath();
this._overallView = map.getViewport(polyline.getPath());
this._status = CANCEL;
this._opts = {
zoom: this._getZoom(),
tilt: DEFAULT_TILT,
heading: DEFAULT_HEADING,
duration: DEFAULT_DURATION,
delay: DEFAULT_DELAY,
overallView: DEFAULT_OVERALLVIEW
};
this._initOpts(opts);
this._expandPath = this._addPath(polyline.getPath());
// window.requestAnimationFrame(this._step);
// 暂停时累计经历的时间
this._pauseTime = 0;
};
/**
* 获取轨迹播放合适的缩放级别
* @return {number} zoom
*/
TrackAnimation.prototype._getZoom = function () {
return Math.min(this._overallView.zoom + DELTA_ZOOM, this._map.getMaxZoom());
};
/**
* 根据当前配置更新动画参数
*/
TrackAnimation.prototype._updateAniParams = function () {
this._updatePathAni();
this._updateViewAni();
this._polyline.setPath(this._expandPath.slice(0, 1));
};
/**
* 轨迹动画
*/
TrackAnimation.prototype._updatePathAni = function () {
this._expandPath = this._addPath(this._totalPath);
};
/**
* 视角动画
*/
TrackAnimation.prototype._updateViewAni = function () {
this._overallView = this._map.getViewport(this._totalPath);
var length = this._totalPath.length;
var keyFrames = [];
var duration = this._opts.overallView ? this._opts.duration + 2000 : this._opts.duration;
for (var i = 0; i < length; i++) {
var item = this._totalPath[i];
var percent = this._pathPercents[i] * (this._opts.duration / duration)
keyFrames.push({
center: new BMapGL.Point(item.lng, item.lat),
zoom: this._opts.zoom,
tilt: i === 0 ? 0 : this._opts.tilt,
heading: i === 0 ? 0 : this._opts.heading,
percentage: percent
});
}
if (this._opts.overallView) {
keyFrames.push({
center: new BMapGL.Point(this._overallView.center.lng, this._overallView.center.lat),
zoom: this._overallView.zoom - DELTA_ZOOM,
tilt: 0,
heading: 0,
percentage: 1
});
}
var opts = {
duration: duration,
delay: 0,
interation: 1
};
this._viewAni = new BMapGL.ViewAnimation(keyFrames, opts);
};
/**
* 扩充Path
* @param {Array} path 原始路径
*/
TrackAnimation.prototype._addPath = function (path) {
var TOTAL_NUM = this._opts.duration / 10;
var length = path.length;
var totalDistance = 0;
var distances = [];
var expandPath = [];
for (var i = 1; i < length; i++) {
var distance = this._map.getDistance(path[i - 1], path[i]);
distances.push(distance);
totalDistance += distance;
}
var percents = [0];
for (var i = 1; i < length; i++) {
var percent = (distances[i - 1] / totalDistance).toFixed(2);
// percents.push(percent);
percents[i] = percents[i - 1] + parseFloat(percent, 10);
expandPath = expandPath.concat(this._getPath(path[i - 1], path[i], percent * TOTAL_NUM));
}
this._pathPercents = percents;
return expandPath;
};
/**
* 获取差值Path
* @param {Object} start 起始点
* @param {Object} end 终止点
* @param {number} num 差值点数量
*/
TrackAnimation.prototype._getPath = function (start, end, num) {
var result = [];
if (num === 0) {
return result;
}
for (var i = 0; i <= num; i++) {
var point = new BMapGL.Point(
(end.lng - start.lng) / num * i + start.lng,
(end.lat - start.lat) / num * i + start.lat
);
result.push(point);
}
return result;
}
/**
* 初始化配置参数
* @param {Object} opts 配置
*/
TrackAnimation.prototype._initOpts = function (opts) {
for (var p in opts) {
if (opts.hasOwnProperty(p)) {
this._opts[p] = opts[p];
}
}
};
/**
* 启动动画
*/
TrackAnimation.prototype.start = function () {
var me = this;
setTimeout(function () {
me._updateAniParams();
me._map.removeOverlay(me._polyline);
me._map.addOverlay(me._polyline);
me._status = PLAY;
me._step(performance.now());
me._map.startViewAnimation(me._viewAni);
}, this._opts.delay);
};
/**
* 终止动画
*/
TrackAnimation.prototype.cancel = function () {
this._clearRAF();
this._status = CANCEL;
start = 0;
this._pauseTime = 0;
this._map.cancelViewAnimation(this._viewAni);
this._map.removeOverlay(this._polyline);
};
/**
* 暂停动画
*/
TrackAnimation.prototype.pause = function () {
if (this._status === PLAY) {
this._clearRAF();
this._map.pauseViewAnimation(this._viewAni);
this._status = PAUSE;
this._isPausing = performance.now();
}
};
/**
* 继续动画
*/
TrackAnimation.prototype.continue = function () {
if (this._status === PAUSE) {
this._pauseTime += performance.now() - this._isPausing;
this._isPausing = undefined;
this._status = PLAY;
this._step(performance.now());
this._map.continueViewAnimation(this._viewAni);
}
};
/**
* rAF动画函数
* @param {number} timestamp 时间戳
*/
TrackAnimation.prototype._step = function (timestamp) {
if (this._status === CANCEL) {
start = 0;
return;
}
if (!start) {
start = timestamp;
}
timestamp = timestamp - this._pauseTime;
var percent = (timestamp - start) / this._opts.duration;
var end = Math.round(this._expandPath.length * percent);
this._polyline.setPath(this._expandPath.slice(0, end));
if (timestamp < start + this._opts.duration) {
this._timer = window.requestAnimationFrame(this._step.bind(this));
} else {
start = 0;
this._status = CANCEL;
this._pauseTime = 0;
}
};
/**
* 清除rAF动画函数
*/
TrackAnimation.prototype._clearRAF = function () {
if (this._timer) {
window.cancelAnimationFrame(this._timer);
}
};
/**
* 设置缩放级别
* @param {number} zoom 缩放级别
*/
TrackAnimation.prototype.setZoom = function (zoom) {
this._opts.zoom = zoom;
};
/**
* 获取缩放级别
* @return {number} zoom
*/
TrackAnimation.prototype.getZoom = function (zoom) {
return this._opts.zoom;
};
/**
* 设置角度
* @param {number} tilt 角度
*/
TrackAnimation.prototype.setTilt = function (tilt) {
this._opts.tilt = tilt;
};
/**
* 获取角度
* @return {number} tilt
*/
TrackAnimation.prototype.getTilt = function (tilt) {
return this._opts.tilt;
};
/**
* 设置延迟
* @param {number} delay 延迟
*/
TrackAnimation.prototype.setDelay = function (delay) {
this._opts.delay = delay;
};
/**
* 获取延迟
* @return {number} delay
*/
TrackAnimation.prototype.getDelay = function (delay) {
return this._opts.delay;
};
/**
* 设置持续事件
* @param {number} duration 持续事件
*/
TrackAnimation.prototype.setDuration = function (duration) {
this._opts.duration = duration;
};
/**
* 获取持续事件
* @return {number} duration
*/
TrackAnimation.prototype.getDuration = function (duration) {
return this._opts.duration;
};
/**
* 开启总览
*/
TrackAnimation.prototype.enableOverallView = function () {
this._opts.overallView = true;
};
/**
* 关闭总览
*/
TrackAnimation.prototype.disableOverallView = function () {
this._opts.overallView = false;
};
/**
* 更新折线
* @param {Object} polyline 更新
*/
TrackAnimation.prototype.setPolyline = function (polyline) {
this._polyline = polyline;
this._totalPath = polyline.getPath();
};
/**
* 获取折线
* @return {Object} polyline
*/
TrackAnimation.prototype.getPolyline = function () {
return this._polyline;
};
})();