cesium-examples/map/2d/build/google-map-flashMarker.js

395 lines
12 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
typeof define === 'function' && define.amd ? define(factory) :
(global.FlashMarker = factory());
}(this, (function () { 'use strict';
function CanvasLayer(opt_options) {
this.isAdded_ = false;
this.isAnimated_ = false;
this.paneName_ = CanvasLayer.DEFAULT_PANE_NAME_;
this.updateHandler_ = null;
this.resizeHandler_ = null;
this.topLeft_ = null;
this.centerListener_ = null;
this.resizeListener_ = null;
this.needsResize_ = true;
this.requestAnimationFrameId_ = null;
var canvas = document.createElement('canvas');
canvas.style.position = 'absolute';
canvas.style.top = 0;
canvas.style.left = 0;
canvas.style.pointerEvents = 'none';
this.canvas = canvas;
this.canvasCssWidth_ = 300;
this.canvasCssHeight_ = 150;
this.resolutionScale_ = 1;
function simpleBindShim(thisArg, func) {
return function () {
func.apply(thisArg);
};
}
this.repositionFunction_ = simpleBindShim(this, this.repositionCanvas_);
this.resizeFunction_ = simpleBindShim(this, this.resize_);
this.requestUpdateFunction_ = simpleBindShim(this, this.update_);
if (opt_options) {
this.setOptions(opt_options);
}
}
var global = typeof window === 'undefined' ? {} : window;
if (global.google && global.google.maps) {
CanvasLayer.prototype = new google.maps.OverlayView();
CanvasLayer.DEFAULT_PANE_NAME_ = 'overlayLayer';
CanvasLayer.CSS_TRANSFORM_ = function () {
var div = document.createElement('div');
var transformProps = ['transform', 'WebkitTransform', 'MozTransform', 'OTransform', 'msTransform'];
for (var i = 0; i < transformProps.length; i++) {
var prop = transformProps[i];
if (div.style[prop] !== undefined) {
return prop;
}
}
return transformProps[0];
}();
CanvasLayer.prototype.requestAnimFrame_ = global.requestAnimationFrame || global.webkitRequestAnimationFrame || global.mozRequestAnimationFrame || global.oRequestAnimationFrame || global.msRequestAnimationFrame || function (callback) {
return global.setTimeout(callback, 1000 / 60);
};
CanvasLayer.prototype.cancelAnimFrame_ = global.cancelAnimationFrame || global.webkitCancelAnimationFrame || global.mozCancelAnimationFrame || global.oCancelAnimationFrame || global.msCancelAnimationFrame || function (requestId) {};
CanvasLayer.prototype.setOptions = function (options) {
if (options.animate !== undefined) {
this.setAnimate(options.animate);
}
if (options.paneName !== undefined) {
this.setPaneName(options.paneName);
}
if (options.updateHandler !== undefined) {
this.setUpdateHandler(options.updateHandler);
}
if (options.resizeHandler !== undefined) {
this.setResizeHandler(options.resizeHandler);
}
if (options.resolutionScale !== undefined) {
this.setResolutionScale(options.resolutionScale);
}
if (options.map !== undefined) {
this.setMap(options.map);
}
};
CanvasLayer.prototype.setAnimate = function (animate) {
this.isAnimated_ = !!animate;
if (this.isAnimated_) {
this.scheduleUpdate();
}
};
CanvasLayer.prototype.isAnimated = function () {
return this.isAnimated_;
};
CanvasLayer.prototype.setPaneName = function (paneName) {
this.paneName_ = paneName;
this.setPane_();
};
CanvasLayer.prototype.getPaneName = function () {
return this.paneName_;
};
CanvasLayer.prototype.setPane_ = function () {
if (!this.isAdded_) {
return;
}
// onAdd has been called, so panes can be used
var panes = this.getPanes();
if (!panes[this.paneName_]) {
throw new Error('"' + this.paneName_ + '" is not a valid MapPane name.');
}
panes[this.paneName_].appendChild(this.canvas);
};
CanvasLayer.prototype.setResizeHandler = function (opt_resizeHandler) {
this.resizeHandler_ = opt_resizeHandler;
};
CanvasLayer.prototype.setResolutionScale = function (scale) {
if (typeof scale === 'number') {
this.resolutionScale_ = scale;
this.resize_();
}
};
CanvasLayer.prototype.setUpdateHandler = function (opt_updateHandler) {
this.updateHandler_ = opt_updateHandler;
};
CanvasLayer.prototype.onAdd = function () {
if (this.isAdded_) {
return;
}
this.isAdded_ = true;
this.setPane_();
this.resizeListener_ = google.maps.event.addListener(this.getMap(), 'resize', this.resizeFunction_);
this.centerListener_ = google.maps.event.addListener(this.getMap(), 'center_changed', this.repositionFunction_);
this.resize_();
this.repositionCanvas_();
};
CanvasLayer.prototype.onRemove = function () {
if (!this.isAdded_) {
return;
}
this.isAdded_ = false;
this.topLeft_ = null;
// remove canvas and listeners for pan and resize from map
this.canvas.parentElement.removeChild(this.canvas);
if (this.centerListener_) {
google.maps.event.removeListener(this.centerListener_);
this.centerListener_ = null;
}
if (this.resizeListener_) {
google.maps.event.removeListener(this.resizeListener_);
this.resizeListener_ = null;
}
// cease canvas update callbacks
if (this.requestAnimationFrameId_) {
this.cancelAnimFrame_.call(global, this.requestAnimationFrameId_);
this.requestAnimationFrameId_ = null;
}
};
CanvasLayer.prototype.resize_ = function () {
if (!this.isAdded_) {
return;
}
var map = this.getMap();
var mapWidth = map.getDiv().offsetWidth;
var mapHeight = map.getDiv().offsetHeight;
var newWidth = mapWidth * this.resolutionScale_;
var newHeight = mapHeight * this.resolutionScale_;
var oldWidth = this.canvas.width;
var oldHeight = this.canvas.height;
// resizing may allocate a new back buffer, so do so conservatively
if (oldWidth !== newWidth || oldHeight !== newHeight) {
this.canvas.width = newWidth;
this.canvas.height = newHeight;
this.needsResize_ = true;
this.scheduleUpdate();
}
// reset styling if new sizes don't match; resize of data not needed
if (this.canvasCssWidth_ !== mapWidth || this.canvasCssHeight_ !== mapHeight) {
this.canvasCssWidth_ = mapWidth;
this.canvasCssHeight_ = mapHeight;
this.canvas.style.width = mapWidth + 'px';
this.canvas.style.height = mapHeight + 'px';
}
};
CanvasLayer.prototype.draw = function () {
this.repositionCanvas_();
};
CanvasLayer.prototype.repositionCanvas_ = function () {
var map = this.getMap();
// topLeft can't be calculated from map.getBounds(), because bounds are
// clamped to -180 and 180 when completely zoomed out. Instead, calculate
// left as an offset from the center, which is an unwrapped LatLng.
var top = map.getBounds().getNorthEast().lat();
var center = map.getCenter();
var scale = Math.pow(2, map.getZoom());
var left = center.lng() - this.canvasCssWidth_ * 180 / (256 * scale);
this.topLeft_ = new google.maps.LatLng(top, left);
// Canvas position relative to draggable map's container depends on
// overlayView's projection, not the map's. Have to use the center of the
// map for this, not the top left, for the same reason as above.
var projection = this.getProjection();
var divCenter = projection.fromLatLngToDivPixel(center);
var offsetX = -Math.round(this.canvasCssWidth_ / 2 - divCenter.x);
var offsetY = -Math.round(this.canvasCssHeight_ / 2 - divCenter.y);
this.canvas.style[CanvasLayer.CSS_TRANSFORM_] = 'translate(' + offsetX + 'px,' + offsetY + 'px)';
this.scheduleUpdate();
};
CanvasLayer.prototype.update_ = function () {
this.requestAnimationFrameId_ = null;
if (!this.isAdded_) {
return;
}
if (this.isAnimated_) {
this.scheduleUpdate();
}
if (this.needsResize_ && this.resizeHandler_) {
this.needsResize_ = false;
this.resizeHandler_();
}
if (this.updateHandler_) {
this.updateHandler_();
}
};
CanvasLayer.prototype.getTopLeft = function () {
return this.topLeft_;
};
CanvasLayer.prototype.scheduleUpdate = function () {
if (this.isAdded_ && !this.requestAnimationFrameId_) {
this.requestAnimationFrameId_ = this.requestAnimFrame_.call(global, this.requestUpdateFunction_);
}
};
}
function Marker(opts) {
this.city = opts.name;
this.location = new google.maps.LatLng(opts.lnglat[1], opts.lnglat[0]);
this.color = opts.color;
this.type = opts.type || 'circle';
this.speed = opts.speed || 0.15;
this.size = 0;
this.max = opts.max || 20;
}
Marker.prototype.draw = function (context) {
context.save();
context.beginPath();
switch (this.type) {
case 'circle':
this._drawCircle(context);
break;
case 'ellipse':
this._drawEllipse(context);
break;
default:
break;
}
context.closePath();
context.restore();
this.size += this.speed;
if (this.size > this.max) {
this.size = 0;
}
};
Marker.prototype._drawCircle = function (context) {
var mapProjection = map.getProjection();
var pixel = this.pixel || mapProjection.fromLatLngToPoint(this.location);
context.strokeStyle = this.color;
context.moveTo(pixel.x + pixel.size, pixel.y);
context.arc(pixel.x, pixel.y, this.size, 0, Math.PI * 2);
context.stroke();
};
Marker.prototype._drawEllipse = function (context) {
var mapProjection = map.getProjection();
var pixel = this.pixel || mapProjection.fromLatLngToPoint(this.location);
var x = pixel.x,
y = pixel.y,
w = this.size,
h = this.size / 2,
kappa = 0.5522848,
// control point offset horizontal
ox = w / 2 * kappa,
// control point offset vertical
oy = h / 2 * kappa,
// x-start
xs = x - w / 2,
// y-start
ys = y - h / 2,
// x-end
xe = x + w / 2,
// y-end
ye = y + h / 2;
context.strokeStyle = this.color;
context.moveTo(xs, y);
context.bezierCurveTo(xs, y - oy, x - ox, ys, x, ys);
context.bezierCurveTo(x + ox, ys, xe, y - oy, xe, y);
context.bezierCurveTo(xe, y + oy, x + ox, ye, x, ye);
context.bezierCurveTo(x - ox, ye, xs, y + oy, xs, y);
context.stroke();
};
function FlashMarker(map, dataSet) {
var animationLayer = null,
animationFlag = true,
markers = [];
var addMarker = function addMarker() {
if (markers.length > 0) return;
markers = [];
for (var i = 0; i < dataSet.length; i++) {
markers.push(new Marker(dataSet[i]));
}
};
//上层canvas渲染动画效果
var render = function render() {
var animationCtx = animationLayer.canvas.getContext('2d');
if (!animationCtx) {
return;
}
if (!animationFlag) {
animationCtx.clearRect(0, 0, animationCtx.canvas.width, animationCtx.canvas.height);
return;
}
addMarker();
animationCtx.fillStyle = 'rgba(0,0,0,.95)';
var prev = animationCtx.globalCompositeOperation;
animationCtx.globalCompositeOperation = 'destination-in';
animationCtx.fillRect(0, 0, animationCtx.canvas.width, animationCtx.canvas.height);
animationCtx.globalCompositeOperation = prev;
for (var i = 0; i < markers.length; i++) {
var marker = markers[i];
marker.draw(animationCtx);
}
};
//初始化
var init = function init() {
animationLayer = new CanvasLayer({
map: map,
updateHandler: render
});
// mouseInteract();
(function drawFrame() {
requestAnimationFrame(drawFrame);
render();
})();
};
init();
}
return FlashMarker;
})));