当前位置: 首页 > news >正文

uniapp:微信小程序使用Canvas 和Canvas 2D绘制图形

一、Canvas 画布

canvas 组件 提供了绘制界面,可以在之上进行任意绘制

功能描述
Canvas 画布。2.9.0 起支持一套新 Canvas 2D 接口(需指定 type 属性),同时支持同层渲染,原有接口不再维护。

二、Canvas 和Canvas 2D 区别

  • Canvas 2D 需指定 type 属性
  • Canvas 属性 canvas-id ,Canvas 2D改成 id
  • Canvas 标签默认宽度300px、高度150px
  • Canvas 2D(新接口)需要显式设置画布宽高,默认:300*150,最大:1365*1365
<canvas class="pie-chart" canvas-id="chartOrg"></canvas>
<canvas class="pie-chart" type="2d" id="chart2d"></canvas>

API的区别

Canvas新版 Canvas 2D
canvasContext.draw()canvasContext接口没有 draw 方法
canvasContext.setFillStyle(“#000000”)canvasContext.fillStyle = “#000000”
canvasContext.setFontSize(16)canvasContext.font = ‘16px PingFang SC’
canvasContext.setTextAlign(‘center’)canvasContext.textAlign = “center”

提醒:上面API的区别是下面示例用到的,还有其他API的变化,感兴趣的读者自行查阅。

三、示例用到的uni API

3.1 uni.createCanvasContext(canvasId, componentInstance)
3.1.1 定义

创建 canvas 绘图上下文(指定 canvasId)。在自定义组件下,第二个参数传入组件实例this,以操作组件内 组件

提醒: 需要指定 canvasId,该绘图上下文只作用于对应的

参数

参数类型说明
canvasIdString画布标识,传入定义在 的 canvas-id或id(支付宝小程序是id、其他平台是canvas-id)
componentInstanceObject自定义组件实例 this ,表示在这个自定义组件下查找拥有 canvas-id 的 ,如果省略,则不在任何自定义组件内查找

返回值:CanvasContext

3.2 uni.getSystemInfoSync()

获取系统信息的同步接口。调用参数和返回值和调用 uni.getSystemInfo() 一样。

3.3 uni.createSelectorQuery()

提醒

  • 使用 uni.createSelectorQuery() 需要在生命周期 mounted 后进行调用。
  • 默认需要使用到 selectorQuery.in 方法。

selectorQuery.in(component)
将选择器的选取范围更改为自定义组件 component 内,返回一个 SelectorQuery 对象实例。(初始时,选择器仅选取页面范围的节点,不会选取任何自定义组件中的节点)。

示例代码

const query = uni.createSelectorQuery().in(this);
query.select("#id").boundingClientRect((data) => {console.log("得到布局位置信息" + JSON.stringify(data));console.log("节点离页面顶部的距离为" + data.top);}).exec();

注意: 支付宝小程序不支持 in(component),使用无效果

四、微信小程序使用Canvas 和Canvas 2D绘制图形示例

示例效果图

在这里插入图片描述

testCanvas.vue代码

<template><view class="view-root-wrap"><view class="view-content-wrap"><view class="view-content"><text>使用canvas绘制</text><text>使用canvas 2D 绘制</text></view><view class="view-content"><canvas class="pie-chart" canvas-id="chartOrg"></canvas><canvas class="pie-chart"  type="2d" id="chart2d"></canvas></view></view></view>
</template>
<script>
export default {data() {return {isReady: false,}},onReady() {this.isReady = true// this.drawChartOrg()// this.startDrawChart2D()},onLoad(options) {this.drawChartOrg()this.startDrawChart2D()},methods: {// 绘制饼图drawChartOrg() {console.log(`执行了 drawChartOrg 方法  this.isReady = ${this.isReady}`)const canvasContext = uni.createCanvasContext('chartOrg', this)const centerX = 70 // 圆心x坐标const centerY = 70 // 圆心y坐标const innerRadius = 46;// 内圆半径const outerRadius = 70; // 外圆半径let chartData = [{ value: 3, color: '#7539f5', name: 'Fortran' },{ value: 4, color: '#91041c', name: 'Delphi/Object Pascal' },{ value: 4.5, color: '#0582a9', name: 'Visual Basic' },{ value: 5.5, color: '#39c8f5', name: 'Go' },{ value: 6, color: '#f2d407', name: 'JavaScript' },{ value: 7, color: '#480479', name: 'C#' },{ value: 9, color: '#f29707', name: 'Java' },{ value: 11, color: '#5620f3', name: 'C' },{ value: 15, color: '#0676c2', name: 'C++' },{ value: 35, color: '#339AF0', name: 'Python' },];const totalPercent = 100let startAngle = 1.5 * Math.PI // 起始角度// 绘制外圆chartData.forEach(item => {const sliceAngle = (2 * Math.PI * item.value) / totalPercentconst endAngle = startAngle + sliceAnglecanvasContext.beginPath()canvasContext.moveTo(centerX, centerY)canvasContext.arc(centerX, centerY, outerRadius, startAngle, endAngle)canvasContext.closePath()canvasContext.setFillStyle(item.color)canvasContext.fill()startAngle = endAngle})// 绘制内圆canvasContext.beginPath()canvasContext.arc(centerX, centerY, innerRadius, 0, 2 * Math.PI)canvasContext.setFillStyle('#FFFFFF')canvasContext.fill()// 添加中间文字canvasContext.setFontSize(16)canvasContext.setFillStyle('#000000')canvasContext.setTextAlign('center')canvasContext.fillText("编程语言", centerX, centerY + 8)canvasContext.draw()},startDrawChart2D() {console.log(`执行了 startDrawChart 方法  this.isReady = ${this.isReady}`)let delayTime = 500;if (this.isReady) {delayTime = 150}setTimeout(() => {this.drawChart2D()}, delayTime);},// 使用 Canvas2D 绘制饼图drawChart2D() {const query = uni.createSelectorQuery().in(this)query.select('#chart2d').fields({ node: true, size: true }).exec((res) => {try {let { node, width, height } = res[0];const canvas = nodeconst canvasContext = canvas.getContext('2d')const dpr = uni.getSystemInfoSync().devicePixelRatioconst tempWidth = width * dprcanvas.width = tempWidthcanvas.height = tempWidthcanvasContext.scale(dpr, dpr)const radius = width / 2const centerX = radius  // 圆心x坐标const centerY = radius // 圆心y坐标const outerRadius = radius; // 外圆半径const innerRadius = outerRadius * 0.65; // 内圆半径let chartData = [{ value: 3, color: '#7539f5', name: 'Fortran' },{ value: 4, color: '#91041c', name: 'Delphi/Object Pascal' },{ value: 4.5, color: '#0582a9', name: 'Visual Basic' },{ value: 5.5, color: '#39c8f5', name: 'Go' },{ value: 6, color: '#f2d407', name: 'JavaScript' },{ value: 7, color: '#480479', name: 'C#' },{ value: 9, color: '#f29707', name: 'Java' },{ value: 11, color: '#5620f3', name: 'C' },{ value: 15, color: '#0676c2', name: 'C++' },{ value: 35, color: '#339AF0', name: 'Python' },];const totalPercent = 100let startAngle = 1.5 * Math.PI // 起始角度// 绘制外圆chartData.forEach(item => {const sliceAngle = (2 * Math.PI * item.value) / totalPercentconst endAngle = startAngle + sliceAnglecanvasContext.beginPath()canvasContext.moveTo(centerX, centerY)canvasContext.arc(centerX, centerY, outerRadius, startAngle, endAngle)canvasContext.closePath()canvasContext.fillStyle = item.colorcanvasContext.fill()startAngle = endAngle})// 绘制内圆canvasContext.beginPath()canvasContext.arc(centerX, centerY, innerRadius, 0, 2 * Math.PI)canvasContext.fillStyle = "#FFFFFF"canvasContext.fill()// 添加中间文字canvasContext.font = '16px PingFang SC'canvasContext.fillStyle = "#000000"canvasContext.textAlign = "center"canvasContext.fillText("编程语言", centerX, centerY + 8)} catch (error) {console.log("drawChart2D 绘制发生异常: " + error)}})},}
}
</script>
<style scoped>
.view-root-wrap {padding: 12px;
}.view-content-wrap {display: flex;flex-direction: column;justify-content: center;background-color: white;padding: 28rpx;border-radius: 16rpx;
}.view-content {display: flex;flex-direction: row;justify-content: space-around;margin-top: 32rpx;
}.pie-chart {width: 140px;height: 140px;
}
</style>
http://www.lryc.cn/news/622970.html

相关文章:

  • nginx下载地址:aarch64
  • Scala面试题及详细答案100道(11-20)-- 函数式编程基础
  • 狗品种识别数据集:1k+图像,6个类别,yolo标注完整
  • linux docker neo4j 导出 (windows 导入)
  • duiLib 实现鼠标拖动状态栏时,窗口跟着拖动
  • 模型量化(Model Quantization)
  • 解决 Windows 下运行 MCP 脚本弹出 WSH 错误窗口的问题 | Windows Script Host
  • 【数据分析】比较SparCC、Pearson和Spearman相关性估计方法在合成组学数据上的表现
  • Footej Camera 2:专业级摄影体验,尽在掌中
  • 《代码重生:杨蓉与62.webp》
  • 2024-2025华为ICT大赛中国区 实践赛昇腾AI赛道(高职组)全国总决赛 理论部分真题+解析
  • 基本电子元件:金属氧化膜电阻器
  • 测试工程师的AI转型指南:从工具使用到测试策略重构
  • Vue组件基础解析
  • 机器学习--决策树
  • [Linux] RAID存储技术
  • 苍穹外卖日记
  • C:\Windows\WinSxS 目录详解
  • Python语言一键整理xhs评论 基于github的开源项目 MediaCrawler
  • MySQL 全文索引指南
  • Spring框架(AOP)
  • “openfeign“调用接口上传文件报错:Failed to deleted temporary file used for part [file]
  • 博士招生 | 香港大学 机器增强认知实验室 招收博士生/实习生/访问学生
  • 安卓11 12系统修改定制化_____修改系统默认域名解析规则 实现屏蔽广告 屏蔽应用更新等功能
  • CVE-2021-4300漏洞复现
  • css实现圆角+边框渐变+背景半透明
  • Camera相机人脸识别系列专题分析之十九:MTK ISP6S平台FDNode原生代码
  • 34 HTB Cat 机器 - 中等难度
  • Three.js三大组件:场景(Scene)、相机(Camera)、渲染器(Renderer)
  • GitHub PR 提交流程