diff --git a/build/baidu-map-pointLine.js b/build/baidu-map-pointLine.js index 9bb4ea2..3d6b4cf 100644 --- a/build/baidu-map-pointLine.js +++ b/build/baidu-map-pointLine.js @@ -104,60 +104,6 @@ CanvasLayer.prototype.getZIndex = function () { return this.zIndex; }; -var GeoUtils = { - /** - * 判断点是否在矩形内 - * @param {Point} point 点对象 - * @param {Bounds} bounds 矩形边界对象 - * @returns {Boolean} 点在矩形内返回true,否则返回false - */ - isPointInRect: function isPointInRect(point, bounds) { - //检查类型是否正确 - if (!(point instanceof BMap.Point) || !(bounds instanceof BMap.Bounds)) { - return false; - } - var sw = bounds.getSouthWest(); //西南脚点 - var ne = bounds.getNorthEast(); //东北脚点 - return point.lng >= sw.lng && point.lng <= ne.lng && point.lat >= sw.lat && point.lat <= ne.lat; - }, - /** - * 判断点是否在折线上 - * @param {Point} point 点对象 - * @param {Polyline} polyline 折线对象 - * @returns {Boolean} 点在折线上返回true,否则返回false - */ - isPointOnPolyline: function isPointOnPolyline(point, polyline) { - //检查类型 - if (!(point instanceof BMap.Point) || !(polyline instanceof BMap.Polyline)) { - return false; - } - - //首先判断点是否在线的外包矩形内,如果在,则进一步判断,否则返回false - var lineBounds = polyline.getBounds(); - if (!this.isPointInRect(point, lineBounds)) { - return false; - } - - //判断点是否在线段上,设点为Q,线段为P1P2 , - //判断点Q在该线段上的依据是:( Q - P1 ) × ( P2 - P1 ) = 0,且 Q 在以 P1,P2为对角顶点的矩形内 - var pts = polyline.getPath(); - for (var i = 0; i < pts.length - 1; i++) { - var curPt = pts[i]; - var nextPt = pts[i + 1]; - //首先判断point是否在curPt和nextPt之间,即:此判断该点是否在该线段的外包矩形内 - if (point.lng >= Math.min(curPt.lng, nextPt.lng) && point.lng <= Math.max(curPt.lng, nextPt.lng) && point.lat >= Math.min(curPt.lat, nextPt.lat) && point.lat <= Math.max(curPt.lat, nextPt.lat)) { - //判断点是否在直线上公式 - var precision = (curPt.lng - point.lng) * (nextPt.lat - point.lat) - (nextPt.lng - point.lng) * (curPt.lat - point.lat); - if (precision < 2e-10 && precision > -2e-10) { - //实质判断是否接近0 - return true; - } - } - } - return false; - } -}; - var tool = { merge: function merge(settings, defaults) { Object.keys(settings).forEach(function (key) { @@ -167,6 +113,29 @@ var tool = { //计算两点间距离 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; } }; @@ -175,6 +144,7 @@ var PointLine = function PointLine(map, userOptions) { self.map = map; self.lines = []; + self.pixelList = []; //默认参数 var options = { @@ -209,7 +179,7 @@ var PointLine = function PointLine(map, userOptions) { }; Line.prototype.draw = function (context) { - var pointList = this.getPointList(); + var pointList = this.pixelList || this.getPointList(); context.save(); context.beginPath(); context.lineWidth = options.lineWidth; @@ -234,7 +204,12 @@ var PointLine = function PointLine(map, userOptions) { baseCtx.clearRect(0, 0, width, height); + self.pixelList = []; self.lines.forEach(function (line) { + self.pixelList.push({ + name: line.name, + data: line.getPointList() + }); line.draw(baseCtx); }); }; @@ -283,23 +258,30 @@ PointLine.prototype.bindEvent = function (e) { map.setDefaultCursor("default"); map.addEventListener('click', this.clickEvent); } + if (this.options.methods.mousemove) { + map.setDefaultCursor("default"); + map.addEventListener('mousemove', this.clickEvent); + } } }; PointLine.prototype.clickEvent = function (e) { var self = this, - lines = self.lines; + lines = self.pixelList; if (lines.length > 0) { lines.forEach(function (line, i) { - var pts = []; - line.path.forEach(function (point, j) { - pts.push(point.location); - }); - var polyline = new BMap.Polyline(pts); - var isOnLine = GeoUtils.isPointOnPolyline(e.point, polyline); - if (isOnLine) { - self.options.methods.click(e, line.name); - return; + 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 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); + return; + } } }); } diff --git a/build/release/baidu-map-pointLine.min.js b/build/release/baidu-map-pointLine.min.js index 7650d13..32ff23d 100644 --- a/build/release/baidu-map-pointLine.min.js +++ b/build/release/baidu-map-pointLine.min.js @@ -1 +1 @@ -!function(t,i){"object"==typeof exports&&"undefined"!=typeof module?module.exports=i():"function"==typeof define&&define.amd?define(i):t.PointLine=i()}(this,function(){"use strict";function t(t){this.options=t||{},this.paneName=this.options.paneName||"labelPane",this.zIndex=this.options.zIndex||0,this._map=t.map,this._lastDrawTime=null,this.show()}t.prototype=new BMap.Overlay,t.prototype.initialize=function(t){this._map=t;var i=this.canvas=document.createElement("canvas"),n=this.ctx=this.canvas.getContext("2d");i.style.cssText="position:absolute;left:0;top:0;z-index:"+this.zIndex+";",this.adjustSize(),this.adjustRatio(n),t.getPanes()[this.paneName].appendChild(i);var e=this;return t.addEventListener("resize",function(){e.adjustSize(),e._draw()}),this.canvas},t.prototype.adjustSize=function(){var t=this._map.getSize(),i=this.canvas;i.width=t.width,i.height=t.height,i.style.width=i.width+"px",i.style.height=i.height+"px"},t.prototype.adjustRatio=function(t){var i=t.backingStorePixelRatio||t.webkitBackingStorePixelRatio||t.mozBackingStorePixelRatio||t.msBackingStorePixelRatio||t.oBackingStorePixelRatio||t.backingStorePixelRatio||1,n=(window.devicePixelRatio||1)/i,e=t.canvas.width,a=t.canvas.height;t.canvas.width=e*n,t.canvas.height=a*n,t.canvas.style.width=e+"px",t.canvas.style.height=a+"px",t.scale(n,n)},t.prototype.draw=function(){var t=this;clearTimeout(t.timeoutID),t.timeoutID=setTimeout(function(){t._draw()},15)},t.prototype._draw=function(){var t=this._map,i=t.getSize(),n=t.getCenter();if(n){var e=t.pointToOverlayPixel(n);this.canvas.style.left=e.x-i.width/2+"px",this.canvas.style.top=e.y-i.height/2+"px",this.dispatchEvent("draw"),this.options.update&&this.options.update.call(this)}},t.prototype.getContainer=function(){return this.canvas},t.prototype.show=function(){this.canvas||this._map.addOverlay(this),this.canvas.style.display="block"},t.prototype.hide=function(){this.canvas.style.display="none"},t.prototype.setZIndex=function(t){this.canvas.style.zIndex=t},t.prototype.getZIndex=function(){return this.zIndex};var i={isPointInRect:function(t,i){if(!(t instanceof BMap.Point&&i instanceof BMap.Bounds))return!1;var n=i.getSouthWest(),e=i.getNorthEast();return t.lng>=n.lng&&t.lng<=e.lng&&t.lat>=n.lat&&t.lat<=e.lat},isPointOnPolyline:function(t,i){if(!(t instanceof BMap.Point&&i instanceof BMap.Polyline))return!1;var n=i.getBounds();if(!this.isPointInRect(t,n))return!1;for(var e=i.getPath(),a=0;a=Math.min(o.lng,s.lng)&&t.lng<=Math.max(o.lng,s.lng)&&t.lat>=Math.min(o.lat,s.lat)&&t.lat<=Math.max(o.lat,s.lat)){var h=(o.lng-t.lng)*(s.lat-t.lat)-(s.lng-t.lng)*(o.lat-t.lat);if(h<2e-10&&h>-2e-10)return!0}}return!1}},n={merge:function(t,i){Object.keys(t).forEach(function(n){i[n]=t[n]})},getDistance:function(t,i){return Math.sqrt((t[0]-i[0])*(t[0]-i[0])+(t[1]-i[1])*(t[1]-i[1]))}},e=function(i,n){function e(t){this.name=t.name,this.path=t.path}var a=this;a.map=i,a.lines=[];var o={lineWidth:1,lineStyle:"#F9815C"},s=null,h=i.getSize().width,l=i.getSize().height;e.prototype.getPointList=function(){var t=[],n=this.path;return n&&n.length>0&&n.forEach(function(n){t.push({name:n.name,pixel:i.pointToPixel(n.location)})}),t},e.prototype.draw=function(t){var i=this.getPointList();t.save(),t.beginPath(),t.lineWidth=o.lineWidth,t.strokeStyle=o.lineStyle,t.moveTo(i[0].pixel.x,i[0].pixel.y);for(var n=0,e=i.length;n0)){o.data.forEach(function(t,i){var n=new e({name:t.name,path:[]});t.data.forEach(function(t,i){n.path.push({name:t.name,location:new BMap.Point(t.Longitude,t.Latitude)})}),a.lines.push(n)})}};a.init(n,o),s=new t({map:i,update:r}),this.clickEvent=this.clickEvent.bind(this),this.bindEvent()};return e.prototype.init=function(t,i){n.merge(t,i),this.options=i},e.prototype.bindEvent=function(t){var i=this.map;this.options.methods&&this.options.methods.click&&(i.setDefaultCursor("default"),i.addEventListener("click",this.clickEvent))},e.prototype.clickEvent=function(t){var n=this,e=n.lines;e.length>0&&e.forEach(function(e,a){var o=[];e.path.forEach(function(t,i){o.push(t.location)});var s=new BMap.Polyline(o);if(i.isPointOnPolyline(t.point,s))return void n.options.methods.click(t,e.name)})},e}); \ No newline at end of file +!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):t.PointLine=e()}(this,function(){"use strict";function t(t){this.options=t||{},this.paneName=this.options.paneName||"labelPane",this.zIndex=this.options.zIndex||0,this._map=t.map,this._lastDrawTime=null,this.show()}t.prototype=new BMap.Overlay,t.prototype.initialize=function(t){this._map=t;var e=this.canvas=document.createElement("canvas"),i=this.ctx=this.canvas.getContext("2d");e.style.cssText="position:absolute;left:0;top:0;z-index:"+this.zIndex+";",this.adjustSize(),this.adjustRatio(i),t.getPanes()[this.paneName].appendChild(e);var n=this;return t.addEventListener("resize",function(){n.adjustSize(),n._draw()}),this.canvas},t.prototype.adjustSize=function(){var t=this._map.getSize(),e=this.canvas;e.width=t.width,e.height=t.height,e.style.width=e.width+"px",e.style.height=e.height+"px"},t.prototype.adjustRatio=function(t){var e=t.backingStorePixelRatio||t.webkitBackingStorePixelRatio||t.mozBackingStorePixelRatio||t.msBackingStorePixelRatio||t.oBackingStorePixelRatio||t.backingStorePixelRatio||1,i=(window.devicePixelRatio||1)/e,n=t.canvas.width,a=t.canvas.height;t.canvas.width=n*i,t.canvas.height=a*i,t.canvas.style.width=n+"px",t.canvas.style.height=a+"px",t.scale(i,i)},t.prototype.draw=function(){var t=this;clearTimeout(t.timeoutID),t.timeoutID=setTimeout(function(){t._draw()},15)},t.prototype._draw=function(){var t=this._map,e=t.getSize(),i=t.getCenter();if(i){var n=t.pointToOverlayPixel(i);this.canvas.style.left=n.x-e.width/2+"px",this.canvas.style.top=n.y-e.height/2+"px",this.dispatchEvent("draw"),this.options.update&&this.options.update.call(this)}},t.prototype.getContainer=function(){return this.canvas},t.prototype.show=function(){this.canvas||this._map.addOverlay(this),this.canvas.style.display="block"},t.prototype.hide=function(){this.canvas.style.display="none"},t.prototype.setZIndex=function(t){this.canvas.style.zIndex=t},t.prototype.getZIndex=function(){return this.zIndex};var e={merge:function(t,e){Object.keys(t).forEach(function(i){e[i]=t[i]})},getDistance:function(t,e){return Math.sqrt((t[0]-e[0])*(t[0]-e[0])+(t[1]-e[1])*(t[1]-e[1]))},containStroke:function(t,e,i,n,a,o,s){if(0===a)return!1;var h=a,r=0,p=t;if(s>e+h&&s>n+h||st+h&&o>i+h||o0&&i.forEach(function(i){t.push({name:i.name,pixel:e.pointToPixel(i.location)})}),t},n.prototype.draw=function(t){var e=this.pixelList||this.getPointList();t.save(),t.beginPath(),t.lineWidth=o.lineWidth,t.strokeStyle=o.lineStyle,t.moveTo(e[0].pixel.x,e[0].pixel.y);for(var i=0,n=e.length;i0)){o.data.forEach(function(t,e){var i=new n({name:t.name,path:[]});t.data.forEach(function(t,e){i.path.push({name:t.name,location:new BMap.Point(t.Longitude,t.Latitude)})}),a.lines.push(i)})}};a.init(i,o),s=new t({map:e,update:p}),this.clickEvent=this.clickEvent.bind(this),this.bindEvent()};return i.prototype.init=function(t,i){e.merge(t,i),this.options=i},i.prototype.bindEvent=function(t){var e=this.map;this.options.methods&&(this.options.methods.click&&(e.setDefaultCursor("default"),e.addEventListener("click",this.clickEvent)),this.options.methods.mousemove&&(e.setDefaultCursor("default"),e.addEventListener("mousemove",this.clickEvent)))},i.prototype.clickEvent=function(t){var i=this,n=i.pixelList;n.length>0&&n.forEach(function(n,a){for(var o=0;o 0) { lines.forEach(function (line, i) { - var pts = []; - line.path.forEach(function (point, j) { - pts.push(point.location); - }); - var polyline = new BMap.Polyline(pts); - var isOnLine = GeoUtils.isPointOnPolyline(e.point, polyline); - if (isOnLine) { - self.options.methods.click(e, line.name); - return; + 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 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); + return; + } } + }); } - } export default PointLine; \ No newline at end of file diff --git a/src/utils/tool.js b/src/utils/tool.js index 3c84f93..9408328 100644 --- a/src/utils/tool.js +++ b/src/utils/tool.js @@ -9,5 +9,33 @@ export default { return Math.sqrt( (p1[0] - p2[0]) * (p1[0] - p2[0]) + (p1[1] - p2[1]) * (p1[1] - p2[1]) ); + }, + //判断点是否在线段上 + 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; } } \ No newline at end of file