gmnon.cn-疯狂蹂躏欧美一区二区精品,欧美精品久久久久a,高清在线视频日韩欧美,日韩免费av一区二区

站長資訊網(wǎng)
最全最豐富的資訊網(wǎng)站

手把手教你在微信小程序中使用canvas繪制天氣折線圖(附代碼)

微信小程序中如何繪制天氣折線圖?下面本篇文章就來給大家介紹一下在微信小程序中使用canvas繪制天氣折線圖的方法,以及使用三階貝塞爾曲線擬合溫度點(diǎn),使之變得圓滑,曲線底部有背景色,希望對大家有所幫助!

手把手教你在微信小程序中使用canvas繪制天氣折線圖(附代碼)

折線

效果圖:

手把手教你在微信小程序中使用canvas繪制天氣折線圖(附代碼)

自定義組件 line-chart

<canvas type="2d" id="line" class="line-class" style="width:{{width}}px;height:{{height}}px" />
Component({   externalClasses: ['line-class'],   properties: {     width: String,     height: String,     data: Array,   },   observers: {     width() {       // 這里監(jiān)聽 width 變化重繪 canvas       // 動態(tài)傳入 width 好像只能這樣了..       const query = this.createSelectorQuery();       query         .select('#line')         .fields({ node: true, size: true })         .exec(res => {           const canvas = res[0].node;           const ctx = canvas.getContext('2d');           const width = res[0].width; // 畫布寬度           const height = res[0].height; // 畫布高度            console.log(`寬度: ${width}, 高度: ${height}`);            const dpr = wx.getSystemInfoSync().pixelRatio;           canvas.width = width * dpr;           canvas.height = height * dpr;           ctx.scale(dpr, dpr);            // 開始繪圖           this.drawLine(ctx, width, height, this.data.data);         });     },   },   methods: {     drawLine(ctx, width, height, data) {       const Max = Math.max(...data);       const Min = Math.min(...data);        // 把 canvas 的寬度, 高度按一定規(guī)則平分       const startX = width / (data.length * 2), // 起始點(diǎn)的橫坐標(biāo) X         baseY = height * 0.9, // 基線縱坐標(biāo) Y         diffX = width / data.length,         diffY = (height * 0.7) / (Max - Min); // 高度預(yù)留 0.2 寫溫度        ctx.beginPath();       ctx.textAlign = 'center';       ctx.font = '13px Microsoft YaHei';       ctx.lineWidth = 2;       ctx.strokeStyle = '#ABDCFF';        // 畫折線圖的線       data.forEach((item, index) => {         const x = startX + diffX * index,           y = baseY - (item - Min) * diffY;          ctx.fillText(`${item}°`, x, y - 10);         ctx.lineTo(x, y);       });       ctx.stroke();        // 畫折線圖背景       ctx.lineTo(startX + (data.length - 1) * diffX, baseY); // 基線終點(diǎn)       ctx.lineTo(startX, baseY); // 基線起點(diǎn)       const lingrad = ctx.createLinearGradient(0, 0, 0, height * 0.7);       lingrad.addColorStop(0, 'rgba(255,255,255,0.9)');       lingrad.addColorStop(1, 'rgba(171,220,255,0)');       ctx.fillStyle = lingrad;       ctx.fill();        // 畫折線圖上的小圓點(diǎn)       ctx.beginPath();       data.forEach((item, index) => {         const x = startX + diffX * index,           y = baseY - (item - Min) * diffY;          ctx.moveTo(x, y);         ctx.arc(x, y, 3, 0, 2 * Math.PI);       });       ctx.fillStyle = '#0396FF';       ctx.fill();     },   }, });

data 就是溫度數(shù)組,如 [1, 2, …]

因?yàn)椴恢罍囟葦?shù)值有多少個(gè),因此這里的 width 動態(tài)傳入

有個(gè)小問題,就是寬度過大的話真機(jī)不會顯示…

 // 獲取 scroll-view 的總寬度  wx.createSelectorQuery()       .select('.hourly')       .boundingClientRect(rect => {         this.setData({           scrollWidth: rect.right - rect.left,         });       })       .exec();
<view class="title">小時(shí)概述</view> <scroll-view scroll-x scroll-y class="scroll" show-scrollbar="{{false}}" enhanced="{{true}}">     <view class="hourly">       <view wx:for="{{time}}" wx:key="index">{{item}}</view>     </view>     <line-chart line-class="line" width="{{scrollWidth}}" height="100" data="{{temp}}" /> </scroll-view>

這里寫 scroll-x 和 scroll-y,要不會出現(xiàn)絕對定位偏移的問題,也不知道為什么

手把手教你在微信小程序中使用canvas繪制天氣折線圖(附代碼)

.scroll {   position: relative;   height: 150px;   width: 100%; }  .hourly {   display: flex;   height: 150px;   position: absolute;   top: 0; }  .hourly > view {   min-width: 3.5em;   text-align: center; }  .line { // 折線圖絕對定位到底部   position: absolute;   bottom: 0; }

這里使用絕對定位其實(shí)是想模擬墨跡天氣這種折線圖和每一天在一個(gè)塊內(nèi)的效果,所以 hourly 要和 scroll-view 等高,canvas 需要定位一下

主要是不知道墨跡天氣怎么實(shí)現(xiàn)的,只能暫時(shí)這樣

手把手教你在微信小程序中使用canvas繪制天氣折線圖(附代碼)

三階貝塞爾曲線

效果圖

手把手教你在微信小程序中使用canvas繪制天氣折線圖(附代碼)

emmm,好像并不怎么圓滑

計(jì)算控制點(diǎn)

首先寫一個(gè)點(diǎn)類

class Point {   constructor(x, y) {     this.x = x;     this.y = y;   } }

Canvas貝塞爾曲線繪制工具 (karlew.com)

http://wx.karlew.com/canvas/bezier/

通過上面這個(gè)網(wǎng)站可以知道三階貝塞爾曲線各個(gè)參數(shù)的意義

手把手教你在微信小程序中使用canvas繪制天氣折線圖(附代碼)

也就是使用 bezierCurveTo 的時(shí)候最后一個(gè)點(diǎn)是下一個(gè)點(diǎn),前兩個(gè)是控制點(diǎn)

控制點(diǎn)的計(jì)算參考: 貝塞爾曲線控制點(diǎn)確定的方法 – 百度文庫

https://wenku.baidu.com/view/c790f8d46bec0975f565e211.html

濃縮一下就是

手把手教你在微信小程序中使用canvas繪制天氣折線圖(附代碼)

這里的 a 和 b 可以是任意正數(shù)

因此定義一個(gè)計(jì)算某點(diǎn)的控制點(diǎn) A 和 B 的方法

/**  * 計(jì)算當(dāng)前點(diǎn)的貝塞爾曲線控制點(diǎn)  * @param {Point} previousPoint: 前一個(gè)點(diǎn)  * @param {Point} currentPoint: 當(dāng)前點(diǎn)  * @param {Point} nextPoint1: 下一個(gè)點(diǎn)  * @param {Point} nextPoint2: 下下個(gè)點(diǎn)  * @param {Number} scale: 系數(shù)  */ calcBezierControlPoints(   previousPoint,   currentPoint,   nextPoint1,   nextPoint2,   scale = 0.25 ) {   let x = currentPoint.x + scale * (nextPoint1.x - previousPoint.x);   let y = currentPoint.y + scale * (nextPoint1.y - previousPoint.y);    const controlPointA = new Point(x, y); // 控制點(diǎn) A    x = nextPoint1.x - scale * (nextPoint2.x - currentPoint.x);   y = nextPoint1.y - scale * (nextPoint2.y - currentPoint.y);    const controlPointB = new Point(x, y); // 控制點(diǎn) B    return { controlPointA, controlPointB }; }

這里 scale 就是 a 和 b,不過將它們的取值相等

但是第一個(gè)點(diǎn)沒有 previousPoint,倒數(shù)第二個(gè)點(diǎn)沒有 nextPoint2

因此當(dāng)點(diǎn)是第一個(gè)的時(shí)候,使用 currentPoint 代替 previousPoint

當(dāng)?shù)箶?shù)第二個(gè)點(diǎn)的時(shí)候,使用 nextPoint1 代替 nextPoint2

手把手教你在微信小程序中使用canvas繪制天氣折線圖(附代碼)

至于最后一個(gè)點(diǎn),不需要做任何事,因?yàn)?bezierCurveTo 第三個(gè)參數(shù)就是下一個(gè)點(diǎn),只需要提供坐標(biāo)就能連起來,不需要計(jì)算控制點(diǎn)

因此繪制三階貝塞爾曲線的方法:

/**  * 繪制貝塞爾曲線  * ctx.bezierCurveTo(控制點(diǎn)1, 控制點(diǎn)2, 當(dāng)前點(diǎn));  */ drawBezierLine(ctx, data, options) {   const { startX, diffX, baseY, diffY, Min } = options;    ctx.beginPath();   // 先移動到第一個(gè)點(diǎn)   ctx.moveTo(startX, baseY - (data[0] - Min) * diffY);    data.forEach((e, i) => {     let curPoint, prePoint, nextPoint1, nextPoint2, x, y;      // 當(dāng)前點(diǎn)     x = startX + diffX * i;     y = baseY - (e - Min) * diffY;     curPoint = new Point(x, y);      // 前一個(gè)點(diǎn)     x = startX + diffX * (i - 1);     y = baseY - (data[i - 1] - Min) * diffY;     prePoint = new Point(x, y);      // 下一個(gè)點(diǎn)     x = startX + diffX * (i + 1);     y = baseY - (data[i + 1] - Min) * diffY;     nextPoint1 = new Point(x, y);      // 下下個(gè)點(diǎn)     x = startX + diffX * (i + 2);     y = baseY - (data[i + 2] - Min) * diffY;     nextPoint2 = new Point(x, y);      if (i === 0) {       // 如果是第一個(gè)點(diǎn), 則前一個(gè)點(diǎn)用當(dāng)前點(diǎn)代替       prePoint = curPoint;     } else if (i === data.length - 2) {       // 如果是倒數(shù)第二個(gè)點(diǎn), 則下下個(gè)點(diǎn)用下一個(gè)點(diǎn)代替       nextPoint2 = nextPoint1;     } else if (i === data.length - 1) {       // 最后一個(gè)點(diǎn)直接退出       return;     }      const { controlPointA, controlPointB } = this.calcBezierControlPoints(       prePoint,       curPoint,       nextPoint1,       nextPoint2     );      ctx.bezierCurveTo(       controlPointA.x,       controlPointA.y,       controlPointB.x,       controlPointB.y,       nextPoint1.x,       nextPoint1.y     );   });    ctx.stroke(); },

【相關(guān)學(xué)習(xí)推薦:小程序開發(fā)教程】

贊(0)
分享到: 更多 (0)
?
網(wǎng)站地圖   滬ICP備18035694號-2    滬公網(wǎng)安備31011702889846號
gmnon.cn-疯狂蹂躏欧美一区二区精品,欧美精品久久久久a,高清在线视频日韩欧美,日韩免费av一区二区
男插女免费视频| 日韩中字在线观看| 天天干天天干天天干天天干天天干| 中文字幕av导航| 手机版av在线| 嫩草视频免费在线观看| 亚洲成人福利在线观看| 美女网站免费观看视频| 欧美 日韩 国产 激情| 动漫av免费观看| 另类小说第一页| 亚洲美女性囗交| 亚洲欧美天堂在线| 三级在线免费观看| 欧美午夜性视频| 国产精品wwwww| 天天视频天天爽| 日本黄色a视频| 精品国产一区三区| 久久久久久久久久福利| 在线免费av播放| 三级黄色片免费看| 妞干网在线观看视频| 成年人观看网站| 激情五月俺来也| 国产毛片久久久久久国产毛片| 国内自拍在线观看| 国产无色aaa| 美女av免费观看| 国产欧美高清在线| 波多野结衣免费观看| 久久精品国产sm调教网站演员| 精品一卡二卡三卡| 色综合五月婷婷| 日本xxxxxxx免费视频| 久久精品一二三四| 青青草原av在线播放| 九一免费在线观看| 另类小说色综合| 激情五月宗合网| 日本成人xxx| 丝袜制服一区二区三区| h无码动漫在线观看| 99sesese| 北条麻妃av高潮尖叫在线观看| 波多野结衣三级在线| 成年人小视频网站| av之家在线观看| www.偷拍.com| 日本三级黄色网址| 欧美国产激情视频| av在线播放天堂| 亚洲激情免费视频| 五月天婷婷在线观看视频| 无码内射中文字幕岛国片| 成人午夜视频免费观看| 午夜啪啪免费视频| 久久精品久久99| 亚洲高清视频免费| 亚洲娇小娇小娇小| 91欧美视频在线| 在线免费观看视频黄| 91av俱乐部| 日本免费观看网站| 免费看a级黄色片| 成人黄色一区二区| 9久久婷婷国产综合精品性色| 国产97在线 | 亚洲| 无码中文字幕色专区| 国产a级黄色大片| 成年女人18级毛片毛片免费 | 男人的天堂日韩| 虎白女粉嫩尤物福利视频| 久久精品视频91| 无人在线观看的免费高清视频| 日本精品久久久久中文字幕| 精品国产成人av在线免| 婷婷丁香激情网| 久久精品一卡二卡| 九九久久九九久久| 97在线国产视频| 男人天堂999| 国产美女18xxxx免费视频| 一级黄色片播放| 99精品人妻少妇一区二区| www黄色av| 亚洲小视频网站| 97中文字幕在线| 亚洲一级片免费| 肉大捧一出免费观看网站在线播放 | 少妇熟女一区二区| 大陆av在线播放| 蜜臀av午夜一区二区三区| 免费成人黄色大片| 亚洲精品久久久久久久蜜桃臀| 凹凸国产熟女精品视频| 天堂视频免费看| 免费视频爱爱太爽了| 久久人人爽av| 成人性做爰片免费视频| 国产第一页视频| 亚洲区成人777777精品| 亚洲色精品三区二区一区| 成年在线观看视频| 国产一伦一伦一伦| 欧美深夜福利视频| 欧美一级免费在线| 男人女人黄一级| 精品久久久久久久久久中文字幕| 国内自拍第二页| 免费观看成人网| 日本黄大片在线观看| 小早川怜子一区二区三区| 青青在线视频观看| 欧美日韩性生活片| www婷婷av久久久影片| 韩国一区二区在线播放| 久久午夜夜伦鲁鲁一区二区| 热99这里只有精品| 国产一线二线三线女| 久久久久久久久影视| 黄色小视频免费网站| 精品中文字幕av| 国产视频一视频二| www.男人天堂网| 国产情侣第一页| 国产日韩亚洲欧美在线| 少妇久久久久久被弄到高潮| 中文字幕1234区| 午夜福利123| 成人高清在线观看视频| 久久久一二三四| 波多野结衣 作品| 五月天在线免费视频| 今天免费高清在线观看国语| 一级特黄妇女高潮| 日本一区二区三区四区五区六区| 北条麻妃亚洲一区| 免费观看黄色大片| 黄色三级中文字幕| 国产3p露脸普通话对白| 国模无码视频一区二区三区| 91好吊色国产欧美日韩在线| 三上悠亚久久精品| 亚洲精品中文字幕无码蜜桃| 免费看a级黄色片| 欧美成人手机在线视频| 法国空姐在线观看免费| 国产freexxxx性播放麻豆| 毛片在线视频播放| 国产一级做a爰片久久| 亚洲天堂一区二区在线观看| 国产激情片在线观看| 日本a视频在线观看| 黄色成人免费看| 男女爱爱视频网站| 浮妇高潮喷白浆视频| 亚洲老女人av| 粉嫩av一区二区三区天美传媒| 波多野结衣综合网| 激情视频免费网站| 毛片av在线播放| 在线观看的毛片| 久久这里只有精品18| 91最新在线观看| 野外做受又硬又粗又大视频√| 精品久久久久久无码国产| avove在线观看| 日韩在线第三页| 欧美中文字幕在线观看视频| 色悠悠久久综合网| 国产一级爱c视频| 国内av免费观看| 黄色三级视频在线| 全黄性性激高免费视频| 国产一级免费大片| 久久婷婷国产精品| 日本一道在线观看| 日韩av自拍偷拍| 日本在线观看免费视频| 国产日本在线播放| 在线观看成人免费| 亚洲一区日韩精品| 茄子视频成人免费观看| 免费不卡av在线| 国产日韩第一页| 91精产国品一二三产区别沈先生| 韩国日本在线视频| 欧美精品久久久久久久久久久| 九九精品久久久| 在线观看免费的av| 天天爽天天爽夜夜爽| 噜噜噜久久亚洲精品国产品麻豆 | 欧美在线观看成人| 日日摸日日碰夜夜爽无码| 国产情侣第一页| 男人插女人视频在线观看| 国产成人一区二区三区别| 麻豆一区二区三区在线观看| 先锋影音男人资源|