生活随笔
收集整理的這篇文章主要介紹了
Openlayers4中实现动态线效果
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
2019獨角獸企業重金招聘Python工程師標準>>>
概述:
本文講述如何結合canvas在Openlayers4中實現動態線的效果。
?
效果:
?
代碼:
1、move-line擴展
?
[javascript]?view plain?copy
(function?(global,?factory)?{??????typeof?exports?===?'object'?&&?typeof?module?!==?'undefined'???module.exports?=?factory()?:??????????typeof?define?===?'function'?&&?define.amd???define(factory)?:??????????????(global.MoveLine?=?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.initialize?=?function?()?{??????????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.getViewport().appendChild(canvas);??????????var?that?=?this;??????????map.getView().on('propertychange',function(){??????????????$(canvas).hide();??????????});??????????map.on("moveend",function(){??????????????$(canvas).show();??????????????that.adjustSize();??????????????that._draw();??????????});??????????return?this.canvas;??????};????????CanvasLayer.prototype.adjustSize?=?function?()?{??????????var?size?=?this._map.getSize();??????????var?canvas?=?this.canvas;??????????canvas.width?=?size[0];??????????canvas.height?=?size[1];??????????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';??????????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.getView().getCenter();??????????if?(center)?{??????????????var?pixel?=?map.getPixelFromCoordinate(center);??????????????this.canvas.style.left?=?pixel[0]?-?size[0]?/?2?+?'px';??????????????this.canvas.style.top?=?pixel[1]?-?size[1]?/?2?+?'px';??????????????this.options.update?&&?this.options.update.call(this);??????????}??????};????????CanvasLayer.prototype.getContainer?=?function?()?{??????????return?this.canvas;??????};????????CanvasLayer.prototype.show?=?function?()?{??????????this.initialize();??????????this.canvas.style.display?=?'block';??????};????????CanvasLayer.prototype.hide?=?function?()?{??????????this.canvas.style.display?=?'none';??????};????????CanvasLayer.prototype.setZIndex?=?function?(zIndex)?{??????????this.canvas.style.zIndex?=?zIndex;??????};????????CanvasLayer.prototype.getZIndex?=?function?()?{??????????return?this.zIndex;??????};????????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?MoveLine?=?function?MoveLine(map,?userOptions)?{??????????var?self?=?this;????????????//默認參數??????????var?options?=?{??????????????//marker點半徑??????????????markerRadius:?3,??????????????//marker點顏色,為空或null則默認取線條顏色??????????????markerColor:?'#fff',??????????????//線條類型?solid、dashed、dotted??????????????lineType:?'solid',??????????????//線條寬度??????????????lineWidth:?1,??????????????//線條顏色??????????????colors:?['#F9815C',?'#F8AB60',?'#EDCC72',?'#E2F194',?'#94E08A',?'#4ECDA5'],??????????????//移動點半徑??????????????moveRadius:?2,??????????????//移動點顏色??????????????fillColor:?'#fff',??????????????//移動點陰影顏色??????????????shadowColor:?'#fff',??????????????//移動點陰影大小??????????????shadowBlur:?5??????????};????????????//全局變量??????????var?baseLayer?=?null,??????????????animationLayer?=?null,??????????????width?=?map.getSize()[0],??????????????height?=?map.getSize()[1],??????????????animationFlag?=?true,??????????????markLines?=?[];????????????//參數合并??????????var?merge?=?function?merge(userOptions,?options)?{??????????????Object.keys(userOptions).forEach(function?(key)?{??????????????????options[key]?=?userOptions[key];??????????????});??????????};????????????function?Marker(opts)?{??????????????this.city?=?opts.city;??????????????this.location?=?opts.location;??????????????this.color?=?opts.color;??????????}????????????Marker.prototype.draw?=?function?(context)?{??????????????var?pixel?=?this.pixel?=?map.getPixelFromCoordinate(this.location);????????????????context.save();??????????????context.beginPath();??????????????context.fillStyle?=?options.markerColor?||?this.color;??????????????context.arc(pixel[0],?pixel[1],?options.markerRadius,?0,?Math.PI?*?2,?true);??????????????context.closePath();??????????????context.fill();????????????????context.textAlign?=?'center';??????????????context.textBaseline?=?'middle';??????????????context.font?=?'12px?Microsoft?YaHei';??????????????context.fillStyle?=?this.color;??????????????context.fillText(this.city,?pixel[0],?pixel[1]?-?10);??????????????context.restore();??????????};????????????function?MarkLine(opts)?{??????????????this.from?=?opts.from;??????????????this.to?=?opts.to;??????????????this.id?=?opts.id;??????????????this.step?=?0;??????????}????????????MarkLine.prototype.getPointList?=?function?(from,?to)?{??????????????var?points?=?[[from[0],?from[1]],?[to[0],?to[1]]];??????????????var?ex?=?points[1][0];??????????????var?ey?=?points[1][1];??????????????points[3]?=?[ex,?ey];??????????????points[1]?=?this.getOffsetPoint(points[0],?points[3]);??????????????points[2]?=?this.getOffsetPoint(points[3],?points[0]);??????????????points?=?this.smoothSpline(points,?false);??????????????//修正最后一點在插值產生的偏移??????????????points[points.length?-?1]?=?[ex,?ey];??????????????return?points;??????????};????????????MarkLine.prototype.getOffsetPoint?=?function?(start,?end)?{??????????????var?distance?=?this.getDistance(start,?end)?/?3;?//除以3???????????????var?angle,?dX,?dY;??????????????var?mp?=?[start[0],?start[1]];??????????????var?deltaAngle?=?-0.2;?//偏移0.2弧度??????????????if?(start[0]?!=?end[0]?&&?start[1]?!=?end[1])?{??????????????????//斜率存在??????????????????var?k?=?(end[1]?-?start[1])?/?(end[0]?-?start[0]);??????????????????angle?=?Math.atan(k);??????????????}?else?if?(start[0]?==?end[0])?{??????????????????//垂直線??????????????????angle?=?(start[1]?<=?end[1]???1?:?-1)?*?Math.PI?/?2;??????????????}?else?{??????????????????//水平線??????????????????angle?=?0;??????????????}??????????????if?(start[0]?<=?end[0])?{??????????????????angle?-=?deltaAngle;??????????????????dX?=?Math.round(Math.cos(angle)?*?distance);??????????????????dY?=?Math.round(Math.sin(angle)?*?distance);??????????????????mp[0]?+=?dX;??????????????????mp[1]?+=?dY;??????????????}?else?{??????????????????angle?+=?deltaAngle;??????????????????dX?=?Math.round(Math.cos(angle)?*?distance);??????????????????dY?=?Math.round(Math.sin(angle)?*?distance);??????????????????mp[0]?-=?dX;??????????????????mp[1]?-=?dY;??????????????}??????????????return?mp;??????????};????????????MarkLine.prototype.smoothSpline?=?function?(points,?isLoop)?{??????????????var?len?=?points.length;??????????????var?ret?=?[];??????????????var?distance?=?0;??????????????for?(var?i?=?1;?i?<?len;?i++)?{??????????????????distance?+=?this.getDistance(points[i?-?1],?points[i]);??????????????}??????????????var?segs?=?distance?/?2;??????????????segs?=?segs?<?len???len?:?segs;??????????????for?(var?i?=?0;?i?<?segs;?i++)?{??????????????????var?pos?=?i?/?(segs?-?1)?*?(isLoop???len?:?len?-?1);??????????????????var?idx?=?Math.floor(pos);??????????????????var?w?=?pos?-?idx;??????????????????var?p0;??????????????????var?p1?=?points[idx?%?len];??????????????????var?p2;??????????????????var?p3;??????????????????if?(!isLoop)?{??????????????????????p0?=?points[idx?===?0???idx?:?idx?-?1];??????????????????????p2?=?points[idx?>?len?-?2???len?-?1?:?idx?+?1];??????????????????????p3?=?points[idx?>?len?-?3???len?-?1?:?idx?+?2];??????????????????}?else?{??????????????????????p0?=?points[(idx?-?1?+?len)?%?len];??????????????????????p2?=?points[(idx?+?1)?%?len];??????????????????????p3?=?points[(idx?+?2)?%?len];??????????????????}??????????????????var?w2?=?w?*?w;??????????????????var?w3?=?w?*?w2;????????????????????ret.push([this.interpolate(p0[0],?p1[0],?p2[0],?p3[0],?w,?w2,?w3),?this.interpolate(p0[1],?p1[1],?p2[1],?p3[1],?w,?w2,?w3)]);??????????????}??????????????return?ret;??????????};????????????MarkLine.prototype.interpolate?=?function?(p0,?p1,?p2,?p3,?t,?t2,?t3)?{??????????????var?v0?=?(p2?-?p0)?*?0.5;??????????????var?v1?=?(p3?-?p1)?*?0.5;??????????????return?(2?*?(p1?-?p2)?+?v0?+?v1)?*?t3?+?(-3?*?(p1?-?p2)?-?2?*?v0?-?v1)?*?t2?+?v0?*?t?+?p1;??????????};????????????MarkLine.prototype.getDistance?=?function?(p1,?p2)?{??????????????return?Math.sqrt((p1[0]?-?p2[0])?*?(p1[0]?-?p2[0])?+?(p1[1]?-?p2[1])?*?(p1[1]?-?p2[1]));??????????};????????????MarkLine.prototype.drawMarker?=?function?(context)?{??????????????this.from.draw(context);??????????????this.to.draw(context);??????????};????????????MarkLine.prototype.drawLinePath?=?function?(context)?{??????????????var?pointList?=?this.path?=?this.getPointList(map.getPixelFromCoordinate(this.from.location),?map.getPixelFromCoordinate(this.to.location));??????????????var?len?=?pointList.length;??????????????context.save();??????????????context.beginPath();??????????????context.lineWidth?=?options.lineWidth;??????????????context.strokeStyle?=?options.colors[this.id];????????????????if?(!options.lineType?||?options.lineType?==?'solid')?{??????????????????context.moveTo(pointList[0][0],?pointList[0][1]);??????????????????for?(var?i?=?0;?i?<?len;?i++)?{??????????????????????context.lineTo(pointList[i][0],?pointList[i][1]);??????????????????}??????????????}?else?if?(options.lineType?==?'dashed'?||?options.lineType?==?'dotted')?{??????????????????for?(var?i?=?1;?i?<?len;?i?+=?2)?{??????????????????????context.moveTo(pointList[i?-?1][0],?pointList[i?-?1][1]);??????????????????????context.lineTo(pointList[i][0],?pointList[i][1]);??????????????????}??????????????}??????????????context.stroke();??????????????context.restore();??????????????this.step?=?0;?//縮放地圖時重新繪制動畫??????????};????????????MarkLine.prototype.drawMoveCircle?=?function?(context)?{??????????????var?pointList?=?this.path?||?this.getPointList(map.getPixelFromCoordinate(this.from.location),?map.getPixelFromCoordinate(this.to.location));????????????????context.save();??????????????context.fillStyle?=?options.fillColor;??????????????context.shadowColor?=?options.shadowColor;??????????????context.shadowBlur?=?options.shadowBlur;??????????????context.beginPath();??????????????context.arc(pointList[this.step][0],?pointList[this.step][1],?options.moveRadius,?0,?Math.PI?*?2,?true);??????????????context.fill();??????????????context.closePath();??????????????context.restore();??????????????this.step?+=?1;??????????????if?(this.step?>=?pointList.length)?{??????????????????this.step?=?0;??????????????}??????????};????????????//底層canvas渲染,標注,線條??????????var?brush?=?function?brush()?{??????????????var?baseCtx?=?baseLayer.canvas.getContext('2d');??????????????if?(!baseCtx)?{??????????????????return;??????????????}????????????????addMarkLine();????????????????baseCtx.clearRect(0,?0,?width,?height);????????????????markLines.forEach(function?(line)?{??????????????????line.drawMarker(baseCtx);??????????????????line.drawLinePath(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,.93)';??????????????var?prev?=?animationCtx.globalCompositeOperation;??????????????animationCtx.globalCompositeOperation?=?'destination-in';??????????????animationCtx.fillRect(0,?0,?width,?height);??????????????animationCtx.globalCompositeOperation?=?prev;????????????????for?(var?i?=?0;?i?<?markLines.length;?i++)?{??????????????????var?markLine?=?markLines[i];??????????????????markLine.drawMoveCircle(animationCtx);?//移動圓點??????????????}??????????};??????????var?addMarkLine?=?function?addMarkLine()?{??????????????markLines?=?[];??????????????var?dataset?=?options.data;??????????????dataset.forEach(function?(line,?i)?{??????????????????markLines.push(new?MarkLine({??????????????????????id:?i,??????????????????????from:?new?Marker({??????????????????????????city:?line.from.city,??????????????????????????location:?[line.from.lnglat[0],?line.from.lnglat[1]],??????????????????????????color:?options.colors[i]??????????????????????}),??????????????????????to:?new?Marker({??????????????????????????city:?line.to.city,??????????????????????????location:?[line.to.lnglat[0],?line.to.lnglat[1]],??????????????????????????color:?options.colors[i]??????????????????????})??????????????????}));??????????????});??????????};????????????//初始化??????????var?init?=?function?init(map,?options)?{??????????????merge(userOptions,?options);????????????????baseLayer?=?new?CanvasLayer({??????????????????map:?map,??????????????????update:?brush??????????????});????????????????animationLayer?=?new?CanvasLayer({??????????????????map:?map,??????????????????update:?render??????????????});????????????????(function?drawFrame()?{??????????????????requestAnimationFrame(drawFrame);??????????????????render();??????????????})();??????????};????????????init(map,?options);????????????self.options?=?options;??????};????????MoveLine.prototype.update?=?function?(resetOpts)?{??????????for?(var?key?in?resetOpts)?{??????????????this.options[key]?=?resetOpts[key];??????????}??????};????????return?MoveLine;????})));???
2、前段調用
a、數據格式
?
[javascript]?view plain?copy
{??????????????????????from:?{??????????????????????????city:?'廣州',??????????????????????????lnglat:?[113.270793,?23.135308]??????????????????????},??????????????????????to:?{??????????????????????????city:?'衡山',??????????????????????????lnglat:?[112.612787,?27.317599]??????????????????????}??????????????????}??
b、前段調用
?
[javascript]?view plain?copy
new?MoveLine(map,?{??????????????????????//marker點半徑??????????????????????markerRadius:?2,??????????????????????//marker點顏色,為空或null則默認取線條顏色??????????????????????markerColor:?null,??????????????????????//線條類型?solid、dashed、dotted??????????????????????lineType:?'solid',??????????????????????//線條寬度??????????????????????lineWidth:?2,??????????????????????//線條顏色??????????????????????colors:?['#F9815C',?'#F8AB60',?'#EDCC72',?'#E2F194',?'#94E08A',?'#4ECDA5'],??????????????????????//移動點半徑??????????????????????moveRadius:?3,??????????????????????//移動點顏色??????????????????????fillColor:?'#fff',??????????????????????//移動點陰影顏色??????????????????????shadowColor:?'#fff',??????????????????????//移動點陰影大小??????????????????????shadowBlur:?6,??????????????????????data:?data??????????????????});???
------------------------------------------------------------------------------https://blog.csdn.net/GISShiXiSheng/article/details/78148576?locationNum=11&fps=1
轉載于:https://my.oschina.net/u/1464512/blog/1801155
總結
以上是生活随笔為你收集整理的Openlayers4中实现动态线效果的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。