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一区二区
三级在线免费观看| 久久久无码中文字幕久...| 久久久久久久久久久综合| 国产97色在线 | 日韩| 国产黄色片免费在线观看| 一级黄色片国产| 天堂在线资源视频| 欧美激情精品久久久久久小说| 日本天堂免费a| 深爱五月综合网| 嫩草av久久伊人妇女超级a| 丰满少妇久久久| 欧洲精品视频在线| 国内国产精品天干天干| 在线观看的毛片| 999精品网站| 韩国日本美国免费毛片| 欧美精品色婷婷五月综合| 被灌满精子的波多野结衣| 在线观看免费不卡av| 韩国中文字幕av| 黄色一级免费大片| 亚洲天堂2018av| 污版视频在线观看| 日韩精品视频一二三| 黄色aaa级片| 亚洲成人福利在线观看| 九九九在线观看视频| www日韩视频| 手机在线成人免费视频| jizz欧美性11| 又色又爽又黄视频| 欧洲精品视频在线| 黄色激情在线视频| 国产婷婷一区二区三区| 超碰网在线观看| 欧美牲交a欧美牲交aⅴ免费真| 狠狠干 狠狠操| 苍井空浴缸大战猛男120分钟| 人妻有码中文字幕| 久久国产激情视频| 国产精品夜夜夜爽张柏芝| 麻豆映画在线观看| 欧美日韩精品在线一区二区| 国产一区二区在线视频播放| 日韩无套无码精品| 国产毛片久久久久久| 91大学生片黄在线观看| 日韩日韩日韩日韩日韩| 不卡av免费在线| 午夜啪啪免费视频| 国产美女无遮挡网站| 嫩草影院国产精品| 桥本有菜av在线| 欧美黄色免费影院| www,av在线| 拔插拔插海外华人免费| 国产日韩欧美久久| 国产黄色片免费在线观看| 熟妇人妻无乱码中文字幕真矢织江| 伊人网在线综合| 亚洲精品久久久久久久蜜桃臀| 狠狠爱免费视频| 91香蕉视频网址| 无码精品a∨在线观看中文| 在线观看国产中文字幕| 国产精品av免费观看| 亚洲一区二区三区四区五区xx| 性做爰过程免费播放| 国产精品无码一本二本三本色| 国产精品久久成人免费观看| 国产免费人做人爱午夜视频| 欧美少妇一级片| 日日噜噜夜夜狠狠| 青青青国产在线观看| 福利网在线观看| 五月天婷婷激情视频| 大陆av在线播放| 久久精品久久99| 无人在线观看的免费高清视频| 欧美日韩午夜爽爽| 天天色天天综合网| 亚洲成熟丰满熟妇高潮xxxxx| 一本色道久久88亚洲精品综合 | avav在线播放| 日本黄大片一区二区三区| 免费 成 人 黄 色| 国产精品69久久久| 国产精品夜夜夜爽张柏芝| 免费涩涩18网站入口| 国产最新免费视频| 日韩国产一级片| 国产一级黄色录像片| 午夜天堂在线视频| 日本免费色视频| xx欧美撒尿嘘撒尿xx| av网址在线观看免费| 久久久亚洲精品无码| 中国丰满熟妇xxxx性| 黄色一级片国产| 日本老太婆做爰视频| 91九色国产ts另类人妖| 亚洲理论中文字幕| 亚洲涩涩在线观看| 日日干夜夜操s8| 亚洲一区二区三区观看| 一级在线免费视频| 女同激情久久av久久| 久久婷五月综合| 91插插插影院| 日本xxxxx18| 91精品一区二区三区四区| 欧美 另类 交| 路边理发店露脸熟妇泻火| 久久久国内精品| aa视频在线播放| 久久久999视频| 亚洲精品一二三四五区| 三上悠亚av一区二区三区| 中文av字幕在线观看| 精品国产无码在线| 日韩最新中文字幕| 777久久精品一区二区三区无码| 国产黄色激情视频| 国产成人无码精品久久久性色| 欧美一级欧美一级| 成人在线免费观看av| 亚洲 欧美 日韩系列| 91大神免费观看| www.av毛片| 校园春色 亚洲色图| avove在线观看| 北条麻妃69av| 中文字幕久久av| 国产无限制自拍| wwww.国产| 日韩中文字幕亚洲精品欧美| 黑鬼大战白妞高潮喷白浆| 国产探花在线观看视频| 黄色大片中文字幕| 在线看的黄色网址| 国产日韩亚洲欧美在线| 中文字幕永久视频| 美女av免费观看| 色天使在线观看| 欧美午夜性视频| 小明看看成人免费视频| 自拍日韩亚洲一区在线| 奇米777在线视频| 亚洲熟女乱色一区二区三区| 四虎1515hh.com| 日本成人在线免费视频| 天堂а√在线中文在线| 性欧美极品xxxx欧美一区二区| 中文字幕日韩综合| 日本一二三四区视频| 无码熟妇人妻av在线电影| 日韩成人三级视频| 色戒在线免费观看| a天堂资源在线观看| 日日躁夜夜躁aaaabbbb| 精品国产一二三四区| 日韩精品在线播放视频| 日韩a在线播放| 天天做天天干天天操| 激情综合在线观看| 9色视频在线观看| 免费一区二区三区在线观看| 欧美a在线视频| 99亚洲国产精品| 一级黄色香蕉视频| 黄色三级中文字幕| 日韩第一页在线观看| 欧美日韩在线成人| 很污的网站在线观看| 韩国一区二区在线播放| 日韩视频免费在线播放| 国产人妻人伦精品| 一女二男3p波多野结衣| 亚洲五月天综合| 国产成人黄色片| www.日本少妇| 国产精品久久久久久久乖乖| 日本中文字幕在线不卡| 国语对白做受xxxxx在线中国| www.国产在线播放| 99视频精品全部免费看 | 国产精品三级一区二区| 亚洲男人天堂av在线| 一起操在线视频| 手机在线免费观看毛片| www黄色在线| 18禁男女爽爽爽午夜网站免费| 青春草国产视频| 亚洲乱码日产精品bd在线观看| 亚欧美在线观看| 捷克做爰xxxⅹ性视频| 国产一二三区av| 日韩欧美国产片| 色噜噜狠狠一区二区三区狼国成人|