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

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

/**
* @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;
};
})();