开发
API

canvas

基础库 1.0.0 开始支持 V1 版本,基础库 1.78.0 开始支持 V2 版本。

画布。可使用 JS 操作 Canvas 上下文进行绘制。目前支持 V1,V2 两个版本,说明如下:

属性说明

V1

属性名类型默认值必填说明最低支持版本
canvas-idstringcanvas 组件的标识1.0.0

V2

属性名类型默认值必填说明最低支持版本
typestring指定 canvas 类型,有效值为 "2d" 和 "webgl"1.78.0
bindtouchstarteventhandle手指触摸动作开始1.78.0
bindtouchmoveeventhandle手指触摸后移动1.78.0
bindtouchendeventhandle手指触摸动作结束1.78.0
bindtouchcanceleventhandle手指触摸动作被打断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 canvas,
  gl,
  width,
  height,
  nativeCanvas2d,
  nativeCanvas2dCtx,
  nativeCanvasGl,
  nativeCanvasGlCtx;
let stopAnimate = false;
let animateId = -1;
Page({
  data: {
    width: 100,
    id: "123",
  },
  onReady() {
    let res = tt.getSystemInfoSync();
    this.draw_web(this.data.id);
    this.draw_native("#canvas_type_2d", "2d");
    this.draw_native("#canvas_type_webgl", "webgl");
  },
  onUnload() {
    this.cancelAnimationFrame();
  },
  draw_web(id) {
    console.log(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();
  },
  draw_native(id, type) {
    tt.createSelectorQuery()
      .select(id)
      .node()
      .exec((res) => {
        const canvas = res[0].node;
        let ctx = canvas.getContext(type);
        this.draw_byType(ctx, type, canvas);
      });
  },
  draw_byType(ctx, type, canvas) {
    if (type === "2d") {
      nativeCanvas2d = canvas;
      nativeCanvas2dCtx = ctx;
      this.draw_native_2d(0, 0, 50, 50);
      this.draw_native_2d1(50, 50, 50, 50);
    } else {
      nativeCanvasGl = canvas;
      nativeCanvasGlCtx = ctx;
      this.draw_native_gl(1, 0, 1, 1);
    }
  },
  draw_native_2d(x, y, width, height) {
    let that = this;
    let num = nativeCanvas2d.requestAnimationFrame(function () {
      nativeCanvas2dCtx.fillStyle = "red";
      nativeCanvas2dCtx.fillRect(x, y, width, height);
    });
  },
  draw_native_2d1(x, y, width, height) {
    let that = this;
    let num = nativeCanvas2d.requestAnimationFrame(function () {
      nativeCanvas2dCtx.fillStyle = "red";
      nativeCanvas2dCtx.fillRect(x, y, width, height);
    });
  },
  draw_native_gl(r, g, b, a) {
    let that = this;
    nativeCanvasGl.requestAnimationFrame(function () {
      nativeCanvasGlCtx.clearColor(r, g, b, a);
      nativeCanvasGlCtx.clear(nativeCanvasGlCtx.COLOR_BUFFER_BIT);
    });
  },
  drawGl(e) {
    gl = canvas.getContext("webgl", { alpha: true });
    gl.clearColor(0.0, 0.3, 0.0, 1.0);
    gl.clear(gl.COLOR_BUFFER_BIT);
    this.cancelAnimationFrame();
  },
  cancelAnimationFrame() {
    if (!stopAnimate) {
      stopAnimate = true;
      canvas.cancelAnimationFrame(animateId);
    }
  },
  testBindtouchstart(e) {
    console.log("mytouchstart", e);
  },
  testBindtouchmove(e) {
    console.log("mytouchmove", e);
  },
  testBindtouchend(e) {
    console.log("mytouchend", e);
  },
  testBindtouchcancel(e) {
    console.log(e);
  },
  testBinderror(err) {
    console.error("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 轴方向比例,可参考 代码示例
点击纠错
评价此篇文档