# Canvas 画布

Canvas 画布组件,支持2D和WebGL渲染,提供统一的跨平台画布API。

# 平台差异说明

App(vue) App(nvue) H5 小程序
X

# 基本使用

<template>
  <view>
    <u-canvas :width="300" :height="200" ref="canvas"></u-canvas>
    <u-button @click="drawBasicShapes">绘制基本图形</u-button>
  </view>
</template>

<script>
export default {
  methods: {
    async drawBasicShapes() {
      const canvasContext = await this.$refs.canvas.getCanvasContext();
      const { canvas } = canvasContext;
      
      // 绘制矩形
      canvas.fillStyle = '#ff6b6b';
      canvas.fillRect(20, 20, 80, 60);
      
      // 绘制描边矩形
      canvas.strokeStyle = '#4ecdc4';
      canvas.lineWidth = 3;
      canvas.strokeRect(120, 20, 80, 60);
      
      // 绘制圆形
      canvas.fillStyle = '#45b7d1';
      canvas.beginPath();
      canvas.arc(60, 120, 30, 0, 2 * Math.PI);
      canvas.fill();
      
      // 绘制线条
      canvas.strokeStyle = '#f9ca24';
      canvas.lineWidth = 4;
      canvas.beginPath();
      canvas.moveTo(120, 120);
      canvas.lineTo(200, 120);
      canvas.lineTo(160, 160);
      canvas.closePath();
      canvas.stroke();
      
      canvas.draw();
    }
  }
};
</script>
✅ Copy success!

# 绘制图形

<template>
  <view>
    <u-canvas 
      :width="300" 
      :height="200"
      ref="basicCanvas"
    ></u-canvas>
    <u-button @click="drawBasicShapes">绘制基本图形</u-button>
    <u-button @click="clearCanvas">清空画布</u-button>
  </view>
</template>

<script>
export default {
  methods: {
    async drawBasicShapes() {
      const canvasContext = await this.$refs.basicCanvas.getCanvasContext();
      const { canvas } = canvasContext;
      
      // 绘制矩形
      canvas.fillStyle = '#ff6b6b';
      canvas.fillRect(20, 20, 80, 60);
      
      // 绘制描边矩形
      canvas.strokeStyle = '#4ecdc4';
      canvas.lineWidth = 3;
      canvas.strokeRect(120, 20, 80, 60);
      
      // 绘制圆形
      canvas.fillStyle = '#45b7d1';
      canvas.beginPath();
      canvas.arc(60, 120, 30, 0, 2 * Math.PI);
      canvas.fill();
      
      // 绘制线条
      canvas.strokeStyle = '#f9ca24';
      canvas.lineWidth = 4;
      canvas.beginPath();
      canvas.moveTo(120, 120);
      canvas.lineTo(200, 120);
      canvas.lineTo(160, 160);
      canvas.closePath();
      canvas.stroke();
      
      canvas.draw();
    },
    
    async clearCanvas() {
      const canvasContext = await this.$refs.basicCanvas.getCanvasContext();
      const { canvas, width, height } = canvasContext;
      canvas.clearRect(0, 0, width, height);
      canvas.draw();
    }
  }
};
</script>
✅ Copy success!

# 绘制文字

<template>
  <view>
    <u-canvas 
      :width="300" 
      :height="200"
      ref="textCanvas"
    ></u-canvas>
    <u-button @click="drawText">绘制文字</u-button>
    <u-button @click="clearTextCanvas">清空画布</u-button>
  </view>
</template>

<script>
export default {
  methods: {
    async drawText() {
      const canvasContext = await this.$refs.textCanvas.getCanvasContext();
      const { canvas } = canvasContext;
      
      // 设置字体样式
      canvas.font = '20px Arial';
      canvas.fillStyle = '#333';
      canvas.textAlign = 'center';
      canvas.textBaseline = 'middle';
      
      // 绘制填充文字
      canvas.fillText('Hello uView Canvas', 150, 50);
      
      // 绘制描边文字
      canvas.strokeStyle = '#ff6b6b';
      canvas.lineWidth = 2;
      canvas.strokeText('Stroke Text', 150, 100);
      
      // 设置阴影
      canvas.shadowColor = 'rgba(0,0,0,0.3)';
      canvas.shadowBlur = 8;
      canvas.shadowOffsetX = 2;
      canvas.shadowOffsetY = 2;
      canvas.fillStyle = '#4ecdc4';
      canvas.fillText('Shadow Text', 150, 150);
      
      canvas.draw();
    },
    
    async clearTextCanvas() {
      const canvasContext = await this.$refs.textCanvas.getCanvasContext();
      const { canvas, width, height } = canvasContext;
      canvas.clearRect(0, 0, width, height);
      canvas.draw();
    }
  }
};
</script>
✅ Copy success!

# 图表绘制

# 柱状图

<template>
  <view>
    <u-canvas 
      :width="300" 
      :height="200"
      ref="chartCanvas"
    ></u-canvas>
    <u-button @click="drawChart">绘制柱状图</u-button>
  </view>
</template>

<script>
export default {
  methods: {
    async drawChart() {
      const canvasContext = await this.$refs.chartCanvas.getCanvasContext();
      const { canvas, width, height } = canvasContext;
      
      const data = [60, 80, 45, 90, 70];
      const colors = ['#ff6b6b', '#4ecdc4', '#45b7d1', '#f9ca24', '#6c5ce7'];
      const barWidth = 30;
      const barSpacing = 20;
      const startX = 30;
      const maxHeight = 120;
      
      // 清空画布
      canvas.clearRect(0, 0, width, height);
      
      // 绘制柱状图
      data.forEach((value, index) => {
        const barHeight = (value / 100) * maxHeight;
        const x = startX + index * (barWidth + barSpacing);
        const y = height - 30 - barHeight;
        
        canvas.fillStyle = colors[index];
        canvas.fillRect(x, y, barWidth, barHeight);
        
        // 绘制数值标签
        canvas.fillStyle = '#333';
        canvas.font = '12px Arial';
        canvas.textAlign = 'center';
        canvas.fillText(value.toString(), x + barWidth / 2, y - 5);
      });
      
      canvas.draw();
    }
  }
};
</script>
✅ Copy success!

# 饼图

<template>
  <view>
    <u-canvas 
      :width="300" 
      :height="200"
      ref="pieCanvas"
    ></u-canvas>
    <u-button @click="drawPieChart">绘制饼图</u-button>
  </view>
</template>

<script>
export default {
  methods: {
    async drawPieChart() {
      const canvasContext = await this.$refs.pieCanvas.getCanvasContext();
      const { canvas, width, height } = canvasContext;
      
      const data = [30, 25, 20, 15, 10];
      const colors = ['#ff6b6b', '#4ecdc4', '#45b7d1', '#f9ca24', '#6c5ce7'];
      const centerX = width / 2;
      const centerY = height / 2;
      const radius = 60;
      
      // 清空画布
      canvas.clearRect(0, 0, width, height);
      
      let currentAngle = -Math.PI / 2; // 从顶部开始
      
      data.forEach((value, index) => {
        const sliceAngle = (value / 100) * 2 * Math.PI;
        
        // 绘制扇形
        canvas.fillStyle = colors[index];
        canvas.beginPath();
        canvas.moveTo(centerX, centerY);
        canvas.arc(centerX, centerY, radius, currentAngle, currentAngle + sliceAngle);
        canvas.closePath();
        canvas.fill();
        
        // 绘制标签
        const labelAngle = currentAngle + sliceAngle / 2;
        const labelX = centerX + Math.cos(labelAngle) * (radius + 20);
        const labelY = centerY + Math.sin(labelAngle) * (radius + 20);
        
        canvas.fillStyle = '#333';
        canvas.font = '12px Arial';
        canvas.textAlign = 'center';
        canvas.fillText(`${value}%`, labelX, labelY);
        
        currentAngle += sliceAngle;
      });
      
      canvas.draw();
    }
  }
};
</script>
✅ Copy success!

# 图片处理

# 绘制图片

<template>
  <view>
    <u-canvas 
      :width="300" 
      :height="200"
      ref="imageCanvas"
    ></u-canvas>
    <u-button @click="drawImage">绘制图片</u-button>
  </view>
</template>

<script>
export default {
  methods: {
    async drawImage() {
      const canvasContext = await this.$refs.imageCanvas.getCanvasContext();
      const { canvas, width, height } = canvasContext;
      
      // 清空画布
      canvas.clearRect(0, 0, width, height);
      
      // 绘制真实图片
      const imageUrl = 'https://uview.d3u.cn/web/static/uview/common/50c02fb7gy1i0vn1f8mbuj20qo13eal2.jpg';
      canvas.drawImage(imageUrl, 27, 0, 246, 364);
      
      canvas.draw();
    }
  }
};
</script>
✅ Copy success!

# 导出图片

<template>
  <view>
    <u-canvas 
      :width="300" 
      :height="200"
      ref="exportCanvas"
    ></u-canvas>
    <u-button @click="exportImage">导出图片</u-button>
  </view>
</template>

<script>
export default {
  methods: {
    async exportImage() {
      try {
        const tempFilePath = await this.$refs.exportCanvas.canvasToTempFilePath({
          x: 0,
          y: 0,
          width: 300,
          height: 200,
          destWidth: 300,
          destHeight: 200,
          fileType: 'png',
          quality: 1
        });
        
        console.log('图片已保存到:', tempFilePath);
        uni.showToast({
          title: '图片导出成功',
          icon: 'success'
        });
      } catch (error) {
        console.error('导出失败:', error);
        uni.showToast({
          title: '导出失败',
          icon: 'error'
        });
      }
    }
  }
};
</script>
✅ Copy success!

# 页面源码地址

页面源码地址


 github  gitee

# API

# Props

参数 说明 类型 默认值 可选值
width 画布宽度 String | Number 375 -
height 画布高度 String | Number - -
type 画布类型 String 2d(微信小程序/抖音小程序)
webgl(其他平台)
2d | webgl
disableScroll 是否禁用滚动 Boolean false true
hidpi 是否启用高清 Boolean true false

# Events

事件名 说明 回调参数
onTouchstart 触摸开始 event
onTouchmove 触摸移动 event
onTouchend 触摸结束 event
onTouchcancel 触摸取消 event
onLongtap 长按 event
onError 错误事件 event

# Methods

方法名 说明 参数 返回值
getCanvasContext 获取画布上下文 - Promise<{canvas, width, height, canvasId, use2D}>
queryCanvas 查询画布节点信息 - Promise<{node, size}>
canvasToTempFilePath 导出画布为临时文件 options Promise<string>

# canvasToTempFilePath 参数

参数 说明 类型 默认值
x 画布x轴起点 Number 0
y 画布y轴起点 Number 0
width 画布宽度 Number canvas宽度
height 画布高度 Number canvas高度
destWidth 输出图片宽度 Number width
destHeight 输出图片高度 Number height
fileType 图片格式 String png
quality 图片质量 Number 1
上次更新时间: 2025/9/20 08:47:51
🌟 真诚邀请 🌟
如果你觉得本项目对你有帮助
欢迎访问我们的Gitee/Github 仓库为我们点个 Star!
×