原理说明

1、在知道canvas画布尺寸的情况下,需要将地理经纬度信息转换为canvas画布x,y坐标,因为中国地图地理经纬度坐标取值范围为73.33-135.05(经度)37-50(维度),所以第一步需要确认的就是画布的中心位置,这里命名为centerX和centerY,同样的确认中国地图经纬度对应的中心位置,这里命名为positionX,positionY。

2、人为定义一个放大值range,这个值主要作用就是等比例的将中国地图在canvas画布中放大,range的数值需要根据画布横向尺寸跨度值与中国地图经纬度中经度跨度值相除来求解出来。

3、根据range值将中国地图等比例的在canvas画布上绘制出来。

4、获取地图上需要展示的轨迹经纬度信息,根据上述2,3在canvas画布上绘制出来。

5、定义一个rate值,用于表示在轨迹上运行物体的速度,为了能够保证运行物体轨迹沿着轨迹运行,需要在轨迹任意两个点之间求出横向宽度和纵向跨度,并且以跨度最大的那个为基准求解出轨迹上需要绘制多少个轨迹点,然后从过跨度较小的那个除以求解出来的轨迹点数量得出相应的速率。

6、在轨迹上点和横纵向运行速度确定之后,通过调用requestAnimationFrame函数实现标记点的运动。

效果图如下(图中轨迹经纬度信息纯属虚构)

中国地图绘制方法

function drawShapeOptionFun () {
// 绘制中国地图
chinaGeometry.features.forEach(function (chinaItem, chinaIndex) {
var length = chinaItem.geometry.coordinates.length;
var multipleBool = length > 1 ? true : false;
chinaItem.geometry.coordinates.forEach(function (chinaChildItem, wordItemIndex) {
if (multipleBool) {
// 值界可以使用的经纬度信息
if (chinaChildItem.length && chinaChildItem[0].length == 2) {
drawCanvasFun(chinaChildItem);
}
// 需要转换才可以使用的经纬度信息
if (chinaChildItem.length && chinaChildItem[0].length > 2) {
chinaChildItem.forEach(function (countryItem, countryIndex) {
drawCanvasFun(countryItem);
})
}
} else {
var countryPos = null;
if (chinaChildItem.length > 1) {
countryPos = chinaChildItem;
} else {
countryPos = chinaChildItem[0];
}
if (countryPos) {
drawCanvasFun(countryPos);
}
}
})
})
}
// canvas绘制平面
function drawCanvasFun (itemPosition) {
ctx.fillStyle = mapColor;
ctx.strokeStyle = mapLineColor;
ctx.beginPath();
ctx.moveTo(width / 2 + (itemPosition[0][0] - averageX) * range, height / 2 - (itemPosition[0][1] - averageY) * range);
itemPosition.forEach(function (item) {
ctx.lineTo(width / 2 + (item[0] - averageX) * range, height / 2 - (item[1] - averageY) * range);
})
ctx.fill();
ctx.stroke();
ctx.closePath();
}

中国地图上轨迹和轨迹上运行点坐标确认方法

function drawMetapFun (pointObj,index) {
ctx.shadowOffsetX = 0; // 设置水平位移
ctx.shadowOffsetY = 0; // 设置垂直位移
ctx.shadowBlur = 1; // 设置模糊度
ctx.shadowColor = pointObj.color; // 设置阴影颜色
ctx.strokeStyle = pointObj.color;
ctx.lineWidth = pointObj.lineWidth;
ctx.beginPath();
ctx.moveTo(width / 2 + (pointObj.data[0][0] - averageX) * range,height / 2 - (pointObj.data[0][1] - averageY) * range)
pointObj.data.forEach(function (item, index) {
if (index != 0) {
ctx.lineTo(width / 2 + (item[0] - averageX) * range,height / 2 - (item[1] - averageY) * range)
}
})
ctx.stroke();
// 轨迹上运行的点
ctx.shadowOffsetX = 0; // 设置水平位移
ctx.shadowOffsetY = 0; // 设置垂直位移
ctx.shadowBlur = 1; // 设置模糊度
ctx.shadowColor = pointObj.color; // 设置阴影颜色
ctx.fillStyle = pointObj.color;
ctx.beginPath();
ctx.arc(width / 2 + (pointPositionArray[index].data[pointPositionArray[index].index][0] - averageX) * range,
height / 2 - (pointPositionArray[index].data[pointPositionArray[index].index][1] - averageY) * range,
ballRadius,0,2*Math.PI);
// ctx.arc(pointPositionArray[index].data[pointPositionArray[index].index][0] + offsetX,pointPositionArray[index].data[pointPositionArray[index].index][1] + offsetY,ballRadius,0,2*Math.PI);
ctx.closePath();
ctx.fill();
if (pointPositionArray[index].index >= pointPositionArray[index].length - 1) {
pointPositionArray[index].index = 0;
}
pointPositionArray[index].index ++;
}
function getMetap (pointArray) {
pointArray.forEach(function (item) {
getMetapFun(item);
})
}
function getMetapFun (pointObj) {
var dataArray = [];
pointObj.data.forEach(function (item, index) {
metapXMax = item[0] > metapXMax ? item[0] : metapXMax;
metapYMax = item[1] > metapYMax ? item[1] : metapYMax;
metapXMin = item[0] < metapXMin ? item[0] : metapXMin;
metapYMin = item[1] < metapYMin ? item[1] : metapYMin;
if (index != 0) {
ctx.lineTo(item[0],item[1]);
space = Math.abs(space);
var diffX = item[0] - pointObj.data[index - 1][0];
var diffY = item[1] - pointObj.data[index - 1][1];
var num = 0;
var _space = 0;
dataArray.push[pointObj.data[index - 1][0],pointObj.data[index - 1][1]];
if (Math.abs(diffX) > Math.abs(diffY)) {
num = parseInt(Math.abs(diffX) / space);
_space = diffY / num;
space = diffX > 0 ? space : -space;
for (var i = 0; i < num; i ++) {
dataArray.push([pointObj.data[index - 1][0] + i * space,pointObj.data[index - 1][1] + i * _space])
}
} else {
num = parseInt(Math.abs(diffY) / space);
_space = diffX / num;
space = diffY > 0 ? space : -space;
for (var i = 0; i < num; i ++) {
dataArray.push([pointObj.data[index - 1][0] + i * _space,pointObj.data[index - 1][1] + i * space])
}
}
}
})
pointPositionArray.push({
index: 0,
length: dataArray.length,
data: dataArray
})
}

实例预览地址:canvas模拟中国铁路运行图

后话

希望上述讲解能够帮助到读者!!!

canvas模拟中国铁路运行图的更多相关文章

  1. 结合 CSS3 & Canvas 模拟人行走的效果

    HTML5 和 CSS3 技术给 Web 带来了新的利器,点燃了 Web 开发人员的激情.所谓只有想不到,没有做不到,的确如此.下面给大家分享一个结合 CSS3 & Canvas 模拟人行走的 ...

  2. 经典!HTML5 Canvas 模拟可撕裂布料效果

    这是一个模拟可撕裂布料效果的 HTML5 Canvas 应用演示,效果逼真.你会看到,借助 Canvas 的强大绘图和动画功能,只需很少的代码就能实现让您屏息凝神的效果. 温馨提示:为保证最佳的效果, ...

  3. 中国铁路基于Intel架构超大规模OpenStack行业云的性能优化研究

    1. 项目简介 铁路作为一种大众化的交通工具和非常重要的货物运输方式,其业务规模庞大.覆盖全国.服务全国各族人民.铁路面向公众提供的服务业务,主要是客运和货运两大类,且每年365天.每天7*24小时连 ...

  4. html5打开摄像头并用canvas模拟拍照 - 转

    <video id="video" width="640" height="480" autoplay></video&g ...

  5. html5打开摄像头并用canvas模拟拍照

    网上很多关于用HTML5打开本地摄像头的文章,但各有瑕疵.根据我自己的亲身体验,我分享一下我用HTML5打开摄像头的经验. 废话不多说,直接看代码. HTML代码: <video id=&quo ...

  6. Scratch与物理·天文:模拟中国嫦娥探月工程,探索月球的背面!

    北京时间2019年5月16日凌晨,国际顶级学术期刊<自然>(Nature)在线发表了一篇来自中国科学家的成果:中国的嫦娥四号月球探测器2019年1月3日在月球背面的冯卡门陨石坑(Von K ...

  7. canvas模拟重力效果

    总结 速度和加速度是动画的基础元素,其中两者都是向量,包括了一个重要因素:方向. 要学会应用 分解 和 合成 ,将速度或加速度分解到x.y轴上,然后将每条轴上的加速度或速度相加,然后再分别与物体的位置 ...

  8. canvas 模拟小球上抛运动的物理效果

    最近一直想用学的canvas做一个漂亮的小应用,但是,发现事情并不是想的那么简单.比如,游戏的逼真效果,需要自己来coding…… 所以,自己又先做了一个小demo,算是体验一下亲手打造物理引擎的感觉 ...

  9. 用Canvas,画中国国旗(Canvas基本知识点)

    .getContext("2d")=======>获取绘图接口 //2d .beginPath()========>创建绘图路径开始点 .moveTo(x,y)==== ...

随机推荐

  1. JVM 调优 - jstat

    Java命令学习系列(四)——jstat 2015-07-31 分类:Java 阅读(11041) 评论(1) 阿里大牛珍藏架构资料,点击链接免费获取 jstat(JVM Statistics Mon ...

  2. 1.python环境配置 - python基础入门

    工欲善其事必先利其器,python学习首先要做得就是配置python环境.配置环境只需要下载Pycharm 和 Anaconda两个安装包即可,请跟上我得步伐,一步一步操作. 重要的事情说三遍: 先安 ...

  3. 极光推送消息——RegistrationID方式

    1.工具类 package com.test.util; import cn.jiguang.common.resp.APIConnectionException; import cn.jiguang ...

  4. mysql数据库设计规则总结

    MySQL数据库设计总结   规则1:一般情况可以选择MyISAM存储引擎,如果需要事务支持必须使用InnoDB存储引擎. 注意:MyISAM存储引擎 B-tree索引有一个很大的限制:参与一个索引的 ...

  5. .Net Core 商城微服务项目系列(九):使用Jenkins构建自动发布

    1.首先通过Docker运行Consul,并保证各个服务都成功注册: 然后运行jenkins,对MI.Web项目进行发布构建,至于怎么配置之前已经写过了,和上一篇一模一样,这里贴下批处理命令: cd ...

  6. pip 修改镜像源为豆瓣源

    1. 修改配置文件 编辑配置文件,如果没有则新建: $ vi ~/.pip/pip.conf 添加内容如下: [global] index-url = https://pypi.doubanio.co ...

  7. 2.linux系统基础笔记(延时操作、实时系统中的定时器、事件)

    延时操作 延时操作是操作系统中经常遇到的一种情形.延时的原因很多,有的时候是为了等待外设芯片处理结束,有的时候是为了暂时释放cpu的使用权,有的就是为了希望在一段时间获取资源,如果没法在单位时间内获取 ...

  8. 隐身衣揭秘--java中继承/隐藏/覆写

    故事背景 看过<哈利·波特>的娃们,想必一定还记得电影中的“隐形斗篷”..这件隐形衣是哈利收到的圣诞礼物,也是死亡圣器中的三件套之一,它让哈利小盆友在执行任务的过程中简直是如虎添翼! 其实 ...

  9. 利用 turtle库绘制简单图形

    turtle库是python的基础绘图库,这个库被介绍为一个最常用的用来介绍编程知识的方法库,其主要是用于程序设计入门,是标准库之一,利用turtle可以制作很多复杂的绘图. turtle名称含义为“ ...

  10. python selenium鼠标滑动操作

    先安装pyautogui: pip install pyautogui #coding=utf-8 import pyautogui from selenium import webdriver fr ...