只有canvas的api,要搞一個成熟的K線圖組件出來,對我來說是一個巨大的挑戰(zhàn),但是沒辦法,小程序中,由于api的細(xì)微差別,成熟的三方框架用不了,只好硬著頭皮自己來。從熟讀api開始,一步一步嘗試,希望能有所成就。- -!壓力巨大,開擼吧??!
先創(chuàng)建一個canvas元素,以后所有的例子都要用到他,設(shè)置好id,綁定好事件,不出意外,canvas元素應(yīng)該不會改動了
// canvas.wxml
<canvas canvas-id="stage" class="stage"
bindtouchstart="touchstart"
bindtouchmove="touchmove"
bindtouchend="touchend"
bindtouchcancel="touchcancel"
bindlongtap="longtap" >
</canvas>
// canvas.wxss
.stage {
width: 100%;
height: 200px;
margin: 20px auto;
background-color: #fff;
}
通過官方文檔api的學(xué)習(xí),發(fā)現(xiàn)一個圖形,從繪制開始,到結(jié)束都有一定的規(guī)律,比如畫一個矩形
// 第一步:聲明一個canvas對象
const ctx = wx.createCanvasContext('stage')
// 第二步:定義要繪制的內(nèi)容
ctx.setFillStyle('red')
ctx.fillRect(10, 10, 150, 75)
// 第三步:根據(jù)第二步中繪制的內(nèi)容,將圖像畫出來
ctx.draw()
這樣,就搞定了矩形
填充樣式很多,比如說線性漸變,圓角漸變等,這些都不是重點,需要的時候找api即可,重點在于如果想要繪制圖片的同時,還想畫一條線,并且寫入幾個文字應(yīng)該怎么玩?
根據(jù)剛才發(fā)現(xiàn)的規(guī)律,在第二步中分別定義就行,試試看
const ctx = wx.createCanvasContext('stage')
ctx.setFillStyle('red')
ctx.fillRect(10, 10, 150, 75)
ctx.beginPath()
ctx.moveTo(10, 100)
ctx.lineTo(150, 100)
ctx.setStrokeStyle('red')
ctx.stroke()
ctx.setFontSize(20)
ctx.setFillStyle('orange')
ctx.fillText('canvas 真尼瑪難!', 10, 150)
ctx.draw()
發(fā)現(xiàn)凡是填充內(nèi)容,都是用的跟fill有關(guān)的api,凡是填充線條,都是跟stroke有關(guān)的api,每一個圖形的繪制,都以一次填充結(jié)束,上面我們畫的圖形如下
.
canvas 畫布的坐標(biāo)跟我們數(shù)學(xué)上常用的坐標(biāo)不太一樣,它的(0, 0)點在畫布的左上角,可是實際使用時,我們要將坐標(biāo)原點放在左下角,或者我們生成的坐標(biāo)系的原點處。因此,在傳入數(shù)據(jù)時,我們要講數(shù)據(jù)進(jìn)行處理才能符合我們的實際使用。
我的canvas高度為200,因此左下角的坐標(biāo)點為(0, 200),這時我們根據(jù)常識希望畫一個從(0, 0)到(200, 100)的直線,那么我們應(yīng)該這樣做
line([0, 0], [200, 100])
function line (coors, coore) {
const ctx = wx.createCanvasContext('stage')
ctx.beginPath()
ctx.setStrokeStyle('red')
ctx.moveTo(coors[0], 200 - coors[1])
ctx.lineTo(coore[0], 200 - coore[1])
ctx.stroke()
ctx.draw()
}
如果我們想要畫一個折線圖,從上面的例子可以看出,無非就是根據(jù)傳入的數(shù)據(jù),多做幾次ctx.lineTo操作即可,根據(jù)這個思路可以封裝一個折線圖方法
line (canvasId, options) {
let windowWidth = 0
wx.getSystemInfo({
success (result) {
windowWidth = result.windowWidth
}
})
let a = windowWidth / (options.xAxis.length-1)
let data = []
options.xAxis.map((item, i) => {
data.push([i * a, 200 - options.yAxis[i]])
})
const ctx = wx.createCanvasContext(canvasId)
ctx.beginPath()
data.map((item, i) => {
if (i == 0) {
ctx.moveTo(item[0], item[1])
}
ctx.lineTo(item[0], item[1])
})
ctx.setLineWidth(1)
ctx.setLineCap('square')
ctx.setStrokeStyle('red')
ctx.stroke()
ctx.draw()
}
在onLoad中調(diào)用
onLoad (e) {
this.line('stage', {
xAxis: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30],
yAxis: [11, 33, 22, 32, 14, 15, 20, 60, 23, 44, 77, 122, 133, 89, 156, 122,128, 143, 111, 101, 132, 99, 98, 44, 12, 14, 111, 13, 12, 55]
})
},