Skip to content

畫布

Canvas 畫布 提供了繪製介面,可以在之上進行任意繪製。

1. 基礎使用

第一步:在WXML中添加canvas組件

js
<!-- 2d type canvas -->
<canvas id="myCanvas" type="2d" style="border: 1px solid; width: 300px; height: 150px;" />

首先需要在WXML中添加 Canvas 畫布

指定id='myCanvas'唯一標識一個canvas,用於後續獲取Canvas對象。

指定type用於定義畫布類型,本例子使用type='2d'示例。

第二步:獲取Canvas對象和渲染上下文

js
wx.createSelectorQuery()
    .select('#myCanvas') // id in WXML
    .fields({ node: true, size: true })
    .exec((res) => {
        // Canvas Object
        const canvas = res[0].node
        // rendering context
        const ctx = canvas.getContext('2d')
    })

通過 SelectorQuery選擇上一步的canvas,可以獲取到 Canvas

再通過 Canvas.getContext,我們可以獲取到渲染上下文 RenderingContext

後續的畫布操作與渲染操作,都需要通過這兩個對象來實現。

第三步:初始化Canvas

js
wx.createSelectorQuery()
    .select('#myCanvas') // id in WXML
    .fields({ node: true, size: true })
    .exec((res) => {
        // Canvas Object
        const canvas = res[0].node
        // rendering context
        const ctx = canvas.getContext('2d')


        // The actual drawing width and height of the Canvas.
        const width = res[0].width
        const height = res[0].height


        // Initialise canvas size
        const dpr = wx.getWindowInfo().pixelRatio
        canvas.width = width * dpr
        canvas.height = height * dpr
        ctx.scale(dpr, dpr)
    })

canvas的寬高分為渲染寬高和邏輯寬高:

  • 渲染寬高為canvas畫布在頁面中所實際佔用的寬高大小,即通過對節點進行 boundingClientRect請求獲取到的大小。
  • 邏輯寬高為canvas在渲染過程中的邏輯寬高大小,如繪製一個長方形與邏輯寬高相同,最終長方形會占滿整個畫布,邏輯寬高默認為300 * 150。
  • 不同的設備上,存在物理點數和邏輯點數不相等的情况,所以一般我們需要用 wx.getWindowInfo獲取設備的點數比,乘上canvas的渲染大小,作為畫布的邏輯大小。

第四步:進行繪製

js
// Omit the initialisation steps above, the canvas object and ctx rendering context have already been obtained

// Empty the canvas
ctx.clearRect(0, 0, width, height)

// Drawing a red square
ctx.fillStyle = 'rgb(200, 0, 0)';
ctx.fillRect(10, 10, 50, 50);

// Drawing Blue Translucent Squares
ctx.fillStyle = 'rgba(0, 0, 200, 0.5)';
ctx.fillRect(30, 30, 50, 50);

通過 渲染上下文上的繪圖api,我們可以在畫布上進行任意的繪製

2. 進階使用

2.1 繪製圖片

js
// Omit the initialisation steps above, the canvas object and ctx rendering context are already obtained

// The image object
const image = canvas.createImage()
// Image load completion callback
image.onload = () => {
    // Draw the image to the canvas
    ctx.drawImage(image, 0, 0)
}
// Set the image src
image.src = 'https://open.weixin.qq.com/zh_CN/htmledition/res/assets/res-design-download/icon64_wx_logo.png'

通過 Canvas.createImage我們可以創建圖片對象並加載圖片,當圖片加載完成觸發onload回檔之後,使用ctx.drawImage即可將圖片繪製到canvas上。

2.2 生成圖片

js
// Omitting the initialisation steps above, the canvas object and the ctx rendering context are already acquired


// Drawing a red square
ctx.fillStyle = 'rgb(200, 0, 0)';
ctx.fillRect(10, 10, 50, 50);


// Drawing Blue Translucent Squares
ctx.fillStyle = 'rgba(0, 0, 200, 0.5)';
ctx.fillRect(30, 30, 50, 50);


// Generate Image
wx.canvasToTempFilePath({
    canvas,
    success: res => {
        // Path to the generated image temporary file
        const tempFilePath = res.tempFilePath
    },
})

通過 wx.canvasToTempFilePath接口,可以將canvas上的內容生成圖片暫存文件。

2.3 影格動畫

js
// Omit the initialisation steps above, the canvas object and the ctx rendering context have already been fetched.

const startTime = Date.now()


// Frame rendering callbacks
const draw = () => {
  const time = Date.now()
  // Calculate the elapsed time
  const elapsed = time - startTime


  // Calculate the animation position
  const n = Math.floor(elapsed / 3000)
  const m = elapsed % 3000
  const dx = (n % 2 ? 0 : 1) + (n % 2 ? 1 : -1) * (m < 2500 ? easeOutBounce(m / 2500) : 1)
  const x = (width - 50) * dx


  // Rendering
  ctx.clearRect(0, 0, width, height)
  ctx.fillStyle = 'rgb(200, 0, 0)';
  ctx.fillRect(x, height / 2 - 25, 50, 50);


  // Register for next frame rendering
  canvas.requestAnimationFrame(draw)
}

draw()

通過 Canvas.requestAnimationFrame可以注册動畫幀回檔,在回檔內進行動畫的逐幀繪製。

2.4 自定義字體

通過 wx.loadFontFace可以為Canvas加載自定義字體