百度Echarts实例地址:

http://echarts.baidu.com/examples.html

同事想做一个地图,地图上的几个点通过动态的线连接起来。但是在实例里没找到类似的。

然后仔细分析了一下 《公交路线图》(下图)这个,查看它的数据源结构,是一长串的坐标数组:

如果我把这个长数组缩短为2个坐标,就是起点+终点,那么是不是就是我需要的结果?试了一下:

果然是这样,效果丑了点,但是看得过去。通过这个实验发现这个图的原理就是你定义一条 line ,echarts会根据你提供的坐标绘制路径。然后在选项里他实际上绘制了2遍,一遍是浅色半透明的路径,一遍是移动的光点。

然后并不满足于此,因为看到别人的图这个路径是平滑的曲线。大致找了一下api,没有找到类似的可以直接配置的选项。然后看到有一个实例是绘制各种不同的路径曲线,它的实现靠自己定义一个路径函数,生成坐标数组。然后想了一下,决定自己实现一个。

实现功能:

  • 提供两点坐标A,B,可以确定以线段AB为弦,弧度为π/6(根据自己需要调整,最大π)的圆。

          // arc 为弧AB的弧度
    function getCircleRadio(A, B, arc) {
    return Math.sqrt(Math.pow(B[0]-A[0], 2)+Math.pow(B[1]-A[1], 2)) / (2*Math.sin(arc/2));
    }
  • 计算出半径R,圆心坐标O

    这是个高中数学题啊?赶紧拿起笔开始算公式。经过一系列简(bai)单(du)推(sou)算(suo),可以得到一个二元二次方程组:

    • y0 - ym = k(x0 - xm) ; 过圆心O与AB中点M的直线斜率k,k根据AB的斜率算出(垂直)
    • (x0-xa)² + (y0-ya)² = r²;圆的方程

    经过消元得到一元二次方程,然后确定系数 a,b,c,直接求出两个根。这里我们只取其中一个,比如负根,这样圆心会在左侧。

    (这里我没有自己化简。。是直接百度来的。深刻认识到自己数学知识的匮乏)

      function getCircleOrigin(A, B, r) {
    var x0 = 0, y0 = 0;
    if (A[0] == B[0]) {
    x0 = A[0] - Math.sqrt( r*r - Math.pow((B[1]-A[1]/2), 2));
    y0 = (A[1] + B[1])/2;
    } else if (A[1] == B[1]) {
    x0 = (A[0] + B[0])/2;
    y0 = A[1] + Math.sqrt( r*r - Math.pow((B[0]-A[0]/2), 2));
    } else {
    var M = [(A[0] + B[0])/2, (A[1] + B[1])/2],
    k = (A[0]-B[0])/(B[1]-A[1]),
    a = 1.0 + k * k,
    b = -2 * M[0] - k * k * (A[0] + B[0]),
    c = M[0] * M[0] + k * k * (A[0] + B[0]) * (A[0] + B[0]) / 4.0 - (r * r - ((M[0] - A[0]) * (M[0] - A[0]) + (M[1] - A[1]) * (M[1] - A[1])));
    x0 = (-1.0 * b - Math.sqrt(b * b -4 * a * c)) / (2 * a);
    y0 = k * x0 - k * M[0] + M[1];
    }
    return [x0, y0];
    }
  • 把弧AB等分,返回这n个坐标

    根据圆的坐标点公式:

    • y = y0 + r*sin(rad)

    • x = x0 + r*cos(rad)

      考虑到坐标系不同我把sin和cos换了一下,这里需要先算出端点A的初始弧度 :

        // 半径
      var R = getCircleRadio(A, B, arc);
      // 圆心坐标
      var Ori = getCircleOrigin(A, B, R)
      for (var i=0; i<n; i++) {
      // 等分弧度
      var angl = arc*i / n,
      // 初始弧度
      arc0 = Math.asin((A[0]-Ori[0])/R);
      var x = Ori[0] + Math.sin(arc0 + angl)*R;
      var y = Ori[1] + Math.cos(arc0 + angl)*R;
      points.push([x, y]);
      }

然后贴上完整代码(在百度的实例里粘贴可以看到效果):

	app.title = '北京公交路线 - 线特效';

function getData(point) {
var A = point[0],
B = point[1],
n = 30,
arc = Math.PI / 4,
points = []; function getCircleRadio(A, B, arc) {
return Math.sqrt(Math.pow(B[0]-A[0], 2)+Math.pow(B[1]-A[1], 2)) / (2*Math.sin(arc/2));
} function getCircleOrigin(A, B, r) {
var x0 = 0, y0 = 0;
if (A[0] == B[0]) {
x0 = A[0] - Math.sqrt( r*r - Math.pow((B[1]-A[1]/2), 2));
y0 = (A[1] + B[1])/2;
} else if (A[1] == B[1]) {
x0 = (A[0] + B[0])/2;
y0 = A[1] + Math.sqrt( r*r - Math.pow((B[0]-A[0]/2), 2));
} else {
var M = [(A[0] + B[0])/2, (A[1] + B[1])/2],
k = (A[0]-B[0])/(B[1]-A[1]),
a = 1.0 + k * k,
b = -2 * M[0] - k * k * (A[0] + B[0]),
c = M[0] * M[0] + k * k * (A[0] + B[0]) * (A[0] + B[0]) / 4.0 - (r * r - ((M[0] - A[0]) * (M[0] - A[0]) + (M[1] - A[1]) * (M[1] - A[1])));
x0 = (-1.0 * b - Math.sqrt(b * b -4 * a * c)) / (2 * a);
y0 = k * x0 - k * M[0] + M[1];
}
return [x0, y0];
}
var R = getCircleRadio(A, B, arc);
var Ori = getCircleOrigin(A, B, R)
for (var i=0; i<n; i++) {
var angl = arc*i / n,
arc0 = Math.asin((A[0]-Ori[0])/R);
var x = Ori[0] + Math.sin(arc0 + angl)*R;
var y = Ori[1] + Math.cos(arc0 + angl)*R;
points.push([x, y]);
}
return points;
} $.get('data/asset/data/lines-bus.json', function(data) {
var hStep = 300 / (data.length - 1);
var busLines = [{
coords: getData([[116.4383, 40.1471], [120.5383, 23.1471]]),
lineStyle: {
normal: {
color: echarts.color.modifyHSL('#5A94DF', Math.round(350))
}
}
},
{
coords: getData([[116.4383, 40.1471], [114.5383, 25.1471]]),
lineStyle: {
normal: {
color: echarts.color.modifyHSL('#5A94DF', Math.round(160))
}
}
},
{
coords: getData([[116.4383, 40.1471], [118.5383, 33.1471]]),
lineStyle: {
normal: {
color: echarts.color.modifyHSL('#5A94DF', Math.round(140))
}
}
},
{
coords: getData([[116.4383, 40.1471], [123.5383, 28.1471]]),
lineStyle: {
normal: {
color: echarts.color.modifyHSL('#5A94DF', Math.round(250))
}
}
}];
myChart.setOption(option = {
bmap: {
center: [116.46, 29.92],
zoom: 6,
roam: true,
mapStyle: {
'styleJson': [
{
'featureType': 'water',
'elementType': 'all',
'stylers': {
'color': '#031628'
}
},
{
'featureType': 'land',
'elementType': 'geometry',
'stylers': {
'color': '#000102'
}
},
{
'featureType': 'highway',
'elementType': 'all',
'stylers': {
'visibility': 'off'
}
},
{
'featureType': 'arterial',
'elementType': 'geometry.fill',
'stylers': {
'color': '#000000'
}
},
{
'featureType': 'arterial',
'elementType': 'geometry.stroke',
'stylers': {
'color': '#0b3d51'
}
},
{
'featureType': 'local',
'elementType': 'geometry',
'stylers': {
'color': '#000000'
}
},
{
'featureType': 'railway',
'elementType': 'geometry.fill',
'stylers': {
'color': '#000000'
}
},
{
'featureType': 'railway',
'elementType': 'geometry.stroke',
'stylers': {
'color': '#08304b'
}
},
{
'featureType': 'subway',
'elementType': 'geometry',
'stylers': {
'lightness': -70
}
},
{
'featureType': 'building',
'elementType': 'geometry.fill',
'stylers': {
'color': '#000000'
}
},
{
'featureType': 'all',
'elementType': 'labels.text.fill',
'stylers': {
'color': '#857f7f'
}
},
{
'featureType': 'all',
'elementType': 'labels.text.stroke',
'stylers': {
'color': '#000000'
}
},
{
'featureType': 'building',
'elementType': 'geometry',
'stylers': {
'color': '#022338'
}
},
{
'featureType': 'green',
'elementType': 'geometry',
'stylers': {
'color': '#062032'
}
},
{
'featureType': 'boundary',
'elementType': 'all',
'stylers': {
'color': '#465b6c'
}
},
{
'featureType': 'manmade',
'elementType': 'all',
'stylers': {
'color': '#022338'
}
},
{
'featureType': 'label',
'elementType': 'all',
'stylers': {
'visibility': 'off'
}
}
]
}
},
series: [{
type: 'lines',
coordinateSystem: 'bmap',
polyline: true,
data: busLines,
silent: true,
lineStyle: {
normal: {
// color: '#c23531',
// color: 'rgb(200, 35, 45)',
opacity: 0.3, width: 2
}
},
progressiveThreshold: 500,
progressive: 200
}, {
type: 'lines',
coordinateSystem: 'bmap',
polyline: true,
data: busLines,
lineStyle: {
normal: {
width: 0
}
},
effect: {
constantSpeed: 50,
show: true,
trailLength: 0.5,
symbolSize: 2
},
zlevel: 1
}]
});
});

效果图:

留点尾巴

这里直接用了百度地图api,各个点的坐标也是实际的经纬度。按我理解应该可以定义自己的坐标系,然后选择自己的地图,不过具体怎么实现没有再深入研究。

Baidu - Echarts 地图实例测试,并绘制平滑圆弧路径的更多相关文章

  1. Echarts地图绘制(散点,色卡)

    echarts绘制地图时,提供了js内部注册,也提供了json数据手动注册,这两种都可以绘制对应地图,但有一点不同的是,js内部只注册了中国地图和世界地图,而json数据提供了世界,中国,中国城市的数 ...

  2. echarts地图边界数据的实时获取与应用,省市区县多级联动【附最新geoJson文件下载】

    首先,来看下效果图 在线体验地址:https://hxkj.vip/demo/echartsMap/,并提供实时geoJson数据文件下载 echarts官方社区链接地址(可在线编辑):https:/ ...

  3. echarts地图扩展文件使用geoJson格式。

    echarts地图扩展文件使用geoJson格式. 1.在线生成 http://ecomfe.github.io/echarts-map-tool/  这里可以生成省市区的json,但是最多生成到”区 ...

  4. react使用echarts地图实现中国地图大区展示

    日常项目中经常会用到百度地图或者echarts图标展示,今天给大家展示的是如何在react开发项目中使用百度echars的地图展示,把中国地图分为东北大区.华东大区.华南大区.华西大区.华中大区以及华 ...

  5. 本周学习总结(原生+Echarts地图)

    本周主要想完成工作中大屏地图相关的知识,所以学习的时间不是很长 dsa.js(数据结构) 拖了两个星期还没看,等啥时候继续研究算法和数据结构再看源码 GoJS 有时间要好好研究下 https://gi ...

  6. Vue项目(vuecli3.0搭建)集成高德地图实现路线轨迹绘制

    先看最后实现的效果图 高德地图api文档 https://lbs.amap.com/api/javascript-api/summary 使用 1.在index.html里面引入高德地图js文件 2. ...

  7. Echart 地图实例

    1.地图实例 function func_InEchart() { require.config({ paths: { echarts: '../Scripts/echart2/echarts' }, ...

  8. 如何获取google地图、baidu百度地图的坐标

    google:打开google地图-->查找目的地-->右键:此位置居中-->地址栏键入javascript:void(prompt('',gApplication.getMap() ...

  9. Win7搭建nginx+php+mysql开发环境以及websocket聊天实例测试

    Win7搭建nginx+php+mysql开发环境以及websocket聊天实例测试一.下载相关安装包 1.下载nginx最新版本(nginx1.3.13版之后才支持websocket协议) 下载地址 ...

随机推荐

  1. 一个很有参考意义的unity博客

    http://blog.csdn.net/lyh916/article/details/45133101

  2. linux命令学习笔记(57):ss命令

    ss是Socket Statistics的缩写.顾名思义,ss命令可以用来获取socket统计信息,它可以显示和netstat 类似的内容.但ss的优势在于它能够显示更多更详细的有关TCP和连接状态的 ...

  3. xxx was built without full bitcode" 编译错误解决

    xxx was built without full bitcode" 编译错误解决 iOS 打包上线 All object files and libraries for bitcode ...

  4. FEC(Forward Error Correction)前向纠错 UDP\RTP 中使用用于改善无线等网络丢包等问题--转

    FEC(Forward Error Correction)前向纠错 UDP\RTP 中使用用于改善无线等网络丢包等问题 算法暂不介绍. 思路:FEC ENCODE 增加冗余包,当无线等网络丢包之后,接 ...

  5. sql split函数

    --DROP FUNCTION F_SQLSERVER_SPLIT GO CREATE FUNCTION F_SQLSERVER_SPLIT(@Long_str varchar(8000),@spli ...

  6. bzoj 2160: 拉拉队排练 回文自动机

    题目: Description 艾利斯顿商学院篮球队要参加一年一度的市篮球比赛了.拉拉队是篮球比赛的一个看点,好的拉拉队往往能帮助球队增加士气,赢得最终的比赛.所以作为拉拉队队长的楚雨荨同学知道,帮助 ...

  7. java枚举学习enum

    java 1.5以后才出现enum的关键字 所有的enum类都继承自Enum类,所以enum类无法再继承其他的类,可以实现接口,枚举类出了不能被继承其余的与普通类的特性一致, 枚举类的构造函数只能自己 ...

  8. Puppet master nginx 扩展提升性能(puppet自动化系列4)

    puppet使用SSL(https)协议来进行通讯,默认情况下,puppet server端使用基于Ruby的WEBRick HTTP服务器.由于WEBRick HTTP服务器在处理agent端的性能 ...

  9. 时间倒计时 JS

    <div id="keleyi">Christmas Countdown</div> <script type="text/javascri ...

  10. 【总结整理】javascript的函数在if中调用时是否加括号---与.net的不同之处

    javascript的函数调用时是否加括号 if(event.preventDefault){ event.preventDefault(); if判断条件里面不要加括号,不加括号是应该以属性形式,i ...