生活随笔
收集整理的這篇文章主要介紹了
小程序之基于canvas绘制高铁线路图
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
前幾天@天下雪 給了我一張高鐵的路線圖,問我能不能用canvas畫出來,所以我就試了試,我的思路可能比較復雜;如果有更簡單的思路可以留言回復;
關注微信公眾號,獲取源碼和教程
?
下面說一下我的實現思路:
?
1、首先是每個站點圓角矩形的繪制,一開始想著用canvas把圓角矩形繪制出來,但發現小程序暫時還沒有繪制圓角的arcTo方法,所以用canvas繪制就相對比較麻煩,最后為了方便決定用圖片代替;?
2、將整個路線圖分為四個小圖片,(1)站點圓角矩形(2)站點之間的直連線(3)站點之間右側彎曲連線(4)站點之間左側彎曲連線;?
3、通過觀察分析,將繪制過程分為兩步,(1)奇數行圓角矩形、連線的繪制點x坐標是從左至右遞增,y坐標值是行數乘以某個固定值(2)偶數行圓角矩形、連線的繪制點x坐標是從左至右遞減,y坐標值是行數乘以某個固定值?
4、奇數行,偶數行的圓角矩形的下標index+1是3的倍數的話,奇數行當前下標右側繪制右彎曲連線圖片,偶數行當前下標左側繪制左彎曲連線圖片;?
5、整個canvas繪制區域在不同手機上的適配?
6、具體的一些細節請參照代碼注釋?
7、開發工具上使用drawImage重復繪制同一張圖片只顯示第一次繪制的位置,暫時不知道什么原因,所以請在真機上測試;?
8、有什么不足之處,望大家多多指點!感激!?
wxml代碼:
<!--pages/Gline/index.wxml--> <viewclass="g-title">(G23)選擇出發站點<textclass="chooseStation">{{chooseStation}}</text></view> <canvasbindtouchstart="touchS"canvas-id="map"style='width:{{canvWidth}}rpx;height:{{canvHeight}}px;background-color:#eee'/>
wxss代碼:
/* pages/Gline/index.wxss */
page{ background-color: #eeeeee }
.g-title{font-size: 36rpx;font-weight: 600;color: #768da4;padding: 36rpx 0;padding-left: 20rpx; background-color: #fff}
.chooseStation{color: #32b16c}
js代碼:
[javascript] view plaincopy
js代碼:??????Page({????data:{??????canvWidth:750,??????canvHeight:750,??????stations:['北京南','天津南','濟南西','泰安','滕州東','徐州東','南京南','鎮江南','蘇州北','上海虹橋','北京南','天津南','濟南西','泰安','滕州東','徐州東','南京南','鎮江南','蘇州北','上海虹橋','北京南','天津南','濟南西','泰安','滕州東','徐州東','南京南','鎮江南','蘇州北','上海虹橋'],??????chooseStation:'',??????prevChooseIdx:null,??????????},????onLoad:function(options){??????????????????const?ctx?=?wx.createCanvasContext('map');??????this.ctx?=?ctx;??????this.column?=?3;??????this.offsetTop?=?30;??????this.rect={????????img_b:'/images/rect-b.png',????????img_g:'/images/rect-g.png',????????height:32,????????width:68??????}??????this.line?=?{????????img:'/images/line.png',????????height:6,????????width:30??????},??????this.bendLine?=?{????????img_l:'/images/line_l.png',????????img_r:'/images/line_r.png',????????height:70,????????width:20??????},??????this.rectArr=[];??????this.oddRowIndexArr=[];??????this.evenRowIndexArr=[];??????this.initMap();????},????onReady:function(){????},????onShow:function(){??????????},????onHide:function(){??????????},????onUnload:function(){??????????},????????adaptiveScreenSize:function(o){??????let?ww?=?this.data.winWidth;??????let?zoom?=?ww/375;??????this.setData({zoom:zoom});??????let?rectW?=?o.width*zoom;??????let?rectH?=?o.height*zoom;??????o.width?=?rectW;??????o.height?=?rectH;????},????????initMap:function(){??????const?that?=?this;??????wx.getSystemInfo({????????success:?function(res){??????????const?ww?=?res.windowWidth;??????????const?pr?=?res.pixelRatio;??????????that.setData({?winWidth:ww,pixelRatio:pr});??????????that.drawMap();????????}??????})????},????drawTxtAtPos:function(idx){??????const?rectArr?=?this.rectArr;??????const?w?=?this.rect.width;??????const?h?=?this.rect.height;??????let?txt?=?this.data.stations[idx];??????let?len?=?txt.length;????????????let?fontSize?=?len>3?12:14;??????let?x?=?rectArr[idx].x;??????let?y?=?rectArr[idx].y;??????????????????let?txt_x?=?Math.floor((w?-?len*fontSize)/2)+x;??????let?txt_y?=?Math.floor(h/2+fontSize/2)+y-2;??????this.ctx.setFontSize(fontSize);??????this.ctx.setFillStyle('#ffffff')??????this.ctx.fillText(txt,?txt_x,?txt_y);????},????????initRect:function(idx){??????const?rectArr?=?this.rectArr;??????let?x?=?rectArr[idx].x;??????let?y?=?rectArr[idx].y;??????this.ctx.drawImage(this.rect.img_b,x,?y,?this.rect.width,?this.rect.height);????},????????initCanvHeight:function(){??????let?len?=?this.data.stations.length;??????let?pr?=?this.data.pixelRatio;??????let?z?=?this.data.zoom;??????let?row?=?Math.ceil(len/this.column);??????let?h?=?0;??????if(row?<=?1){????????console.log(this.rect.height);????????h?=?(this.offsetTop*2?+?this.rect.height)*2;??????}else{?????????h?=?this.offsetTop*2+(row-1)*(this.bendLine.height-this.line.height)+this.rect.height;??????}?????this.setData({canvHeight:h});????},????????drawLine:function(){??????const?rectArr?=?this.rectArr;??????let?x=0,y=0;???????if(rectArr.length==2){??????????x?=?rectArr[0].x+this.rect.width;??????????y?=?rectArr[0].y+Math.floor((this.rect.height-this.line.height)/2);??????????this.ctx.drawImage(this.line.img,?x,?y,?this.line.width,?this.line.height);??????}else{????????const?odd?=?this.oddRowIndexArr;????????const?even?=?this.evenRowIndexArr;????????if(odd.length>0){??????????for(let?i=0;i<odd.length;i++){????????????if((odd+1)!=rectArr.length){??????????????x?=?rectArr[odd].x+this.rect.width;??????????????y?=?rectArr[odd].y+Math.floor((this.rect.height-this.line.height)/2);??????????????if((odd+1)%this.column!=0){????????????????this.ctx.drawImage(this.line.img,?x,?y,?this.line.width,?this.line.height);??????????????}else{????????????????this.ctx.drawImage(this.bendLine.img_r,?x,?y,?this.bendLine.width,?this.bendLine.height);??????????????}????????????}??????????}????????}????????????????if(even.length>0){??????????for(let?i=0;i<even.length;i++){????????????if((even+1)!=rectArr.length){??????????????y?=?rectArr[even].y+Math.floor((this.rect.height-this.line.height)/2);??????????????if((even+1)%this.column!=0){????????????????x?=?rectArr[even].x-this.line.width;????????????????this.ctx.drawImage(this.line.img,?x,?y,?this.line.width,?this.line.height);??????????????}else{????????????????x?=?rectArr[even].x-this.bendLine.width;????????????????this.ctx.drawImage(this.bendLine.img_l,?x,?y,?this.bendLine.width,?this.bendLine.height);??????????????}????????????}??????????}????????}??????}????},????drawMap:function(){??????this.adaptiveScreenSize(this.rect);??????this.adaptiveScreenSize(this.line);??????this.adaptiveScreenSize(this.bendLine);??????this.initCanvHeight();??????this.createRectTopPoints();??????????????const?rectArr?=?this.rectArr;?????????for(let?i=0;i<rectArr.length;i++){??????????this.initRect(i);??????????this.drawTxtAtPos(i);????????}????????this.ctx.draw(true);????????????this.drawLine();??????this.ctx.draw(true);????},????????????getDisXArr:function(){??????let?arr?=?[];??????let?ww?=?this.data.winWidth;??????let?disX?=?Math.floor((ww-(this.column*this.rect.width+(this.column-1)*this.line.width))/2);???????for(let?i=0;i<this.column;i++){????????let?x?=?disX+i%this.column*(this.rect.width+this.line.width);????????arr?=?x;??????}????????return?arr;????},????????createRectTopPoints:function(){??????let?rectArr?=?[];??????let?disXArr?=?this.getDisXArr();??????let?disXArrRev?=?this.getDisXArr().reverse();??????let?disY?=?this.offsetTop;??????let?len?=?this.data.stations.length;??????let?row?=?Math.ceil(len/this.column);??????let?n=0,x=0,y=0;??????for(let?j?=?1;j<=row;j++){????????for(let?i=0;i<this.column;i++){??????????++n;??????????if(n<=len){????????????if(j%2!=0){??????????????this.oddRowIndexArr.push(n-1);????????????????????????????x?=?disXArr;????????????}else{??????????????this.evenRowIndexArr.push(n-1);????????????????????????????x?=?disXArrRev;????????????}????????????y?=?disY?+?(j-1)*(this.bendLine.height-this.line.height);????????????this.rectArr[n-1]?=?{x:x,y:y};??????????}????????}??????}????},????????pointInRectPolygon?:?function?(point,?vs)?{??????let?x?=?point[0],?y?=?point[1],inside?=?false;??????for?(let?i?=?0,?j?=?vs.length?-?1;?i?<?vs.length;?j?=?i++)?{??????????let?xi?=?vs[0],?yi?=?vs[1];??????????let?xj?=?vs[j][0],?yj?=?vs[j][1];??????????let?intersect?=?((yi?>?y)?!=?(yj?>?y))??????????????&&?(x?<?(xj?-?xi)?*?(y?-?yi)?/?(yj?-?yi)?+?xi);??????????if?(intersect)?inside?=?!inside;??????}??????return?inside;????},????????????????????????getRectPolygon:function(x,y,w,h){??????let?vs?=?new?Array()?;??????vs[0]?=?[x,y];??????vs[1]?=?[x+w,y];??????vs[2]?=?[x+w,y+h];??????vs[3]?=?[x,y+h];??????return?vs;????}?,????????????????????????chooseStation:function(currIdx){??????let?txt?=?this.data.stations[currIdx];??????let?prevIdx?=?this.data.prevChooseIdx;??????if(prevIdx!=null){????????let?x?=?this.rectArr[prevIdx].x;????????let?y?=?this.rectArr[prevIdx].y;????????this.ctx.drawImage(this.rect.img_b,x,?y,?this.rect.width,?this.rect.height);????????this.drawTxtAtPos(prevIdx);??????}??????let?x?=?this.rectArr[currIdx].x;??????let?y?=?this.rectArr[currIdx].y;??????this.ctx.drawImage(this.rect.img_g,x,?y,?this.rect.width,?this.rect.height);??????this.drawTxtAtPos(currIdx);??????this.ctx.draw(true);??????this.setData({chooseStation:txt,prevChooseIdx:currIdx});????},????????touchS:function(e){??????console.log(e);??????let?touch?=?e.changedTouches;??????if(touch.length==1){????????let?tapPoint?=?[touch[0].x,touch[0].y];????????let?rectArr?=?this.rectArr;????????for(let?i=0;i<rectArr.length;i++){??????????let?vs?=?this.getRectPolygon(rectArr.x,rectArr.y,this.rect.width,this.rect.height);??????????let?inside?=?this.pointInRectPolygon(tapPoint,vs);??????????if(inside){????????????this.chooseStation(i);????????????break;??????????}????????}??????}????}??})??
真機測試圖:
wxapp-Gline.zip?
?
?
轉載于http://www.wxapp-union.com/article-1419-1.html
總結
以上是生活随笔為你收集整理的小程序之基于canvas绘制高铁线路图的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。