开发
API

canvas

基础库 1.0.0 开始支持本组件。 基础库 1.78.0 开始支持 v2 版本。

画布。可使用 JS 操作 Canvas 上下文进行绘制。

目前支持 v1,v2 两个版本,说明如下:

  • v1:通过 tt.createCanvasContext 获取 canvas 上下文。本方案的 <canvas> 组件为 web 组件。
  • v2:属性 type 为 2dwebgl。需通过 SelectorQuery 获取 Canvas 实例 使用相关能力。本方案的 <canvas> 组件为原生组件,使用时请注意原生组件相关限制。

属性说明

属性名类型默认值必填说明最低支持版本
canvas-idstring[v1]canvas 组件的标识1.0.0
typestring[v2]指定 canvas 类型,有效值为 "2d" 和 "webgl"1.78.0
bindtouchstartEventHandle[v2]手指触摸动作开始1.78.0
bindtouchmoveEventHandle[v2]手指触摸后移动1.78.0
bindtouchendEventHandle[v2]手指触摸动作结束1.78.0
bindtouchcancelEventHandle[v2]手指触摸动作被打断1.78.0

代码示例

开发者工具中预览

<!-- index.ttml -->
<view class="container">
  <view class="canvas-intro">canvas基础绘画能力</view>

  <view class="canvas-item">
    <canvas
      canvas-id="{{id}}"
      bindtouchstart="testBindtouchstart"
      bindtouchmove="testBindtouchmove"
      bindtouchend="testBindtouchend"
      bindtouchcancel="testBindtouchcancel"
      binderror="testBinderror"
      style="width: {{width + 100}}px; height: 100px;border: 1px solid blue"
    ></canvas>
    <view class="expection">预期:一个小人</view>
  </view>

  <view class="canvas-item">
    <canvas
      id="canvas_type_2d"
      type="2d"
      data-key="native-2d"
      binderror="testBinderror"
      bindtouchstart="testBindtouchstart"
      bindtouchmove="testBindtouchmove"
      bindtouchcancel="testBindtouchcancel"
      bindtouchend="testBindtouchend"
      style="width: {{width + 100}}px; height: 100px;border: 1px solid blue"
    ></canvas>
    <view class="expection">预期:canvas 2d</view>
  </view>

  <view class="canvas-item">
    <canvas
      id="canvas_type_webgl"
      type="webgl"
      binderror="testBinderror"
      bindtouchstart="testBindtouchstart"
      bindtouchmove="testBindtouchmove"
      bindtouchcancel="testBindtouchcancel"
      bindtouchend="testBindtouchend"
      style="width: 100px; height: 100px;border: 1px solid red"
    ></canvas>
    <view class="expection">预期:canvas webgl</view>
  </view>
</view>
// index.js
const app = getApp();
let nativeCanvas2d;
let nativeCanvas2dCtx;
let nativeCanvasGl;
let nativeCanvasGlCtx;

Page({
  data: {
    width: 100,
    id: "123",
  },

  onReady() {
    this.drawWeb(this.data.id);
    this.drawNative("#canvas_type_2d", "2d");
    this.drawNative("#canvas_type_webgl", "webgl");
  },

  drawWeb(id) {
    const ctx = tt.createCanvasContext(id);
    ctx.beginPath();
    ctx.arc(20, 20, 10, 0, Math.PI * 2);
    ctx.rect(10, 30, 20, 15);
    ctx.stroke();
    ctx.beginPath();
    ctx.arc(17, 18, 2, 0, Math.PI * 2);
    ctx.arc(23, 18, 2, 0, Math.PI * 2);
    ctx.fill();
    ctx.beginPath();
    ctx.save();
    ctx.lineWidth = 3;
    ctx.moveTo(18, 25);
    ctx.quadraticCurveTo(23, 22, 26, 23);
    ctx.stroke();
    ctx.restore();
    ctx.draw();
  },

  drawNative(id, type) {
    tt.createSelectorQuery()
      .select(id)
      .node()
      .exec((res) => {
        const canvas = res[0].node;
        const ctx = canvas.getContext(type);
        this.drawByType(ctx, type, canvas);
      });
  },

  drawByType(ctx, type, canvas) {
    if (type === "2d") {
      nativeCanvas2d = canvas;
      nativeCanvas2dCtx = ctx;
      this.drawNative2D(0, 0, 50, 50);
      this.drawNative2D(50, 50, 50, 50);
    } else {
      nativeCanvasGl = canvas;
      nativeCanvasGlCtx = ctx;
      this.drawNativeGL(1, 0, 1, 1);
    }
  },

  drawNative2D(x, y, width, height) {
    nativeCanvas2d.requestAnimationFrame(function () {
      nativeCanvas2dCtx.fillStyle = "red";
      nativeCanvas2dCtx.fillRect(x, y, width, height);
    });
  },

  drawNativeGL(r, g, b, a) {
    nativeCanvasGl.requestAnimationFrame(function () {
      nativeCanvasGlCtx.clearColor(r, g, b, a);
      nativeCanvasGlCtx.clear(nativeCanvasGlCtx.COLOR_BUFFER_BIT);
    });
  },

  testBindtouchstart(e) {
    console.log("--- touchstart", e);
  },

  testBindtouchmove(e) {
    console.log("--- touchmove", e);
  },

  testBindtouchend(e) {
    console.log("--- touchend", e);
  },

  testBindtouchcancel(e) {
    console.log("--- touchcancel", e);
  },

  testBinderror(err) {
    console.log("==== canvas err", err);
  },
});

扫码体验

请使用字节宿主APP扫码

Bug & Tip

  • Tip: <canvas> 组件的默认宽度为 300px,高度为 225px。
  • Tip: iOS 下,<canvas> 组件的画布面积(宽度 ✖️ 高度)最大为 16777216 。
  • Tip: 若指定了 type 属性,且为合法值,则为 canvas 新方案,该组件为原生组件,使用时请注意相关限制。
  • Tip: 【V2】Android 基础库 1.87.0 起支持同层渲染。
  • Tip: 【V2】提供了释放 canvas 的方法,为减少内存占用,建议离开页面时通过 CanvasContext.canvas.dispose() 主动释放 canvas 的资源,释放后绑定的 CanvasContext 将无法使用。
  • Tip: 【V2】若修改 <canvas> 组件的宽高,也需要修改对应 canvas 画布的宽高(如CanvasContext.canvas.width=100)。
  • Tip: 【V2】画布初始尺寸同组件尺寸,插入后需要将画布尺寸设置为设备相同比例,同时缩放 CanvasContext x,y 轴方向比例,可参考 代码示例
点击纠错
评价此篇文档