# Canvas canvas

The canvas component provides a drawing interface on which you can draw arbitrarily

# Basic usage

# Add a canvas component to WXML

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

First you need to add the canvas component to the WXML.

Specifyid = "myCanvas"to uniquely identify a canvas for subsequent acquisition of Canvas objects .

Specifytypeto define the canvas type. In this example, use thetype = "2d"example.

# Step 2: Get the Canvas object and render context

this.createSelectorQuery()
    .select('#myCanvas') // 在 WXML 中填入的 id
    .fields({ node: true, size: true })
    .exec((res) => {
        // Canvas 对象
        const canvas = res[0].node
        // 渲染上下文
        const ctx = canvas.getContext('2d')
    })

The SelectorQuery Select the canvas from the previous step to get the Canvas object .

By using Canvas.getContext , we can get the rendering context RenderingContext .

Subsequent canvas and rendering operations need to be implemented through these two objects.

# Step 3: Initial Canvas

this.createSelectorQuery()
    .select('#myCanvas') // 在 WXML 中填入的 id
    .fields({ node: true, size: true })
    .exec((res) => {
        // Canvas 对象
        const canvas = res[0].node
        // 渲染上下文
        const ctx = canvas.getContext('2d')

        // Canvas 画布的实际绘制宽高
        const width = res[0].width
        const height = res[0].height

        // 初始化画布大小
        const dpr = wx.getWindowInfo().pixelRatio
        canvas.width = width * dpr
        canvas.height = height * dpr
        ctx.scale(dpr, dpr)
    })

The width of canvas is divided into rendering width and logical width:

  • Render width is the actual width of the canvas on the page, that is, the size obtained by making a boundingClientRect request to a node.
  • The logical width is the size of the canvas in the rendering process, such as drawing a rectangular with the same logical width, and eventually the rectangular will occupy the entire canvas.Logical width defaults to300 * 150.

On different devices, there are cases where the physical and logical pixels are not equal, so generally we need to use wx.getWindowInfo to obtain the pixel ratio of the device and multiply the rendering size of the canvas as the logical size of the paint.

# Step 4: Conduct a mapping

Preview with Developer Tool

// Omitting the initial steps above, you've got the canvas object and the ctx rendering context

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

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

// Draw blue translucent squares
ctx.fillStyle = 'rgba(0, 0, 200, 0.5)';
ctx.fillRect(30, 30, 50, 50);

With the drawing API on the rendering context , we can draw arbitrarily on the canvas.

# Advanced Use

# Draw a picture

Preview with Developer Tool

// Omitting the initial steps above, you've got the canvas object and the ctx rendering context

// Picture objects
const image = canvas.createImage()
// Image loading completes a callback
image.onload = () => {
    // 将图片绘制到 canvas 上
    ctx.drawImage(image, 0, 0)
}
// Set up picture src
image.src = 'https://open.weixin.qq.com/zh_CN/htmledition/res/assets/res-design-download/icon64_wx_logo.png'

With Canvas.createImage we can create image objects and load images.When the image load is complete and triggers theonloadcallback, you can draw the image onto the canvas usingctx.drawImage.

# Generate Pictures

Preview with Developer Tool

// Omitting the initial steps above, you've got the canvas object and the ctx rendering context

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

// Draw blue translucent squares
ctx.fillStyle = 'rgba(0, 0, 200, 0.5)';
ctx.fillRect(30, 30, 50, 50);

// Generate Pictures
wx.canvasToTempFilePath({
    canvas,
    success: res => {
        // 生成的图片临时文件路径
        const tempFilePath = res.tempFilePath
    },
})

Using the wx.canvasToTempFilePath interface, you can generate temporary picture files from the contents of the canvas.

# Frame Animation

Preview with Developer Tool

// Omitting the initial steps above, you've got the canvas object and the ctx rendering context

const startTime = Date.now()

// Frame Rendering callback
const draw = () => {
  const time = Date.now()
  // 计算经过的时间
  const elapsed = time - startTime

  // 计算动画位置
  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

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

  // 注册下一帧渲染
  canvas.requestAnimationFrame(draw)
}

draw()

Through Canvas.requestAnimationFrame you can register an animation frame callback, in which the animation is drawn frame by frame.

# Custom Fonts

Using wx.loadFontFace you can load custom fonts for Canvas.

Preview with Developer Tool

# Record a video

Canvas content can be recorded as video and saved by MediaRecorder .

Preview with Developer Tool

# WebGL

Preview with Developer Tool

<canvas type="webgl" id="myCanvas" />
// Omitting the initial steps above, you've got the canvas object

const gl = canvas.getContext('webgl') // 获取 webgl 渲染上下文