热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

java动态画线_Openlayers4中实现动态线效果

(function(global,factory){typeofexportsobject&&typeofmodule!undefined?module.exportsfactor

(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 &#61; (start[1] <&#61; end[1] ? 1 : -1) * Math.PI / 2;

} else {

//水平线

angle &#61; 0;

}

if (start[0] <&#61; end[0]) {

angle -&#61; deltaAngle;

dX &#61; Math.round(Math.cos(angle) * distance);

dY &#61; Math.round(Math.sin(angle) * distance);

mp[0] &#43;&#61; dX;

mp[1] &#43;&#61; dY;

} else {

angle &#43;&#61; deltaAngle;

dX &#61; Math.round(Math.cos(angle) * distance);

dY &#61; Math.round(Math.sin(angle) * distance);

mp[0] -&#61; dX;

mp[1] -&#61; dY;

}

return mp;

};

MarkLine.prototype.smoothSpline &#61; function (points, isLoop) {

var len &#61; points.length;

var ret &#61; [];

var distance &#61; 0;

for (var i &#61; 1; i 

distance &#43;&#61; this.getDistance(points[i - 1], points[i]);

}

var segs &#61; distance / 2;

segs &#61; segs 

for (var i &#61; 0; i 

var pos &#61; i / (segs - 1) * (isLoop ? len : len - 1);

var idx &#61; Math.floor(pos);

var w &#61; pos - idx;

var p0;

var p1 &#61; points[idx % len];

var p2;

var p3;

if (!isLoop) {

p0 &#61; points[idx &#61;&#61;&#61; 0 ? idx : idx - 1];

p2 &#61; points[idx > len - 2 ? len - 1 : idx &#43; 1];

p3 &#61; points[idx > len - 3 ? len - 1 : idx &#43; 2];

} else {

p0 &#61; points[(idx - 1 &#43; len) % len];

p2 &#61; points[(idx &#43; 1) % len];

p3 &#61; points[(idx &#43; 2) % len];

}

var w2 &#61; w * w;

var w3 &#61; 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 &#61; function (p0, p1, p2, p3, t, t2, t3) {

var v0 &#61; (p2 - p0) * 0.5;

var v1 &#61; (p3 - p1) * 0.5;

return (2 * (p1 - p2) &#43; v0 &#43; v1) * t3 &#43; (-3 * (p1 - p2) - 2 * v0 - v1) * t2 &#43; v0 * t &#43; p1;

};

MarkLine.prototype.getDistance &#61; function (p1, p2) {

return Math.sqrt((p1[0] - p2[0]) * (p1[0] - p2[0]) &#43; (p1[1] - p2[1]) * (p1[1] - p2[1]));

};

MarkLine.prototype.drawMarker &#61; function (context) {

this.from.draw(context);

this.to.draw(context);

};

MarkLine.prototype.drawLinePath &#61; function (context) {

var pointList &#61; this.path &#61; this.getPointList(map.getPixelFromCoordinate(this.from.location), map.getPixelFromCoordinate(this.to.location));

var len &#61; pointList.length;

context.save();

context.beginPath();

context.lineWidth &#61; options.lineWidth;

context.strokeStyle &#61; options.colors[this.id];

if (!options.lineType || options.lineType &#61;&#61; &#39;solid&#39;) {

context.moveTo(pointList[0][0], pointList[0][1]);

for (var i &#61; 0; i 

context.lineTo(pointList[i][0], pointList[i][1]);

}

} else if (options.lineType &#61;&#61; &#39;dashed&#39; || options.lineType &#61;&#61; &#39;dotted&#39;) {

for (var i &#61; 1; i 

context.moveTo(pointList[i - 1][0], pointList[i - 1][1]);

context.lineTo(pointList[i][0], pointList[i][1]);

}

}

context.stroke();

context.restore();

this.step &#61; 0; //缩放地图时重新绘制动画

};

MarkLine.prototype.drawMoveCircle &#61; function (context) {

var pointList &#61; this.path || this.getPointList(map.getPixelFromCoordinate(this.from.location), map.getPixelFromCoordinate(this.to.location));

context.save();

context.fillStyle &#61; options.fillColor;

context.shadowColor &#61; options.shadowColor;

context.shadowBlur &#61; 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 &#43;&#61; 1;

if (this.step >&#61; pointList.length) {

this.step &#61; 0;

}

};

//底层canvas渲染&#xff0c;标注&#xff0c;线条

var brush &#61; function brush() {

var baseCtx &#61; baseLayer.canvas.getContext(&#39;2d&#39;);

if (!baseCtx) {

return;

}

addMarkLine();

baseCtx.clearRect(0, 0, width, height);

markLines.forEach(function (line) {

line.drawMarker(baseCtx);

line.drawLinePath(baseCtx);

});

};

//上层canvas渲染&#xff0c;动画效果

var render &#61; function render() {

var animationCtx &#61; animationLayer.canvas.getContext(&#39;2d&#39;);

if (!animationCtx) {

return;

}

if (!animationFlag) {

animationCtx.clearRect(0, 0, width, height);

return;

}

animationCtx.fillStyle &#61; &#39;rgba(0,0,0,.93)&#39;;

var prev &#61; animationCtx.globalCompositeOperation;

animationCtx.globalCompositeOperation &#61; &#39;destination-in&#39;;

animationCtx.fillRect(0, 0, width, height);

animationCtx.globalCompositeOperation &#61; prev;

for (var i &#61; 0; i 

var markLine &#61; markLines[i];

markLine.drawMoveCircle(animationCtx); //移动圆点

}

};

var addMarkLine &#61; function addMarkLine() {

markLines &#61; [];

var dataset &#61; 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 &#61; function init(map, options) {

merge(userOptions, options);

baseLayer &#61; new CanvasLayer({

map: map,

update: brush

});

animationLayer &#61; new CanvasLayer({

map: map,

update: render

});

(function drawFrame() {

requestAnimationFrame(drawFrame);

render();

})();

};

init(map, options);

self.options &#61; options;

};

MoveLine.prototype.update &#61; function (resetOpts) {

for (var key in resetOpts) {

this.options[key] &#61; resetOpts[key];

}

};

return MoveLine;

})));



推荐阅读
  • XML介绍与使用的概述及标签规则
    本文介绍了XML的基本概念和用途,包括XML的可扩展性和标签的自定义特性。同时还详细解释了XML标签的规则,包括标签的尖括号和合法标识符的组成,标签必须成对出现的原则以及特殊标签的使用方法。通过本文的阅读,读者可以对XML的基本知识有一个全面的了解。 ... [详细]
  • FeatureRequestIsyourfeaturerequestrelatedtoaproblem?Please ... [详细]
  • Spring特性实现接口多类的动态调用详解
    本文详细介绍了如何使用Spring特性实现接口多类的动态调用。通过对Spring IoC容器的基础类BeanFactory和ApplicationContext的介绍,以及getBeansOfType方法的应用,解决了在实际工作中遇到的接口及多个实现类的问题。同时,文章还提到了SPI使用的不便之处,并介绍了借助ApplicationContext实现需求的方法。阅读本文,你将了解到Spring特性的实现原理和实际应用方式。 ... [详细]
  • 推荐系统遇上深度学习(十七)详解推荐系统中的常用评测指标
    原创:石晓文小小挖掘机2018-06-18笔者是一个痴迷于挖掘数据中的价值的学习人,希望在平日的工作学习中,挖掘数据的价值, ... [详细]
  • 自动轮播,反转播放的ViewPagerAdapter的使用方法和效果展示
    本文介绍了如何使用自动轮播、反转播放的ViewPagerAdapter,并展示了其效果。该ViewPagerAdapter支持无限循环、触摸暂停、切换缩放等功能。同时提供了使用GIF.gif的示例和github地址。通过LoopFragmentPagerAdapter类的getActualCount、getActualItem和getActualPagerTitle方法可以实现自定义的循环效果和标题展示。 ... [详细]
  • 标题: ... [详细]
  • ASP.NET2.0数据教程之十四:使用FormView的模板
    本文介绍了在ASP.NET 2.0中使用FormView控件来实现自定义的显示外观,与GridView和DetailsView不同,FormView使用模板来呈现,可以实现不规则的外观呈现。同时还介绍了TemplateField的用法和FormView与DetailsView的区别。 ... [详细]
  • Go GUIlxn/walk 学习3.菜单栏和工具栏的具体实现
    本文介绍了使用Go语言的GUI库lxn/walk实现菜单栏和工具栏的具体方法,包括消息窗口的产生、文件放置动作响应和提示框的应用。部分代码来自上一篇博客和lxn/walk官方示例。文章提供了学习GUI开发的实际案例和代码示例。 ... [详细]
  • 本文介绍了iOS数据库Sqlite的SQL语句分类和常见约束关键字。SQL语句分为DDL、DML和DQL三种类型,其中DDL语句用于定义、删除和修改数据表,关键字包括create、drop和alter。常见约束关键字包括if not exists、if exists、primary key、autoincrement、not null和default。此外,还介绍了常见的数据库数据类型,包括integer、text和real。 ... [详细]
  • 基于dlib的人脸68特征点提取(眨眼张嘴检测)python版本
    文章目录引言开发环境和库流程设计张嘴和闭眼的检测引言(1)利用Dlib官方训练好的模型“shape_predictor_68_face_landmarks.dat”进行68个点标定 ... [详细]
  • 网址:https:vue.docschina.orgv2guideforms.html表单input绑定基础用法可以通过使用v-model指令,在 ... [详细]
  • 如何在HTML中获取鼠标的当前位置
    本文介绍了在HTML中获取鼠标当前位置的三种方法,分别是相对于屏幕的位置、相对于窗口的位置以及考虑了页面滚动因素的位置。通过这些方法可以准确获取鼠标的坐标信息。 ... [详细]
  • 本文介绍了pack布局管理器在Perl/Tk中的使用方法及注意事项。通过调用pack()方法,可以控制部件在显示窗口中的位置和大小。同时,本文还提到了在使用pack布局管理器时,应注意将部件分组以便在水平和垂直方向上进行堆放。此外,还介绍了使用Frame部件或Toplevel部件来组织部件在窗口内的方法。最后,本文强调了在使用pack布局管理器时,应避免在中间切换到grid布局管理器,以免造成混乱。 ... [详细]
  • Gitlab接入公司内部单点登录的安装和配置教程
    本文介绍了如何将公司内部的Gitlab系统接入单点登录服务,并提供了安装和配置的详细教程。通过使用oauth2协议,将原有的各子系统的独立登录统一迁移至单点登录。文章包括Gitlab的安装环境、版本号、编辑配置文件的步骤,并解决了在迁移过程中可能遇到的问题。 ... [详细]
  • Android获取app应用程序大小的方法
    Android获取app应用程序大小的方法-Android对这种方法进行了封装,我们没有权限去调用这个方法,所以我们只能通过AIDL,然后利用Java的反射机制去调用系统级的方法。 ... [详细]
author-avatar
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有