我的编程空间,编程开发者的网络收藏夹
学习永远不晚

怎么用HTML5 Canvas实现交互式地铁线路图

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

怎么用HTML5 Canvas实现交互式地铁线路图

这篇文章主要介绍怎么用HTML5 Canvas实现交互式地铁线路图,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!

  界面生成

  底层的p是通过ht.graph.GraphView组件生成的,然后就可以利用HTforWeb提供好的方法,调用canvas画笔随便绘制就好,先来看看怎么生成底层p:

  vardm=newht.DataModel();//数据容器

  vargv=newht.graph.GraphView(dm);//拓扑组件

  gv.addToDOM();//将拓扑图组件添加进body中

  addToDOM函数声明如下:

  addToDOM=function(){

  varself=this,

  view=self.getView(),

  style=view.style;

  document.body.appendChild(view);//将组件底层p添加到body中

  style.left='0';//默认组件是绝对定位,所以要设置位置

  style.right='0';

  style.top='0';

  style.bottom='0';

  window.addEventListener('resize',function(){self.iv();},false);//窗口变化事件

  }

  现在我就可以在这个p上乱涂乱画了~首先我获取下载好的地铁线路图上的点,我将它们放在subway.js中,这个js文件全部都是下载的内容,我没有做其他的改动,主要是将这些点根据线路来分分配添加到数组中,比如:

  mark_Point13=[];//线路数组内包含线路的起点和终点坐标以及这条线路的名称

  t_Point13=[];//换成站点数组内包含线路中的换乘站点坐标以及换成站点名称

  n_Point13=[];//小站点数组内包含线路中的小站点坐标以及小站点名称

  mark_Point13.push({name:'十三号线',value:[113.4973,23.1095]});

  mark_Point13.push({name:'十三号线',value:[113.4155,23.1080]});

  t_Point13.push({name:'鱼珠',value:[113.41548,23.10547]});

  n_Point13.push({name:'裕丰围',value:[113.41548,23.10004]});

  接下来来描绘地铁线路,我声明了一个数组lineNum,用来装js中所有的地铁线路的编号,以及一个color数组,用来装所有的地铁线的颜色,这些颜色的index与lineNum中地铁线编号的index是一一对应的:

  varlineNum=['1','2','3','30','4','5','6','7','8','9','13','14','32','18','21','22','60','68'];

  varcolor=['#f1cd44','#0060a1','#ed9b4f','#ed9b4f','#007e3a','#cb0447','#7a1a57',

  '#18472c','#008193','#83c39e','#8a8c29','#82352b','#82352b','#09a1e0','#8a8c29',

  '#82352b','#b6d300','#09a1e0'];

  接着遍历lineNum,将lineNum中的元素和颜色传到createLine函数中,根据这两个参数来绘制地铁线路以及配色,毕竟js文件中的命名方式也是有规律的,哪一条线路,则命名后面一定会加上对应的数字,所以我们只需要将字符串与这个编号结合即可获得js中对应的数组了:

  letlineName='Line'+num;

  letline=window[lineName];

  createLine的定义也非常简单,我的代码设置了不少的样式,所以看起来有点多。创建一个ht.Polyline管线,我们可以通过polyline.addPoint()函数向这个变量中添加具体的点,通过setSegments可以设置点的连接方式。

  functioncreateLine(num,color){//绘制地图线

  varpolyline=newht.Polyline();//多边形管线

  polyline.setTag(num);//设置节点tag标签,作为唯一标示

  if(num==='68')polyline.setToolTip('APM');//设置提示信息

  elseif(num==='60')polyline.setToolTip('GF');

  elsepolyline.setToolTip('Line'+num);

  if(color){

  polyline.s({//s为setStyle的简写,设置样式

  'shape.border.width':0.4,//设置多边形的边框宽度

  'shape.border.color':color,//设置多边形的边框颜色

  'select.width':0.2,//设置选中节点的边框宽度

  'select.color':color//设置选中节点的边框颜色

  });

  }

  letlineName='Line'+num;

  letline=window[lineName];

  for(leti=0;i<line.length;i++){

  for(letj=0;j<line[i].coords.length;j++){

  polyline.addPoint({x:line[i].coords[j][0]*300,y:-line[i].coords[j][1]*300});

  if(num==='68'){//APM线(有两条,但是点是在同一个数组中的)

  if(i===0&&j===0){

  polyline.setSegments([1]);

  }

  elseif(i===1&&j===0){

  polyline.getSegments().push(1);

  }

  else{

  polyline.getSegments().push(2);

  }

  }

  }

  }

  polyline.setLayer('0');//将线设置在下层,点设置在上层“top”

  dm.add(polyline);//将管线添加进数据容器中储存,不然这个管线属于“游离”状态,是不会显示在拓扑图上的

  returnpolyline;

  }

  上面代码中添加地铁线上的点有分为几种情况,是因为js中设置线的时候Line68有一个“跳跃”点的现象,所以我们必须“跳跃”过去,篇幅有限Line68数组具体的声明自行看subway.js。

  这里说明一点,如果用的是addPoint函数,不设置segments时,默认将添加进的点用直线连接,segments的定义如下:

  1:moveTo,占用1个点信息,代表一个新路径的起点

  2:lineTo,占用1个点信息,代表从上次最后点连接到该点

  3:quadraticCurveTo,占用2个点信息,第一个点作为曲线控制点,第二个点作为曲线结束点

  4:bezierCurveTo,占用3个点信息,第一和第二个点作为曲线控制点,第三个点作为曲线结束点

  5:closePath,不占用点信息,代表本次路径绘制结束,并闭合到路径的起始点

  所以我们要做“跳跃”的行为设置segments为1即可。

  最后绘制这些地铁线上的点,这个部分subway.js中也分离出来了,命名以“mark_Point”、“t_Point”以及“n_Point”开头,我在前面js的展示部分有对这些数组进行解释,大家动动中指划上去看看。

  我们在这些点的位置添加ht.Node节点,当节点一添加进dm数据容器中时,就会在拓扑图上显示,当然,前提是这个拓扑图组件gv设置的数据容器是这个dm。篇幅有限,添加地铁线上的点的代码部分我只展示添加“换乘站点”的点:

  vartName='t_Point'+num;

  vartP=window[tName];//大站点

  if(tP){//有些线路没有“换乘站点”

  for(leti=0;i<tP.length;i++){

  letnode=createNode(tP[i].name,tP[i].value,color[index]);//在获取的线路上的点的坐标位置添加节点

  node.s({//设置节点的样式style

  'label.scale':0.05,//文本缩放,可以避免浏览器限制的最小字号问题

  'label.font':'bold12pxarial,sans-serif'//设置文本的font

  });

  node.setSize(0.6,0.6);//设置节点大小。由于js中每个点之间的偏移量太小,所以我不得不把节点设置小一些

  node.setImage('images/旋转箭头.json');//设置节点的图片

  node.a('alarmColor1','rgb(150,150,150)');//attr属性,可以在这里面设置任何的东西,alarmColor1是在上面设置的image的json中绑定的属性,具体参看HTforWeb矢量手册(http://www.hightopo.com/guide/guide/core/vector/ht-vector-guide.html#ref_binding)

  node.a('alarmColor2','rgb(150,150,150)');//同上

  node.a('tpNode',true);//这个属性设置只是为了用来区分“换乘站点”和“小站点”的,后面会用上

  }

  }

  所有的地铁线路以及站点都添加完毕。但是!你可能会看不见自己绘制的图,因为他们太小了,这个时候可以设置graphView拓扑组件上的fitContent函数,我们顺便将拓扑图上的所有东西不可移动也设置一下:

  gv.fitContent(false,0.00001);//自适应大小,参数1为是否动画,参数2为gv与边框的padding值

  gv.setMovableFunc(function(){

  returnfalse;//设置gv上的节点不可移动

  });

  这下你的地铁线路图就可以显示啦~接下来看看交互。

  交互

  首先是鼠标移动事件,鼠标滑过具体线路时,线路会变粗,悬停一会儿还能看到这条线路的编号;当鼠标移动到“换乘站点”或“小站点”,站点对应的图标都会变大并且变色,字体也会变大,鼠标移开图标变回原来的颜色并且字体变小。不同点在于鼠标移动到“换乘站点”时,“换乘站点”会旋转。

  鼠标滑动事件,我直接基于gv的底层p进行的mousemove事件,通过ht封装的getDataAt函数传入事件event参数,获取事件下对应的节点,然后就可以随意操作节点了:

  gv.getView().addEventListener('mousemove',function(e){

  vardata=gv.getDataAt(e);//传入逻辑坐标点或者交互event事件参数,返回当前点下的图元

  if(name){

  originNode(name);//不管什么时候都要让节点保持原来的大小

  }

  if(datainstanceofht.Polyline){//判断事件节点的类型

  dm.sm().ss(data);//选中“管道”

  name='';

  clearInterval(interval);

  }

  elseif(datainstanceofht.Node){

  if(data.getTag()!==name&&data.a('tpNode')){//若不是同一个节点,并且mousemove的事件对象为ht.Node类型,那么设置节点的旋转

  interval=setInterval(function(){

  data.setRotation(data.getRotation()-Math.PI/16);//在自身旋转的基础上再旋转

  },100);

  }

  if(data.a('npNode')){//如果鼠标移到“小站点”也要停止动画

  clearInterval(interval);

  }

  expandNode(data,name);////自定义的放大节点函数,比较容易,我不粘代码了,可以去http://hightopo.com/查看

  dm.sm().ss(data);//设置选中节点

  name=data.getTag();//作为“上一个节点”的存储变量,可以通过这个值来获取节点

  }

  else{//其他任何情况则不选中任何内容并且清除“换乘站点”上的动画

  dm.sm().ss(null);

  name='';

  clearInterval(interval);

  }

  });

  鼠标悬停在地铁线路上时显示“具体线路信息”,我是通过设置tooltip来完成的(注意:要打开gv的tooltip开关):

  gv.enableToolTip();//打开tooltip的开关

  if(num==='68')polyline.setToolTip('APM');//设置提示信息

  elseif(num==='60')polyline.setToolTip('GF');

  elsepolyline.setToolTip('Line'+num);

  然后我利用右下角的form表单,单击表单上的具体线路,或者双击拓扑图上任意一个“站点”或者线路,则拓扑图会自适应到对应的部分,将被双击的部分展现到拓扑图的中央。

  form表单的声明部分我好像还没有解释。。。就是通过new一个ht.widget.FomePane类创建一个form表单组件,通过form.getView()获取表单组件的底层p,将这个p摆放在body右下角,然后通过addRow函数向form表单中添加一行的表单项,可以在这行中添加任意多个项,通过addRow函数的第二个参数(一个数组),对添加进的表单项进行宽度的设置,通过第三个参数设置这行的高度:

  functioncreateForm(){//创建右下角的form表单

  varform=newht.widget.FormPane();

  form.setWidth(200);//设置表单宽度

  form.setHeight(416);//设置表单高度

  letview=form.getView();

  document.body.appendChild(view);//将表单添加进body中

  view.style.zIndex=1000;

  view.style.bottom='10px';//ht组件几乎都设置绝对路径

  view.style.right='10px';

  view.style.background='rgba(211,211,211,0.8)';

  names.forEach(function(nameString){

  form.addRow([//向表单中添加行

  {//这一行中的第一个表单项

  button:{//向表单中添加button按钮

  icon:'images/Line'+nameString.value+'.json',//设置按钮的图标

  background:'',//设置按钮的背景

  borderColor:'',//设置按钮的边框颜色

  clickable:false//设置按钮不可点击

  }

  },

  {//第二个表单项

  button:{

  label:nameString.name,

  labelFont:'bold14pxarial,sans-serif',

  labelColor:'#fff',

  background:'',

  borderColor:'',

  onClicked:function(){//按钮点击回调事件

  gv.sm().ss(dm.getDataByTag(nameString.value));//设置选中按下的按钮对应的线路

  gv.fitData(gv.sm().ld(),true,5);//将选中的地铁线路显示在拓扑图的中央

  }

  }

  }

  ],[0.1,0.2],23);//第二个参数是设置第一参数中的数组的宽度,小于1是比例,大于1是实际宽度。第三个参数是该行的高度

  });

  }

  单击“站点”显示红色标注,双击节点自适应放置到拓扑图中央以及双击空白处将红色标注隐藏的内容都是通过对拓扑组件gv的事件监听来控制的,非常清晰易懂,代码如下:

  varnode=createRedLight();//创建一个新的节点,显示为“红灯”的样式

  gv.mi(function(e){//ht中拓扑组件中的事件监听

  if(e.kind==='clickData'&&(e.data.a('tpNode')||e.data.a('npNode'))){//e.kind获取当前事件类型,e.data获取当前事件下的节点

  node.s('2d.visible',true);//设置node节点可见

  node.setPosition(e.data.getPosition().x,e.data.getPosition().y);//设置node的坐标为当前事件下节点的位置

  }

  elseif(e.kind==='doubleClickData'){//双击节点

  gv.fitData(e.data,false,10);//将事件下的节点自适应到拓扑图的中央,参数1为自适应的节点,参数2为是否动画,参数3为gv与边框的padding

  }

  elseif(e.kind==='doubleClickBackground'){//双击空白处

  node.s('2d.visible',false);//设置node节点不可见查看HTforWeb样式手册(http://www.hightopo.com/guide/guide/core/theme/ht-theme-guide.html#ref_style)

  }

  });

  注意s(style)和a(attr)定义是这样的,s是ht预定义的一些样式属性,而a是我们用户来自定义的属性,一般是通过调用字符串来调用结果的,这个字符串对应的可以是常量也可以是函数,还是很灵活的。

  最后还做了一个小小的部分,选中“站点”,则该“站点”的上方会显示一个红色的会“呼吸”的用来注明当前选中的“站点”。

  “呼吸”的部分是利用ht的setAnimation函数来完成的,在用这个函数之前要先打开数据容器的动画开关,然后设置动画:

  dm.enableAnimation();//打开数据容器的动画开关

  functioncreateRedLight(){

  varnode=newht.Node();

  node.setImage('images/红灯.json');//设置节点的图片

  node.setSize(1,1);//设置节点的大小

  node.setLayer('firstTop');//设置节点显示在gv的最上层

  node.s('2d.visible',false);//节点不可见

  node.s('select.width',0);//节点选中时的边框为0,不可见

  node.s('2d.selectable',false);//设置这个属性,则节点不可选中

  node.setAnimation({//设置动画具体参见HTforWeb动画手册(http://www.hightopo.com/guide/guide/plugin/animation/ht-animation-guide.html)

  expandWidth:{

  property:"width",//设置这个属性,并且未设置accessType,则默认通过setWidth/getWidth来设置和获取属性。这里的width和下面的height都是通过前面设置的size得到的

  from:0.5,//动画开始时的属性值

  to:1,//动画结束时的属性值

  next:"collapseWidth"//字符串类型,指定当前动画完成之后,要执行的下个动画,可将多个动画融合

  },

  collapseWidth:{

  property:"width",

  from:1,

  to:0.5,

  next:"expandWidth"

  },

  expandHeight:{

  property:"height",

  from:0.5,

  to:1,

  next:"collapseHeight"

  },

  collapseHeight:{

  property:"height",

  from:1,

  to:0.5,

  next:"expandHeight"

  },

  start:["expandWidth","expandHeight"]//数组,用于指定要启动的一个或多个动画

  });

  dm.add(node);

  returnnode;

  }

以上是“怎么用HTML5 Canvas实现交互式地铁线路图”这篇文章的所有内容,感谢各位的阅读!希望分享的内容对大家有帮助,更多相关知识,欢迎关注编程网行业资讯频道!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

怎么用HTML5 Canvas实现交互式地铁线路图

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

基 HTML5 Canvas实现交互式地铁线路图的示例

这篇文章主要介绍了基 HTML5 Canvas实现交互式地铁线路图的示例,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。效果图 http://www.hightopo.com/
2023-06-09

怎么在html5中使用canvas 实现光线沿不规则路径运动

这篇文章将为大家详细讲解有关怎么在html5中使用canvas 实现光线沿不规则路径运动,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。svg让动画沿着不规则路径运动查阅svg文档后发现,sv
2023-06-09

使用canvas怎么实现橡皮筋式线条绘图应用

使用canvas怎么实现橡皮筋式线条绘图应用?相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。什么叫橡皮筋式指画图时橡皮筋一样伸缩自如。。例子如下:point_down:思路思路很
2023-06-09

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录