UNPKG

mapv

Version:

a library of geography visualization

296 lines (238 loc) 8.73 kB
/** * @author kyle / http://nikai.us/ */ import BaseLayer from "../BaseLayer"; import CanvasLayer from "./CanvasLayer"; import clear from "../../canvas/clear"; import DataSet from "../../data/DataSet"; import TWEEN from "../../utils/Tween"; class Layer extends BaseLayer{ constructor(map, dataSet, options) { super(map, dataSet, options); var self = this; var data = null; options = options || {}; this.clickEvent = this.clickEvent.bind(this); this.mousemoveEvent = this.mousemoveEvent.bind(this); this.tapEvent = this.tapEvent.bind(this); self.init(options); self.argCheck(options); self.transferToMercator(); var canvasLayer = this.canvasLayer = new CanvasLayer({ map: map, context: this.context, paneName: options.paneName, mixBlendMode: options.mixBlendMode, enableMassClear: options.enableMassClear, zIndex: options.zIndex, update: function() { self._canvasUpdate(); } }); dataSet.on('change', function() { self.transferToMercator(); canvasLayer.draw(); }); } clickEvent(e) { var pixel = e.pixel; super.clickEvent(pixel, e); } mousemoveEvent(e) { var pixel = e.pixel; super.mousemoveEvent(pixel, e); } tapEvent(e) { var pixel = e.pixel; super.tapEvent(pixel, e); } bindEvent(e) { this.unbindEvent(); var map = this.map; var timer = 0; var that = this; if (this.options.methods) { if (this.options.methods.click) { map.setDefaultCursor("default"); map.addEventListener('click', this.clickEvent); } if (this.options.methods.mousemove) { map.addEventListener('mousemove', this.mousemoveEvent); } if ("ontouchend" in window.document && this.options.methods.tap) { map.addEventListener('touchstart', function(e) { timer = new Date }); map.addEventListener('touchend', function(e) { if(new Date - timer < 300){ that.tapEvent(e) } }); } } } unbindEvent(e) { var map = this.map; if (this.options.methods) { if (this.options.methods.click) { map.removeEventListener('click', this.clickEvent); } if (this.options.methods.mousemove) { map.removeEventListener('mousemove', this.mousemoveEvent); } } } // 经纬度左边转换为墨卡托坐标 transferToMercator(dataSet) { if (!dataSet) { dataSet = this.dataSet; } var projection = this.map.getMapType().getProjection(); if (this.options.coordType !== 'bd09mc') { var data = dataSet.get(); data = dataSet.transferCoordinate(data, function(coordinates) { if (coordinates[0] < -180 || coordinates[0] > 180 || coordinates[1] < -90 || coordinates[1] > 90) { return coordinates; } else { var pixel = projection.lngLatToPoint({ lng: coordinates[0], lat: coordinates[1] }); return [pixel.x, pixel.y]; } }, 'coordinates', 'coordinates_mercator'); dataSet._set(data); } } getContext() { return this.canvasLayer.canvas.getContext(this.context); } _canvasUpdate(time) { if (!this.canvasLayer) { return; } var self = this; var animationOptions = self.options.animation; var map = this.canvasLayer._map; var zoomUnit = Math.pow(2, 18 - map.getZoom()); var projection = map.getMapType().getProjection(); var mcCenter = projection.lngLatToPoint(map.getCenter()); var nwMc = new BMap.Pixel(mcCenter.x - (map.getSize().width / 2) * zoomUnit, mcCenter.y + (map.getSize().height / 2) * zoomUnit); //左上角墨卡托坐标 var context = this.getContext(); if (self.isEnabledTime()) { if (time === undefined) { clear(context); return; } if (this.context == '2d') { context.save(); context.globalCompositeOperation = 'destination-out'; context.fillStyle = 'rgba(0, 0, 0, .1)'; context.fillRect(0, 0, context.canvas.width, context.canvas.height); context.restore(); } } else { clear(context); } if (this.context == '2d') { for (var key in self.options) { context[key] = self.options[key]; } } else { context.clear(context.COLOR_BUFFER_BIT); } if (self.options.minZoom && map.getZoom() < self.options.minZoom || self.options.maxZoom && map.getZoom() > self.options.maxZoom) { return; } var scale = 1; if (this.context != '2d') { scale = this.canvasLayer.devicePixelRatio; } var dataGetOptions = { fromColumn: self.options.coordType == 'bd09mc' ? 'coordinates' : 'coordinates_mercator', transferCoordinate: function(coordinate) { var x = (coordinate[0] - nwMc.x) / zoomUnit * scale; var y = (nwMc.y - coordinate[1]) / zoomUnit * scale; return [x, y]; } } if (time !== undefined) { dataGetOptions.filter = function(item) { var trails = animationOptions.trails || 10; if (time && item.time > (time - trails) && item.time < time) { return true; } else { return false; } } } // get data from data set var data; if (self.options.draw === 'cluster') { var bounds = this.map.getBounds(); var ne = bounds.getNorthEast(); var sw = bounds.getSouthWest(); var clusterData = this.supercluster.getClusters([sw.lng, sw.lat, ne.lng, ne.lat], this.getZoom()); this.clusterDataSet.set(clusterData); this.transferToMercator(this.clusterDataSet); data = this.clusterDataSet.get(dataGetOptions); } else { data = self.dataSet.get(dataGetOptions); } this.processData(data); var nwPixel = map.pointToPixel(new BMap.Point(0, 0)); if (self.options.unit == 'm') { if (self.options.size) { self.options._size = self.options.size / zoomUnit; } if (self.options.width) { self.options._width = self.options.width / zoomUnit; } if (self.options.height) { self.options._height = self.options.height / zoomUnit; } } else { self.options._size = self.options.size; self.options._height = self.options.height; self.options._width = self.options.width; } this.drawContext(context, data, self.options, nwPixel); //console.timeEnd('draw'); //console.timeEnd('update') self.options.updateCallback && self.options.updateCallback(time); } init(options) { var self = this; self.options = options; this.initDataRange(options); this.context = self.options.context || '2d'; if (self.options.zIndex) { this.canvasLayer && this.canvasLayer.setZIndex(self.options.zIndex); } if (self.options.max) { this.intensity.setMax(self.options.max); } if (self.options.min) { this.intensity.setMin(self.options.min); } this.initAnimator(); this.bindEvent(); } getZoom() { return this.map.getZoom(); } addAnimatorEvent() { this.map.addEventListener('movestart', this.animatorMovestartEvent.bind(this)); this.map.addEventListener('moveend', this.animatorMoveendEvent.bind(this)); } show() { this.map.addOverlay(this.canvasLayer); } hide() { this.map.removeOverlay(this.canvasLayer); } draw() { this.canvasLayer.draw(); } } export default Layer;