html5地图连线原理,基于html5技术绘制上海地铁图 – 双车道路况信息

上海地铁图的绘制,最近有客户提出了新的需求:双车道,并显示路网状态信息。经过一番研究,在原地铁图基础上做了扩展实现

5b929f231a20cb96f239f8d3ca2a8910.png

交通图介绍

路况状态在GIS系统中广泛应用,谷歌地图,百度地图都有实时路况的功能,太复杂并非好事,就像地铁图,按真实经纬度呈现反而不够直观,交通图、路网也是如此,去掉无关信息,将有限的数据(路,收费站,路况)展现出来,成为一种解决方案

百度地图中的路况信息

305c41384bd933fb658c610303303836.png

双车道的绘制

来看具体实现,原来的地铁图是一条线表示,改用双线绘制,可表现来往的方向,canvas并没有双线线形,需要自己实现

三种连接点类型

双线的算法类似2d中的stroke算法,stroke拐点有三种方式:尖的、圆角、斜面,考虑到路网拐角不会太尖,所以简单实现,采用miter方式,沿线各个拐点左右偏移

fa5034adf3648c975fd1b1dd6feed256.png

绘制双车道,计算拐点的法线和夹角

function drawDoubleLine(path, points, isDoubleLine, size, lineDirection) {

var p0, p1;

Q.forEach(points, function (p) {

if (!p1) {

p1 = p;

return;

}

p1._a = Math.atan2(p.y - p1.y, p.x - p1.x);

if (p0) {

p1.angle = Math.atan2(Math.sin(p0._a) + Math.sin(p1._a), Math.cos(p0._a) + Math.cos(p1._a));

p1.angle -= Math.PI / 2;

var theta = Math.abs(p1._a - p0._a);

if (theta > Math.PI) {

theta = 2 * Math.PI - theta;

}

p1.inclinedAngle = Math.PI - theta;

} else {

p1.angle = p1._a - Math.PI / 2;

}

p0 = p1;

p1 = p;

});

p1.angle = Math.atan2(p1.y - p0.y, p1.x - p0.x) - Math.PI / 2;

if (lineDirection == "left") {

drawLine(path, points, 0.5, size);

return;

}

if (lineDirection == "right") {

drawLine(path, points, -0.5, size);

return;

}

if (!isDoubleLine) {

drawLine(path, points, 0, size);

return;

}

drawLine(path, points, 0.5, size);

drawLine(path, points, -0.5, size);

}

绘制连线

function drawLine(path, points, yOffset, size, doubleLine) {

Q.forEach(points, function (p, index) {

var angle = p.angle;

var inclinedAngle = p.inclinedAngle;

var x = p.x, y = p.y;

var offset = yOffset;

if (offset) {

offset *= 2 / 3 * 0.8;

}

if (p.yOffset) {

offset += p.yOffset;

}

if (offset) {

offset *= size;

if (inclinedAngle) {

offset /= Math.max(0.2, Math.sin(inclinedAngle / 2));

}

var sin = Math.sin(angle);

var cos = Math.cos(angle);

x += cos * offset;

y += sin * offset;

}

if (index == 0) {

path.moveTo(x, y);

} else {

path.lineTo(x, y);

}

});

}

双车道呈现效果

1ea095d4882b0491d732e5bc6a30f51b.png

路况状态绘制

路况状态也是呈线条状,与路网绘制相同,只不过为单向,还是上面的绘制函数,参数lineDirection表示车道方向,左侧车道偏移50%,右侧则偏移-50%,这样可以实现两侧不同的状态

function drawDoubleLine(path, points, isDoubleLine, size, lineDirection) {

...

if (lineDirection == "left") {

drawLine(path, points, 0.5, size);

return;

}

if (lineDirection == "right") {

drawLine(path, points, -0.5, size);

return;

}

...

}

路况模拟数据

与原来的例子相同,路况信息也可以通过JSON数据加载,整个为一个array,集合中每个元素为一条路的路况片段信息,”line”属性表示所在路线的编号,”fragments”表示路况片段集合,每个片段包含三个属性,与路线的json表示相同,只不过增加了”direction”属性,表示片段的方向

[{

"line": "11",

"fragments": [

{

"color": "#FF0000",

"direction": "right",

"stations": [230, 231, 232]

},

{

"color": "#FFFF00",

"direction": "left",

"stations": [229, 230, 231, 232]

},

{

"color": "#00FF00",

"direction": "left",

"stations": [227, 228, 229]

}

]

}]

路况运行效果

上面11号线上的模拟数据,得到下面的效果

d1f6fce6ecdd6afde3598174c5a94fb8.png

在线演示

在线演示:http://demo.qunee.com/#Shanghai Metro Map 2012

示例下载:路况图示例.zip

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要实现基于HTML5的两个div自动连线,你可以使用Canvas元素和JavaScript编程来实现。以下是一个基本的实现思路: 1. 创建一个Canvas元素,并将其添加到HTML文档中。 2. 在Canvas上绘制两个div元素的中心点坐标。 3. 使用JavaScript代码计算两个div元素之间的距离和角度。 4. 将计算出来的距离和角度转换成Canvas中的坐标系坐标。 5. 在Canvas上使用绘函数绘制一条连接两个div元素的线。 下面是一个简单的代码示例,可以帮助你理解如何实现这个功能: HTML: ```html <div id="div1" style="width: 100px; height: 100px; background-color: red; position: absolute; left: 100px; top: 100px;"></div> <div id="div2" style="width: 100px; height: 100px; background-color: blue; position: absolute; left: 300px; top: 200px;"></div> <canvas id="canvas" style="position: absolute; left: 0; top: 0;"></canvas> ``` JavaScript: ```javascript var canvas = document.getElementById("canvas"); var ctx = canvas.getContext("2d"); var div1 = document.getElementById("div1"); var div2 = document.getElementById("div2"); var x1 = div1.offsetLeft + div1.offsetWidth / 2; var y1 = div1.offsetTop + div1.offsetHeight / 2; var x2 = div2.offsetLeft + div2.offsetWidth / 2; var y2 = div2.offsetTop + div2.offsetHeight / 2; var distance = Math.sqrt(Math.pow((x2 - x1), 2) + Math.pow((y2 - y1), 2)); var angle = Math.atan2((y2 - y1), (x2 - x1)); var x1_offset = Math.cos(angle) * div1.offsetWidth / 2; var y1_offset = Math.sin(angle) * div1.offsetHeight / 2; var x2_offset = Math.cos(angle) * div2.offsetWidth / 2; var y2_offset = Math.sin(angle) * div2.offsetHeight / 2; var x1_new = x1 + x1_offset; var y1_new = y1 + y1_offset; var x2_new = x2 - x2_offset; var y2_new = y2 - y2_offset; ctx.beginPath(); ctx.moveTo(x1_new, y1_new); ctx.lineTo(x2_new, y2_new); ctx.stroke(); ``` 这段代码实现了两个div元素之间的连线。你可以根据需要进一步修改和优化。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值