├── .gitattributes
├── LICENSE
├── README.md
├── examples
├── images
│ ├── arrow.png
│ ├── arrow3.png
│ ├── arrow_ci.png
│ ├── begin.png
│ ├── end.png
│ └── flag.png
├── marker-direction.html
└── marker-direction.js
└── src
├── marker-direction.js
└── marker-direction.min.js
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 JackZouShao
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | leaflet-marker-direction
2 | =============
3 |
4 | Plugin for Leaflet to display the path and the direction of the marker
5 |
6 | Check out the [demo](https://thomas2077.github.io/leaflet-marker-direction/examples/marker-direction.html)
7 |
8 | Leaflet versions
9 | -----
10 | The plugin is based on Leaflet 1.0.0 or above
11 |
12 | Usage
13 | ----
14 | ````js
15 | // inite map
16 | var map = L.map('map').setView([30.201479, 120.155908], 13);
17 | L.tileLayer(...).addTo(map);
18 |
19 | // your data
20 | var list = [
21 | {"lon":"120.15261","lat":"30.182835"},
22 | {"lon":"120.152431666667","lat":"30.1828733333333"},
23 | {"lon":"120.15239","lat":"30.182755"},
24 | {"lon":"120.152303333333","lat":"30.1826566666667"}
25 | ];
26 | // iterate your data
27 | for(var i in list){
28 | var img = new Image();
29 | img.src = './images/arrow3.png';
30 | var options = {
31 | label: 'your label',
32 | labelFlag: labelFlag,
33 | labelColor: 'black',
34 | img: img
35 | };
36 |
37 | // use angeMaker plugin
38 | var angleMarker = L.angleMarker(latlng, options);
39 | var angle = 0;
40 |
41 | // get angele between A(previousPoint) and B(nextPoint)
42 | angle = angleMarker.getAngle(previousLatLng, nextLanLng);
43 |
44 | // set angele A -> B
45 | angleMarker.setHeading(angle);
46 | map.addLayer(angleMarker);
47 | }
48 | ````
49 | ### Options
50 | *`label` Text near the your marker
51 | *`labelFlag` whethe to display the text
52 | *`labelColor` The color of the text
53 | *`img` Your custom maker
54 | ### update history
55 |
--------------------------------------------------------------------------------
/examples/images/arrow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Thomas2077/leaflet-marker-direction/448b1e7ff250d1dc5e96ce7836fb1c313a912208/examples/images/arrow.png
--------------------------------------------------------------------------------
/examples/images/arrow3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Thomas2077/leaflet-marker-direction/448b1e7ff250d1dc5e96ce7836fb1c313a912208/examples/images/arrow3.png
--------------------------------------------------------------------------------
/examples/images/arrow_ci.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Thomas2077/leaflet-marker-direction/448b1e7ff250d1dc5e96ce7836fb1c313a912208/examples/images/arrow_ci.png
--------------------------------------------------------------------------------
/examples/images/begin.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Thomas2077/leaflet-marker-direction/448b1e7ff250d1dc5e96ce7836fb1c313a912208/examples/images/begin.png
--------------------------------------------------------------------------------
/examples/images/end.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Thomas2077/leaflet-marker-direction/448b1e7ff250d1dc5e96ce7836fb1c313a912208/examples/images/end.png
--------------------------------------------------------------------------------
/examples/images/flag.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Thomas2077/leaflet-marker-direction/448b1e7ff250d1dc5e96ce7836fb1c313a912208/examples/images/flag.png
--------------------------------------------------------------------------------
/examples/marker-direction.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | demo
6 |
46 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
61 |
62 |
949 |
950 |
--------------------------------------------------------------------------------
/examples/marker-direction.js:
--------------------------------------------------------------------------------
1 | /*
2 | * LEAFLET.MARKER_DRECTION
3 | * vesion 0.0.1
4 | * @author Thomas Zou
5 | * @date 10/1/2018
6 | */
7 |
8 | /* Angle ICON */
9 | L.AngleIcon = L.Icon.extend({
10 | // default value
11 | options: {
12 | angle: 0,
13 | iconSize: new L.Point(80,60), // canvas size
14 | className: "leaflet-boat-icon",
15 | course: 0, // angle
16 | labelAnchor: [10, -10], // test loaction
17 | pointType:0, // pointType
18 | ciFlag :false,
19 | label:'',
20 | textColor:'red',
21 | img:null
22 | },
23 |
24 | createIcon: function () {
25 | var e = document.createElement("canvas");
26 | this._setIconStyles(e, "icon");
27 | var s = this.options.iconSize;
28 | e.width = s.x;
29 | e.height = s.y;
30 | this.ctx = e.getContext("2d");
31 | this.draw(e.getContext("2d"), s.x, s.y);
32 | return e;
33 | },
34 |
35 | draw: function(ctx, w, h) {
36 |
37 | if(!ctx)
38 | return;
39 | var x = this.x;
40 | var y = this.y;
41 |
42 | var course = this.options.course;
43 |
44 | ctx.font="10px Courier New";
45 | ctx.fillStyle = this.options.textColor;
46 | if(this.options.ciFlag){
47 | var text = this.options.label;
48 | ctx.fillText(text, 0, 20);
49 | }
50 |
51 | this.drwaImage(ctx, this.options.img, course, 35, 20);
52 | },
53 |
54 | /**
55 | * draw image by canvas
56 | * @param ctx canvas
57 | * @param img image
58 | * @param course angle
59 | * @param w width
60 | * @param h height
61 | */
62 | drwaImage : function(ctx , img, course, w, h){
63 | console.log(img.src)
64 | img.onload = function(){
65 | //平移坐标原点
66 | ctx.translate(40,30);
67 | //旋转画布
68 | ctx.rotate(course);
69 | ctx.translate(-40,-30);
70 | //画图
71 | ctx.drawImage(img,w,h);
72 | console.log(img.src)
73 | }
74 | },
75 |
76 | /**
77 | * 获得两点之间方向角 (Get the direction angle between two points)
78 | * 根据地球上两点之间的经纬度计算两点之间与正北方向的夹角
79 | * (According to the latitude and longitude between two points on earth,
80 | * calculate the angle between two points and the direction of the north)
81 | *
82 | * @param 点A(L.Latlng) PointA
83 | * @param 点B(L.Latlng) PointB
84 | * @return result: AB角度 (the angle of AB (calculated result degree))
85 | *
86 | * @version 2016-08-19
87 | *
88 | * @see Math.atan2()用于返回从x轴到指定坐标点(x, y)的角度(以弧度为单位);y/x = tan#
89 | * Math.atan2 () returns the angle (in radians) from the x-axis to the specified coordinate point (x, y); y / x = tan #
90 | * @version 2016-08-19
91 | */
92 | getAngle : function(A, B){
93 | var angle = null;
94 | var latA = A.lat;
95 | var lonA = A.lon;
96 | var latB = B.lat;
97 | var lonB = B.lon;
98 |
99 | // 注意经度或者纬度相等 (when longitude or latitude is equal)
100 | if(lonA == lonB && latA>latB ){
101 | angle = Math.PI;
102 | }
103 | else if(lonA == lonB && latA < latB ){
104 | angle = 0 ;
105 | }
106 | else if(lonA > lonB && latA == latB ){
107 | angle = -(Math.PI/2);
108 | }
109 | else if(lonA < lonB && latA == latB ){
110 | angle = Math.PI/2 ;
111 | }
112 |
113 | // 注意经度或者纬度都不相等 (Longitude and latitude are not equal)
114 | else{
115 | var x1 = A.lat*Math.pow(10,12);
116 | var x2 = B.lat*Math.pow(10,12);
117 | var y1 = A.lon*Math.pow(10,12);
118 | var y2 = B.lon*Math.pow(10,12);
119 | angle = Math.atan2(y2-y1,x2-x1)
120 | }
121 | options.angle = angle;
122 | return angle;
123 | },
124 |
125 | /**
126 | * 设置maker 和正北方向 角度
127 | * Set the angle between the maker and the north
128 | * @param heading (Unit: radian)
129 | */
130 | setHeading : function(heading) {
131 |
132 | if(!heading){
133 | heading = options.angle;
134 | }
135 | this.options.course = (heading % 360);
136 | var s = this.options.iconSize;
137 |
138 | //我们不需要在这里显示的调用draw()方法,因为map.addLayer(layer)会调用这个方法
139 | //We do not need to call draw() as shown here
140 | //because map.addLayer (layer) will call this method
141 | //this.draw(this.ctx, s.x, s.y);
142 | }
143 | });
144 |
145 | // AngleMarker继承Marker并添加setHeading 和 getAngle 方法
146 | // AngleMarker extends from Marker and adds the setHeading and getAngle methods
147 | L.AngleMarker = L.Marker.extend({
148 | getAngle : function (A, B) {
149 | return this.options.icon.getAngle(A, B);
150 | },
151 | setHeading: function(heading) {
152 | this.options.icon.setHeading(heading);
153 | }
154 | });
155 |
156 | L.angleMarker = function(pos, options) {
157 |
158 | options.icon = new L.AngleIcon({
159 | ciFlag:options.labelFlag,
160 | label:options.label,
161 | textColor:options.labelColor,
162 | img: options.img
163 | });
164 |
165 | return new L.AngleMarker(pos,options);
166 | };
167 |
--------------------------------------------------------------------------------
/src/marker-direction.js:
--------------------------------------------------------------------------------
1 | /*
2 | * LEAFLET.MARKER_DRECTION
3 | * vesion 0.0.1
4 | * @author Thomas Zou
5 | * @date 10/1/2018
6 | */
7 |
8 | /* Angle ICON */
9 | L.AngleIcon = L.Icon.extend({
10 | // default value
11 | options: {
12 | angle: 0,
13 | iconSize: new L.Point(80,60), // canvas size
14 | className: "leaflet-boat-icon",
15 | course: 0, // angle
16 | labelAnchor: [10, -10], // test loaction
17 | pointType:0, // pointType
18 | ciFlag :false,
19 | label:'',
20 | textColor:'red',
21 | img:null
22 | },
23 |
24 | createIcon: function () {
25 | var e = document.createElement("canvas");
26 | this._setIconStyles(e, "icon");
27 | var s = this.options.iconSize;
28 | e.width = s.x;
29 | e.height = s.y;
30 | this.ctx = e.getContext("2d");
31 | this.draw(e.getContext("2d"), s.x, s.y);
32 | return e;
33 | },
34 |
35 | draw: function(ctx, w, h) {
36 |
37 | if(!ctx)
38 | return;
39 | var x = this.x;
40 | var y = this.y;
41 |
42 | var course = this.options.course;
43 |
44 | ctx.font="10px Courier New";
45 | ctx.fillStyle = this.options.textColor;
46 | if(this.options.ciFlag){
47 | var text = this.options.label;
48 | ctx.fillText(text, 0, 20);
49 | }
50 |
51 | this.drwaImage(ctx, this.options.img, course, 35, 20);
52 | },
53 |
54 | /**
55 | * draw image by canvas
56 | * @param ctx canvas
57 | * @param img image
58 | * @param course angle
59 | * @param w width
60 | * @param h height
61 | */
62 | drwaImage : function(ctx , img, course, w, h){
63 | console.log(img.src)
64 | img.onload = function(){
65 | //平移坐标原点
66 | ctx.translate(40,30);
67 | //旋转画布
68 | ctx.rotate(course);
69 | ctx.translate(-40,-30);
70 | //画图
71 | ctx.drawImage(img,w,h);
72 | console.log(img.src)
73 | }
74 | },
75 |
76 | /**
77 | * 获得两点之间方向角 (Get the direction angle between two points)
78 | * 根据地球上两点之间的经纬度计算两点之间与正北方向的夹角
79 | * (According to the latitude and longitude between two points on earth,
80 | * calculate the angle between two points and the direction of the north)
81 | *
82 | * @param 点A(L.Latlng) PointA
83 | * @param 点B(L.Latlng) PointB
84 | * @return result: AB角度 (the angle of AB (calculated result degree))
85 | *
86 | * @version 2016-08-19
87 | *
88 | * @see Math.atan2()用于返回从x轴到指定坐标点(x, y)的角度(以弧度为单位);y/x = tan#
89 | * Math.atan2 () returns the angle (in radians) from the x-axis to the specified coordinate point (x, y); y / x = tan #
90 | * @version 2016-08-19
91 | */
92 | getAngle : function(A, B){
93 | var angle = null;
94 | var latA = A.lat;
95 | var lonA = A.lon;
96 | var latB = B.lat;
97 | var lonB = B.lon;
98 |
99 | // 注意经度或者纬度相等 (when longitude or latitude is equal)
100 | if(lonA == lonB && latA>latB ){
101 | angle = Math.PI;
102 | }
103 | else if(lonA == lonB && latA < latB ){
104 | angle = 0 ;
105 | }
106 | else if(lonA > lonB && latA == latB ){
107 | angle = -(Math.PI/2);
108 | }
109 | else if(lonA < lonB && latA == latB ){
110 | angle = Math.PI/2 ;
111 | }
112 |
113 | // 注意经度或者纬度都不相等 (Longitude and latitude are not equal)
114 | else{
115 | var x1 = A.lat*Math.pow(10,12);
116 | var x2 = B.lat*Math.pow(10,12);
117 | var y1 = A.lon*Math.pow(10,12);
118 | var y2 = B.lon*Math.pow(10,12);
119 | angle = Math.atan2(y2-y1,x2-x1)
120 | }
121 | options.angle = angle;
122 | return angle;
123 | },
124 |
125 | /**
126 | * 设置maker 和正北方向 角度
127 | * Set the angle between the maker and the north
128 | * @param heading (Unit: radian)
129 | */
130 | setHeading : function(heading) {
131 |
132 | if(!heading){
133 | heading = options.angle;
134 | }
135 | this.options.course = (heading % 360);
136 | var s = this.options.iconSize;
137 |
138 | //我们不需要在这里显示的调用draw()方法,因为map.addLayer(layer)会调用这个方法
139 | //We do not need to call draw() as shown here
140 | //because map.addLayer (layer) will call this method
141 | //this.draw(this.ctx, s.x, s.y);
142 | }
143 | });
144 |
145 | // AngleMarker继承Marker并添加setHeading 和 getAngle 方法
146 | // AngleMarker extends from Marker and adds the setHeading and getAngle methods
147 | L.AngleMarker = L.Marker.extend({
148 | getAngle : function (A, B) {
149 | return this.options.icon.getAngle(A, B);
150 | },
151 | setHeading: function(heading) {
152 | this.options.icon.setHeading(heading);
153 | }
154 | });
155 |
156 | L.angleMarker = function(pos, options) {
157 |
158 | options.icon = new L.AngleIcon({
159 | ciFlag:options.labelFlag,
160 | label:options.label,
161 | textColor:options.labelColor,
162 | img: options.img
163 | });
164 |
165 | return new L.AngleMarker(pos,options);
166 | };
167 |
--------------------------------------------------------------------------------
/src/marker-direction.min.js:
--------------------------------------------------------------------------------
1 | L.AngleIcon=L.Icon.extend({options:{angle:0,iconSize:new L.Point(80,60),className:"leaflet-boat-icon",course:0,labelAnchor:[10,-10],pointType:0,ciFlag:false,label:"",textColor:"red",img:null},createIcon:function(){var e=document.createElement("canvas");this._setIconStyles(e,"icon");var s=this.options.iconSize;e.width=s.x;e.height=s.y;this.ctx=e.getContext("2d");this.draw(e.getContext("2d"),s.x,s.y);return e},draw:function(ctx,w,h){if(!ctx){return}var x=this.x;var y=this.y;var course=this.options.course;ctx.font="10px Courier New";ctx.fillStyle=this.options.textColor;if(this.options.ciFlag){var text=this.options.label;ctx.fillText(text,0,20)}this.drwaImage(ctx,this.options.img,course,35,20)},drwaImage:function(ctx,img,course,w,h){console.log(img.src);img.onload=function(){ctx.translate(40,30);ctx.rotate(course);ctx.translate(-40,-30);ctx.drawImage(img,w,h);console.log(img.src)}},getAngle:function(A,B){var angle=null;var latA=A.lat;var lonA=A.lon;var latB=B.lat;var lonB=B.lon;if(lonA==lonB&&latA>latB){angle=Math.PI}else{if(lonA==lonB&&latAlonB&&latA==latB){angle=-(Math.PI/2)}else{if(lonA