cesium-examples/map/2d/build/baidu-map-lineGradient.js

541 lines
17 KiB
JavaScript
Raw Permalink Normal View History

(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
typeof define === 'function' && define.amd ? define(factory) :
(global.LineGradient = factory());
}(this, (function () { 'use strict';
/**
* @author https://github.com/chengquan223
* @Date 2017-02-27
* */
function CanvasLayer(options) {
this.options = options || {};
this.paneName = this.options.paneName || 'labelPane';
this.zIndex = this.options.zIndex || 0;
this._map = options.map;
this._lastDrawTime = null;
this.show();
}
CanvasLayer.prototype = new BMap.Overlay();
CanvasLayer.prototype.initialize = function (map) {
this._map = map;
var canvas = this.canvas = document.createElement('canvas');
var ctx = this.ctx = this.canvas.getContext('2d');
canvas.style.cssText = 'position:absolute;' + 'left:0;' + 'top:0;' + 'z-index:' + this.zIndex + ';';
this.adjustSize();
this.adjustRatio(ctx);
map.getPanes()[this.paneName].appendChild(canvas);
var that = this;
map.addEventListener('resize', function () {
that.adjustSize();
that._draw();
});
return this.canvas;
};
CanvasLayer.prototype.adjustSize = function () {
var size = this._map.getSize();
var canvas = this.canvas;
canvas.width = size.width;
canvas.height = size.height;
canvas.style.width = canvas.width + 'px';
canvas.style.height = canvas.height + 'px';
};
CanvasLayer.prototype.adjustRatio = function (ctx) {
var backingStore = ctx.backingStorePixelRatio || ctx.webkitBackingStorePixelRatio || ctx.mozBackingStorePixelRatio || ctx.msBackingStorePixelRatio || ctx.oBackingStorePixelRatio || ctx.backingStorePixelRatio || 1;
var pixelRatio = (window.devicePixelRatio || 1) / backingStore;
var canvasWidth = ctx.canvas.width;
var canvasHeight = ctx.canvas.height;
ctx.canvas.width = canvasWidth * pixelRatio;
ctx.canvas.height = canvasHeight * pixelRatio;
ctx.canvas.style.width = canvasWidth + 'px';
ctx.canvas.style.height = canvasHeight + 'px';
// console.log(ctx.canvas.height, canvasHeight);
ctx.scale(pixelRatio, pixelRatio);
};
CanvasLayer.prototype.draw = function () {
var self = this;
var args = arguments;
clearTimeout(self.timeoutID);
self.timeoutID = setTimeout(function () {
self._draw();
}, 15);
};
CanvasLayer.prototype._draw = function () {
var map = this._map;
var size = map.getSize();
var center = map.getCenter();
if (center) {
var pixel = map.pointToOverlayPixel(center);
this.canvas.style.left = pixel.x - size.width / 2 + 'px';
this.canvas.style.top = pixel.y - size.height / 2 + 'px';
this.dispatchEvent('draw');
this.options.update && this.options.update.call(this);
}
};
CanvasLayer.prototype.getContainer = function () {
return this.canvas;
};
CanvasLayer.prototype.show = function () {
if (!this.canvas) {
this._map.addOverlay(this);
}
this.canvas.style.display = 'block';
};
CanvasLayer.prototype.hide = function () {
this.canvas.style.display = 'none';
//this._map.removeOverlay(this);
};
CanvasLayer.prototype.setZIndex = function (zIndex) {
this.canvas.style.zIndex = zIndex;
};
CanvasLayer.prototype.getZIndex = function () {
return this.zIndex;
};
var tool = {
merge: function merge(settings, defaults) {
Object.keys(settings).forEach(function (key) {
defaults[key] = settings[key];
});
},
//计算两点间距离
getDistance: function getDistance(p1, p2) {
return Math.sqrt((p1[0] - p2[0]) * (p1[0] - p2[0]) + (p1[1] - p2[1]) * (p1[1] - p2[1]));
},
//判断点是否在线段上
containStroke: function containStroke(x0, y0, x1, y1, lineWidth, x, y) {
if (lineWidth === 0) {
return false;
}
var _l = lineWidth;
var _a = 0;
var _b = x0;
// Quick reject
if (y > y0 + _l && y > y1 + _l || y < y0 - _l && y < y1 - _l || x > x0 + _l && x > x1 + _l || x < x0 - _l && x < x1 - _l) {
return false;
}
if (x0 !== x1) {
_a = (y0 - y1) / (x0 - x1);
_b = (x0 * y1 - x1 * y0) / (x0 - x1);
} else {
return Math.abs(x - x0) <= _l / 2;
}
var tmp = _a * x - y + _b;
var _s = tmp * tmp / (_a * _a + 1);
return _s <= _l / 2 * _l / 2;
},
//是否在矩形内
isPointInRect: function isPointInRect(point, bound) {
var wn = bound.wn; //西北
var es = bound.es; //东南
return point.x >= wn.x && point.x <= es.x && point.y >= wn.y && point.y <= es.y;
},
//是否在圆内
isPointInCircle: function isPointInCircle(point, center, radius) {
var dis = this.getDistanceNew(point, center);
return dis <= radius;
},
//两点间距离
getDistanceNew: function getDistanceNew(point1, point2) {
return Math.sqrt(Math.pow(point1.x - point2.x, 2) + Math.pow(point1.y - point2.y, 2));
}
};
var global = typeof window === 'undefined' ? {} : window;
var requestAnimationFrame = global.requestAnimationFrame || global.mozRequestAnimationFrame || global.webkitRequestAnimationFrame || global.msRequestAnimationFrame || function (callback) {
return global.setTimeout(callback, 1000 / 60);
};
var LineGradient = function LineGradient(map, userOptions) {
var self = this;
self.map = map;
self.lines = [];
self.pixelList = [];
//默认参数
var options = {
//线条宽度
lineWidth: 1
};
//全局变量
var baseLayer = null,
animationLayer = null,
animationFlag = true,
width = map.getSize().width,
height = map.getSize().height;
function Line(opts) {
this.name = opts.name;
this.label = opts.label;
this.labelColor = opts.labelColor;
this.path = opts.path;
this.step = 0;
}
Line.prototype.getPointList = function () {
var points = [],
path = this.path;
if (path && path.length > 0) {
path.forEach(function (p) {
points.push({
code: p.code,
name: p.name,
location: p.location,
pixel: map.pointToPixel(p.location),
height: p.height,
value: p.value,
time: p.time,
color: p.color
});
});
}
return points;
};
Line.prototype.draw = function (context) {
var pointList = this.pixelList || this.getPointList();
for (var i = 0, len = pointList.length; i < len - 1; i++) {
context.save();
context.beginPath();
// context.lineCap = "round";
// context.lineJoin = "round";
context.lineWidth = options.lineWidth;
context.strokeStyle = pointList[i].color;
context.moveTo(pointList[i].pixel.x, pointList[i].pixel.y);
context.lineTo(pointList[i + 1].pixel.x, pointList[i + 1].pixel.y);
context.stroke();
context.closePath();
context.restore();
}
var lastpoint = pointList[pointList.length - 1];
context.font = 'bold 14px Arial';
context.textAlign = 'left';
context.textBaseline = 'middle';
context.fillStyle = this.labelColor;
context.fillText(this.label, lastpoint.pixel.x, lastpoint.pixel.y);
};
Line.prototype.drawMoveCircle = function (context) {
var pointList = this.pixelList || this.getPointList();
context.save();
context.fillStyle = '#fff';
context.shadowColor = '#fff';
context.shadowBlur = 5;
context.beginPath();
context.arc(pointList[this.step].pixel.x, pointList[this.step].pixel.y, 3, 0, Math.PI * 2, true);
context.fill();
context.closePath();
context.restore();
this.step += 1;
if (this.step >= pointList.length) {
this.step = 0;
}
};
Line.prototype.drawArrow = function (context, map) {
var pointList = this.pixelList || this.getPointList();
// for (var i = 0, len = pointList.length; i < len - 1; i++) {
if (this.step >= pointList.length - 1) {
this.step = 0;
}
context.beginPath();
// context.lineWidth = options.animateLineWidth;
context.lineWidth = 5;
context.strokeStyle = '#fff';
context.moveTo(pointList[this.step].pixel.x, pointList[this.step].pixel.y);
context.lineTo(pointList[this.step + 1].pixel.x, pointList[this.step + 1].pixel.y);
context.stroke();
context.save();
context.translate(pointList[this.step + 1].pixel.x, pointList[this.step + 1].pixel.y);
//我的箭头本垂直向下算出直线偏离Y的角然后旋转 ,rotate是顺时针旋转的所以加个负号
var ang = (pointList[this.step + 1].pixel.x - pointList[this.step].pixel.x) / (pointList[this.step + 1].pixel.y - pointList[this.step].pixel.y);
ang = Math.atan(ang);
pointList[this.step + 1].pixel.y - pointList[this.step].pixel.y >= 0 ? context.rotate(-ang) : context.rotate(Math.PI - ang); //加个180度反过来
context.lineTo(-6, -6);
context.lineTo(0, 6);
context.lineTo(6, -6);
context.lineTo(0, 0);
context.fillStyle = '#fff';
context.fill(); //箭头是个封闭图形
context.restore(); //用来恢复Canvas之前保存的状态,否则会影响后续绘制
this.step += 1;
// }
};
//底层canvas渲染标注线条
var brush = function brush() {
var baseCtx = baseLayer.canvas.getContext('2d');
if (!baseCtx) {
return;
}
addLine();
baseCtx.clearRect(0, 0, width, height);
self.pixelList = [];
self.lines.forEach(function (line) {
self.pixelList.push({
name: line.name,
label: line.label,
labelColor: line.labelColor,
data: line.getPointList()
});
line.draw(baseCtx);
});
};
//中层canvas渲染动画效果
var render = function render() {
var animationCtx = animationLayer.canvas.getContext('2d');
if (!animationCtx) {
return;
}
if (!animationFlag) {
animationCtx.clearRect(0, 0, width, height);
return;
}
animationCtx.fillStyle = 'rgba(0,0,0,.2)';
var prev = animationCtx.globalCompositeOperation;
animationCtx.globalCompositeOperation = 'destination-in';
animationCtx.fillRect(0, 0, width, height);
animationCtx.globalCompositeOperation = prev;
var lines = self.lines;
for (var i = 0; i < lines.length; i++) {
var line = lines[i];
// line.drawMoveCircle(animationCtx); //移动圆点
line.drawArrow(animationCtx); //画箭头
}
};
//鼠标事件
var mouseInteract = function mouseInteract() {
map.addEventListener('movestart', function () {
animationFlag = false;
});
map.addEventListener('moveend', function () {
animationFlag = true;
self.lines = []; //解决拖动后多余的小圆点bug没想明白暂时这样
});
map.addEventListener('zoomstart', function () {
animationFlag = false;
});
map.addEventListener('zoomend', function () {
animationFlag = true;
self.lines = [];
});
};
var addLine = function addLine() {
if (self.lines && self.lines.length > 0) return;
var dataset = options.data;
var legend = new Legend();
dataset.forEach(function (l, i) {
var line = new Line({
name: l.name,
label: l.label,
labelColor: l.labelColor,
path: []
});
l.data.forEach(function (p, j) {
line.path.push({
code: p.code,
name: p.name,
location: new BMap.Point(p.Longitude, p.Latitude),
height: p.height,
value: p.value,
time: p.time,
color: legend.getColor(p.value).color
});
});
self.lines.push(line);
});
};
var Legend = function Legend() {
var options = {
width: 400,
height: 15,
range: [700, 750, 800, 850, 900, 950, 1000, 1050, 1100],
// gradient: {
// 0: 'rgba(100,255,51,1)',
// 0.167: 'rgba(153,255,51,1)',
// 0.333: 'rgba(204,255,51,1)',
// 0.5: 'rgba(255,255,71,0.8)',
// 0.667: 'rgba(255,250,150,1',
// 0.833: 'rgba(255,187,102,0.9)',
// 1: 'rgba(255,119,68,0.9)'
// }
gradient: {
0.1: '#fe0000',
0.4: '#ffaa01',
0.7: '#b0e000',
1.0: '#38a702'
}
};
var canvas = document.createElement('canvas');
var context = canvas.getContext('2d');
canvas.width = options.width;
canvas.height = options.height;
var grad = context.createLinearGradient(0, 0, canvas.width, canvas.height);
for (var gradient in options.gradient) {
grad.addColorStop(gradient, options.gradient[gradient]);
}
context.fillStyle = grad;
context.fillRect(0, 0, canvas.width, canvas.height);
this.d2Hex = function (d) {
// Converts a decimal number to a two digit Hex value
var hex = Number(d).toString(16);
while (hex.length < 2) {
hex = "0" + hex;
}
return hex.toUpperCase();
};
this.getRgbColor = function (point) {
var imageData = context.getImageData(0, 0, canvas.width, canvas.height);
var data = imageData.data;
var i = (point.Y * canvas.width + point.X) * 4;
var rgb = [],
color = '#',
objRgbColor = {
"rgb": rgb,
"color": color
};
for (var j = 0; j < 3; j++) {
rgb.push(data[i + j]);
color += this.d2Hex(data[i + j]);
}
objRgbColor.color = color;
return objRgbColor;
};
this.getColor = function (value) {
var colorValue = value - options.range[0];
var point = Math.round(colorValue * canvas.width / (options.range[options.range.length - 1] - options.range[0]));
return this.getRgbColor({
X: point,
Y: 1
});
};
};
self.init(userOptions, options);
baseLayer = new CanvasLayer({
map: map,
update: brush
});
animationLayer = new CanvasLayer({
map: map,
update: render
});
mouseInteract();
(function drawFrame() {
self.timer = setTimeout(function () {
self.animationId = requestAnimationFrame(drawFrame);
render();
}, 1000 / 10);
// requestAnimationFrame(drawFrame);
// render();
})();
this.clickEvent = this.clickEvent.bind(this);
this.bindEvent();
};
LineGradient.prototype.init = function (settings, defaults) {
//合并参数
tool.merge(settings, defaults);
this.options = defaults;
};
LineGradient.prototype.bindEvent = function (e) {
var map = this.map;
if (this.options.methods) {
if (this.options.methods.click) {
map.setDefaultCursor("default");
map.addEventListener('click', this.clickEvent);
}
if (this.options.methods.mousemove) {
map.setDefaultCursor("default");
map.addEventListener('mousemove', this.clickEvent);
}
}
};
LineGradient.prototype.clickEvent = function (e) {
var self = this,
flag = false,
lines = self.pixelList;
if (lines.length > 0) {
lines.forEach(function (line, i) {
for (var j = 0; j < line.data.length; j++) {
var beginPt = line.data[j].pixel;
if (line.data[j + 1] == undefined) {
return;
}
var endPt = line.data[j + 1].pixel;
var curPt = e.pixel;
var inCircle = tool.isPointInCircle(curPt, beginPt, self.options.lineWidth);
if (inCircle) {
// self.options.methods.click(e, line.name);
self.options.methods.mousemove(e, line.data[j]);
flag = true;
return;
}
// var isOnLine = tool.containStroke(beginPt.x, beginPt.y, endPt.x, endPt.y, self.options.lineWidth, curPt.x, curPt.y);
// if (isOnLine) {
// // self.options.methods.click(e, line.name);
// self.options.methods.mousemove(e, line);
// return;
// }
}
});
if (!flag) {
document.getElementById('tooltips').style.visibility = 'hidden';
}
}
};
return LineGradient;
})));