canvas模拟中国铁路运行图
原理说明
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模拟中国铁路运行图的更多相关文章
- 结合 CSS3 & Canvas 模拟人行走的效果
HTML5 和 CSS3 技术给 Web 带来了新的利器,点燃了 Web 开发人员的激情.所谓只有想不到,没有做不到,的确如此.下面给大家分享一个结合 CSS3 & Canvas 模拟人行走的 ...
- 经典!HTML5 Canvas 模拟可撕裂布料效果
这是一个模拟可撕裂布料效果的 HTML5 Canvas 应用演示,效果逼真.你会看到,借助 Canvas 的强大绘图和动画功能,只需很少的代码就能实现让您屏息凝神的效果. 温馨提示:为保证最佳的效果, ...
- 中国铁路基于Intel架构超大规模OpenStack行业云的性能优化研究
1. 项目简介 铁路作为一种大众化的交通工具和非常重要的货物运输方式,其业务规模庞大.覆盖全国.服务全国各族人民.铁路面向公众提供的服务业务,主要是客运和货运两大类,且每年365天.每天7*24小时连 ...
- html5打开摄像头并用canvas模拟拍照 - 转
<video id="video" width="640" height="480" autoplay></video&g ...
- html5打开摄像头并用canvas模拟拍照
网上很多关于用HTML5打开本地摄像头的文章,但各有瑕疵.根据我自己的亲身体验,我分享一下我用HTML5打开摄像头的经验. 废话不多说,直接看代码. HTML代码: <video id=&quo ...
- Scratch与物理·天文:模拟中国嫦娥探月工程,探索月球的背面!
北京时间2019年5月16日凌晨,国际顶级学术期刊<自然>(Nature)在线发表了一篇来自中国科学家的成果:中国的嫦娥四号月球探测器2019年1月3日在月球背面的冯卡门陨石坑(Von K ...
- canvas模拟重力效果
总结 速度和加速度是动画的基础元素,其中两者都是向量,包括了一个重要因素:方向. 要学会应用 分解 和 合成 ,将速度或加速度分解到x.y轴上,然后将每条轴上的加速度或速度相加,然后再分别与物体的位置 ...
- canvas 模拟小球上抛运动的物理效果
最近一直想用学的canvas做一个漂亮的小应用,但是,发现事情并不是想的那么简单.比如,游戏的逼真效果,需要自己来coding…… 所以,自己又先做了一个小demo,算是体验一下亲手打造物理引擎的感觉 ...
- 用Canvas,画中国国旗(Canvas基本知识点)
.getContext("2d")=======>获取绘图接口 //2d .beginPath()========>创建绘图路径开始点 .moveTo(x,y)==== ...
随机推荐
- mysql按关键词截取字符串
按关键字截取字符串 :substring_index(被截取字段,关键字,关键字出现的次数) eg:字符串:test.docx:test2.zip substring_index(file_name, ...
- Mysql学习笔记整理之引擎
mysql的引擎: myisam引擎 Mysql 5.5之前默认的存储引擎 数据.索引分别存储 (数据物理磁盘---索引物理磁盘) .MYD 存储数据 表级索 ...
- JS/JQuery 禁用超链接a
JS // 禁用超链接元素elem ; document.getElementById(elemID).setAttribute('disabled', 'disabled'); // 启用超链接元素 ...
- 【译】微软的Python入门教程(一)
Getting started with Python(Python入门) Overview 概述 The series of videos on Channel 9 is designed to h ...
- MongoDB 学习笔记之 TTL索引,部分索引和文本索引
TTL索引: TTL集合支持mongodb对存储的数据进行失效时间设置,经过指定的时间段后.或在指定的时间点过期,集合自动被mongod清除.这一特性有利于对一些只需要保存一定时间的数据信息进行存储, ...
- Android 横竖屏切换生命周期
默认情况下,屏幕会旋转并且会重新走生命周期. 1. 屏幕不旋转 在AndroidManifest文件中的对应Activity中配置android:screenOrientation=”landsc ...
- 03 python基础作业(一)
1.将['alex','eric',’rain’]用下划线拼接成字符串.(['alex','eric',123]呢?) li=['alex','eric','rain'] v='_'.join(li) ...
- 浅谈sqlserver的事务锁
锁的概述 一. 为什么要引入锁 多个用户同时对数据库的并发操作时会带来以下数据不一致的问题: 丢失更新 A,B两个用户读同一数据并进行修改,其中一个用户的修改结果破坏了另一个修改的结果,比如订票系统 ...
- Windows 10 更新后VMware Workstation pro无法运行 (无需卸载原版本VM)
问题 描述:当前Windows版本是win10-1903,VMware版本比较老旧是VMware Workstation Pro 15.0.4:国庆节后微软推送了一个新的更新补丁,10月10日更新之后 ...
- Vijos 1067守望者的烦恼
背景 守望者-warden,长期在暗夜精灵的的首都艾萨琳内担任视察监狱的任务,监狱是成长条行的,守望者warden拥有一个技能名叫“闪烁”,这个技能可以把她传送到后面的监狱内查看,她比较懒,一般不查看 ...