【移动应用开发技术】在微信小程序中如何使用canvas绘制天气折线图_第1页
【移动应用开发技术】在微信小程序中如何使用canvas绘制天气折线图_第2页
【移动应用开发技术】在微信小程序中如何使用canvas绘制天气折线图_第3页
【移动应用开发技术】在微信小程序中如何使用canvas绘制天气折线图_第4页
【移动应用开发技术】在微信小程序中如何使用canvas绘制天气折线图_第5页
已阅读5页,还剩6页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

【移动应用开发技术】在微信小程序中如何使用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()

{

//

这里监听

width

变化重绘

canvas

//

动态传入

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

的宽度,

高度按一定规则平分

const

startX

=

width

/

(data.length

*

2),

//

起始点的横坐标

X

baseY

=

height

*

0.9,

//

基线纵坐标

Y

diffX

=

width

/

data.length,

diffY

=

(height

*

0.7)

/

(Max

-

Min);

//

高度预留

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);

//

基线终点

ctx.lineTo(startX,

baseY);

//

基线起点

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();

//

画折线图上的小圆点

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就是温度数组,如[1,2,...]因为不知道温度数值有多少个,因此这里的width动态传入有个小问题,就是宽度过大的话真机不会显示...

//

获取

scroll-view

的总宽度

wx.createSelectorQuery()

.select('.hourly')

.boundingClientRect(rect

=>

{

this.setData({

scrollWidth:

rect.right

-

rect.left,

});

})

.exec();<view

class="title">小时概述</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,要不会出现绝对定位偏移的问题,也不知道为什么.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;

}这里使用绝对定位其实是想模拟墨迹天气这种折线图和每一天在一个块内的效果,所以hourly要和scroll-view等高,canvas需要定位一下主要是不知道墨迹天气怎么实现的,只能暂时这样三阶贝塞尔曲线效果图emmm,好像并不怎么圆滑计算控制点首先写一个点类class

Point

{

constructor(x,

y)

{

this.x

=

x;

this.y

=

y;

}

}也就是使用bezierCurveTo的时候最后一个点是下一个点,前两个是控制点浓缩一下就是这里的a和b可以是任意正数因此定义一个计算某点的控制点A和B的方法/**

*

计算当前点的贝塞尔曲线控制点

*

@param

{Point}

previousPoint:

前一个点

*

@param

{Point}

currentPoint:

当前点

*

@param

{Point}

nextPoint1:

下一个点

*

@param

{Point}

nextPoint2:

下下个点

*

@param

{Number}

scale:

系数

*/

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);

//

控制点

A

x

=

nextPoint1.x

-

scale

*

(nextPoint2.x

-

currentPoint.x);

y

=

nextPoint1.y

-

scale

*

(nextPoint2.y

-

currentPoint.y);

const

controlPointB

=

new

Point(x,

y);

//

控制点

B

return

{

controlPointA,

controlPointB

};

}这里scale就是a和b,不过将它们的取值相等但是第一个点没有previousPoint,倒数第二个点没有nextPoint2因此当点是第一个的时候,使用currentPoint代替previousPoint当倒数第二个点的时候,使用nextPoint1代替nextPoint2至于最后一个点,不需要做任何事,因为bezierCurveTo第三个参数就是下一个点,只需要提供坐标就能连起来,不需要计算控制点因此绘制三阶贝塞尔曲线的方法:/**

*

绘制贝塞尔曲线

*

ctx.bezierCurveTo(控制点1,

控制点2,

当前点);

*/

drawBezierLine(ctx,

data,

options)

{

const

{

startX,

diffX,

baseY,

diffY,

Min

}

=

options;

ctx.beginPath();

//

先移动到第一个点

ctx.moveTo(startX,

baseY

-

(data[0]

-

Min)

*

diffY);

data.forEach((e,

i)

=>

{

let

curPoint,

prePoint,

nextPoint1,

nextPoint2,

x,

y;

//

当前点

x

=

startX

+

diffX

*

i;

y

=

baseY

-

(e

-

Min)

*

diffY;

curPoint

=

new

Point(x,

y);

//

前一个点

x

=

startX

+

diffX

*

(i

-

1);

y

=

baseY

-

(data[i

-

1]

-

Min)

*

diffY;

prePoint

=

new

Point(x,

y);

//

下一个点

x

=

startX

+

diffX

*

(i

+

1);

y

=

baseY

-

(data[i

+

1]

-

Min)

*

diffY;

nextPoint1

=

new

Point(x,

y);

//

下下个点

x

=

startX

+

diffX

*

(i

+

2);

y

=

baseY

-

(data[i

+

2]

-

Min)

*

diffY;

nextPoint2

=

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论