-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathCanvasMarker.js
112 lines (90 loc) · 4.04 KB
/
CanvasMarker.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
'use strict';
L.CanvasMarker = L.Marker.extend({
options: {
color: 'grey'
},
onAdd: function(map) {
this._map = map;
this.createCanvas(map);
this.catchEvents();
this.startAnimation();
},
createCanvas: function(map) {
var canvas = L.DomUtil.create('canvas', 'leaflet-marker-icon');
//append the canvas to the leaflet-marker-pane, which means that the panning transformation is automatically applied
map._container.getElementsByClassName('leaflet-marker-pane')[0].appendChild(canvas);
canvas.style.position = 'absolute';
canvas.height = map._container.clientHeight;
canvas.width = map._container.clientWidth;
//Create new canvas elements with the transformaton in mind (panning!)
var mapTransforms = this.getTransform(map._container.getElementsByClassName('leaflet-map-pane')[0]);
canvas.style.left = (mapTransforms[0] * -1) + 'px';
canvas.style.top = (mapTransforms[1] * -1) + 'px';
this._canvas = canvas;
},
getTransform: function(el) {
//retrieve the transform attribute of a given element and returns the values in an array
var transform = window.getComputedStyle(el, null).getPropertyValue('-webkit-transform');
var results = transform.match(/matrix(?:(3d)\(-{0,1}\d+(?:, -{0,1}\d+)*(?:, (-{0,1}\d+))(?:, (-{0,1}\d+))(?:, (-{0,1}\d+)), -{0,1}\d+\)|\(-{0,1}\d+(?:, -{0,1}\d+)*(?:, (-{0,1}\d+))(?:, (-{0,1}\d+))\))/);
if (!results) return [0, 0, 0];
if (results[1] == '3d') return results.slice(2, 5);
results.push(0);
return results.slice(5, 8); // returns the [X,Y,Z,1] values
},
startAnimation: function() {
this.options.displayPos = this._map.latLngToContainerPoint(this._latlng);
var context = this._canvas.getContext('2d');
this.animate(context, this._canvas, 500, 0);
},
drawArc: function(context, x, y, radius, startAngle, endAngle) {
context.beginPath();
context.arc(x, y, radius, startAngle, endAngle, false);
context.lineWidth = 5;
context.strokeStyle = this.options.color;
context.stroke();
},
drawCircle: function(context, x, y, radius) {
context.beginPath();
context.arc(x, y, radius, 0, 2 * Math.PI, false);
context.lineWidth = 3;
context.strokeStyle = this.options.color;
context.stroke();
},
animate: function(context, canvas, radius, i) {
var x = this.options.displayPos.x;
var y = this.options.displayPos.y;
context.clearRect(0, 0, canvas.width, canvas.height);
//i is the counter which is responsible for the rotation
i += 0.05;
if (radius > 30) radius -= 20;
else {
this.drawCircle(context, x, y, 10);
}
var startAngle = 0 + i;
var endAngle = 0.85 * Math.PI + i;
this.drawArc(context, x, y, radius, startAngle, endAngle);
this.drawArc(context, x, y, radius, startAngle + Math.PI, endAngle + Math.PI);
this.drawCircle(context, x, y, radius + 2);
window.requestAnimFrame(function() {
this.animate(context, canvas, radius, i);
}.bind(this));
},
catchEvents: function() {
//display positions have to be recalculated if the map is zoomed
this._map.on('zoomend', function() {
this.options.displayPos = this._map.latLngToContainerPoint(this._latlng);
}.bind(this));
},
onRemove: function(map) {
map._container.getElementsByClassName('leaflet-marker-pane')[0].removeChild(this._canvas);
}
});
L.canvasMarker = function(latlng, options) {
return new L.CanvasMarker(latlng, options);
};
window.requestAnimFrame = (function(callback) {
return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame ||
function(callback) {
window.setTimeout(callback, 1000 / 60);
};
})();