日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

小程序之基于canvas绘制高铁线路图

發(fā)布時間:2024/1/1 编程问答 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 小程序之基于canvas绘制高铁线路图 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

前幾天@天下雪 給了我一張高鐵的路線圖,問我能不能用canvas畫出來,所以我就試了試,我的思路可能比較復(fù)雜;如果有更簡單的思路可以留言回復(fù);

關(guān)注微信公眾號,獲取源碼和教程

?

下面說一下我的實現(xiàn)思路: ?
1、首先是每個站點圓角矩形的繪制,一開始想著用canvas把圓角矩形繪制出來,但發(fā)現(xiàn)小程序暫時還沒有繪制圓角的arcTo方法,所以用canvas繪制就相對比較麻煩,最后為了方便決定用圖片代替;?
2、將整個路線圖分為四個小圖片,(1)站點圓角矩形(2)站點之間的直連線(3)站點之間右側(cè)彎曲連線(4)站點之間左側(cè)彎曲連線;?
3、通過觀察分析,將繪制過程分為兩步,(1)奇數(shù)行圓角矩形、連線的繪制點x坐標(biāo)是從左至右遞增,y坐標(biāo)值是行數(shù)乘以某個固定值(2)偶數(shù)行圓角矩形、連線的繪制點x坐標(biāo)是從左至右遞減,y坐標(biāo)值是行數(shù)乘以某個固定值?
4、奇數(shù)行,偶數(shù)行的圓角矩形的下標(biāo)index+1是3的倍數(shù)的話,奇數(shù)行當(dāng)前下標(biāo)右側(cè)繪制右彎曲連線圖片,偶數(shù)行當(dāng)前下標(biāo)左側(cè)繪制左彎曲連線圖片;?
5、整個canvas繪制區(qū)域在不同手機上的適配?
6、具體的一些細節(jié)請參照代碼注釋?
7、開發(fā)工具上使用drawImage重復(fù)繪制同一張圖片只顯示第一次繪制的位置,暫時不知道什么原因,所以請在真機上測試;?
8、有什么不足之處,望大家多多指點!感激!?

wxml代碼:

  • <!--pages/Gline/index.wxml-->
  • <viewclass="g-title">(G23)選擇出發(fā)站點<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代碼:??
  • ??
  • //?pages/Gline/index.js??
  • Page({??
  • ??data:{??
  • ????canvWidth:750,??
  • ????canvHeight:750,??
  • ????stations:['北京南','天津南','濟南西','泰安','滕州東','徐州東','南京南','鎮(zhèn)江南','蘇州北','上海虹橋','北京南','天津南','濟南西','泰安','滕州東','徐州東','南京南','鎮(zhèn)江南','蘇州北','上海虹橋','北京南','天津南','濟南西','泰安','滕州東','徐州東','南京南','鎮(zhèn)江南','蘇州北','上海虹橋'],??
  • ????chooseStation:'',//頁面顯示選中的車站名字??
  • ????prevChooseIdx:null,//上一次選中車站的下標(biāo)??
  • ????//?stations:['北京南','天津南','濟南西','泰安'],??
  • ??},??
  • ??onLoad:function(options){??
  • ????//?頁面初始化?options為頁面跳轉(zhuǎn)所帶來的參數(shù)??
  • ????//?this.setData({canvHeight:502});??
  • ????const?ctx?=?wx.createCanvasContext('map');//路線圖繪制的畫布上下文對象??
  • ????this.ctx?=?ctx;//將ctx對象綁定到當(dāng)前頁面中??
  • ????this.column?=?3;//每行顯示車站數(shù)量??
  • ????this.offsetTop?=?30;//繪制起始坐標(biāo)的top值,也就是距離canvas頂部的距離??
  • ????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',//左側(cè)連線??
  • ??????img_r:'/images/line_r.png',//右側(cè)連線??
  • ??????height:70,??
  • ??????width:20??
  • ????},??
  • ????this.rectArr=[];//記錄所有車站的繪制起始點的坐標(biāo)的數(shù)組??
  • ????this.oddRowIndexArr=[];//記錄奇數(shù)行的車站的下標(biāo)數(shù)組,如[0,1,2,6,.....]??
  • ????this.evenRowIndexArr=[];//記錄偶數(shù)行的車站的下標(biāo)數(shù)組,如[3,4,5,9,.....]??
  • ????this.initMap();??
  • ??},??
  • ??onReady:function(){??
  • ??},??
  • ??onShow:function(){??
  • ????//?頁面顯示??
  • ??},??
  • ??onHide:function(){??
  • ????//?頁面隱藏??
  • ??},??
  • ??onUnload:function(){??
  • ????//?頁面關(guān)閉??
  • ??},??
  • ??//對不同設(shè)備下圖片大小的適配??
  • ??adaptiveScreenSize:function(o){??
  • ????let?ww?=?this.data.winWidth;??
  • ????let?zoom?=?ww/375;//375這里是按iPhone6的寬度做等比縮放??
  • ????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});//將設(shè)備的信息存入data中,供后面使用??
  • ????????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;??
  • ????//當(dāng)站點文本文字超過3個字,將縮小字號??
  • ????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;//這里額外-2,文本才能更接近垂直居中??
  • ????this.ctx.setFontSize(fontSize);??
  • ????this.ctx.setFillStyle('#ffffff')??
  • ????this.ctx.fillText(txt,?txt_x,?txt_y);??
  • ??},??
  • ??//在下標(biāo)為idx處繪制圓角矩形??
  • ??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);??
  • ??},??
  • ??//動態(tài)計算不同屏幕大小canvas的高度??
  • ??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});??
  • ??},??
  • ??//繪制線路這邏輯比較亂,我是把路線分為奇數(shù)段和偶數(shù)段進行繪制??
  • ??drawLine:function(){??
  • ????const?rectArr?=?this.rectArr;??
  • ????let?x=0,y=0;???
  • ????if(rectArr.length==2){//首先當(dāng)車站數(shù)量為2個的時候,只需繪制一條線段??
  • ????????x?=?rectArr[0].x+this.rect.width;//計算繪制線段起始點的x坐標(biāo)??
  • ????????y?=?rectArr[0].y+Math.floor((this.rect.height-this.line.height)/2);//計算繪制線段起始點的y坐標(biāo)??
  • ????????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){//判斷當(dāng)前下標(biāo)繪制點后面是否還有繪制點??
  • ????????????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){//判斷奇數(shù)行繪制點的下標(biāo)如果不是3的整數(shù)倍將繪制一條直線,反之繪制右曲線??
  • ??????????????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);??
  • ????????????}??
  • ??????????}??
  • ????????}??
  • ??????}??
  • ??????//下面邏輯同奇數(shù)行的邏輯,不同的是繪制直線和彎曲線時x的坐標(biāo)會有變化??
  • ??????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();??
  • ????//?setTimeout(()=>{??
  • ??????const?rectArr?=?this.rectArr;???
  • ??????for(let?i=0;i<rectArr.length;i++){??
  • ????????this.initRect(i);??
  • ????????this.drawTxtAtPos(i);??
  • ??????}??
  • ??????this.ctx.draw(true);??
  • ????//?},500);??
  • ????this.drawLine();??
  • ????this.ctx.draw(true);??
  • ??},??
  • ??//計算后,每行的所有繪制點的起始坐標(biāo)x值是一個固定數(shù)組??
  • ??//如:奇數(shù)行[10,20,30],偶數(shù)行:[30,20,10]??
  • ??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;??
  • ??},??
  • ??//根據(jù)給出的車站數(shù)量,將每個車站的繪制頂點計算出來存入數(shù)組rectArr中??
  • ??createRectTopPoints:function(){??
  • ????let?rectArr?=?[];??
  • ????let?disXArr?=?this.getDisXArr();??
  • ????let?disXArrRev?=?this.getDisXArr().reverse();??
  • ????let?disY?=?this.offsetTop;//繪制初始點距離canvas頂部的高度??
  • ????let?len?=?this.data.stations.length;??
  • ????let?row?=?Math.ceil(len/this.column);//根據(jù)車站數(shù)量計算需要繪制的行數(shù)??
  • ????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);??
  • ????????????//console.log("奇數(shù)行:"+n);??
  • ????????????x?=?disXArr;??
  • ??????????}else{??
  • ????????????this.evenRowIndexArr.push(n-1);??
  • ????????????//console.log("偶數(shù)行:"+n);??
  • ????????????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;??
  • ??},??
  • ????????//根據(jù)某個圓角矩形的繪制點和寬高,計算出圓角矩形4個頂點的坐標(biāo)值??
  • ????????//順序為左上,右上,右下,左下,也就是順時針方向??
  • ??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;??
  • ??}?,??
  • ??//點擊車站調(diào)取的事件,事件中需要處理:??
  • ??//1、需要獲取到當(dāng)前點擊的車站文本??
  • ??//2、判斷是否有過選取,如果之前有選取,需要將之前選取過的區(qū)塊顏色改為默認色??
  • ??//3、改變當(dāng)前區(qū)塊的顏色??
  • ??//4、記錄當(dāng)前點擊的下標(biāo)??
  • ??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;//這里一定要用changedTouches,如果用touches,安卓機會有問題??
  • ????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?
    ?
    ?

    轉(zhuǎn)載于http://www.wxapp-union.com/article-1419-1.html

    總結(jié)

    以上是生活随笔為你收集整理的小程序之基于canvas绘制高铁线路图的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。