news 2026/10/29 2:10:22

微信小程序:canvas组件

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
微信小程序:canvas组件

一 实现功能

  1. 手指触摸画布自由绘制手写线条;
  2. 清空画布按钮,一键清除画布所有笔迹;
  3. ✨作业扩展:改变画笔线条颜色按钮,循环切换画笔颜色;
  4. 适配设备像素比 dpr,解决真机画布线条模糊。

二 项目初始化

新建小程序项目,不使用云服务、不使用模板。

案例要求renderer设置为webview渲染模式。

app.json

{ "pages": [ "pages/index/index" ], "window": { "navigationBarTextStyle": "black", "navigationStyle": "custom" }, "style": "v2", "renderer": "webview", "componentFramework": "glass‑easel", "sitemapLocation": "sitemap.json", "lazyCodeLoading": "requiredComponents" }

1、页面布局 index.wxml

<!--index.wxml--> <scroll-view class="scrollarea" scroll-y type="list"> <view class="box"> <view class="title">自由绘图</view> <canvas type="2d" id="my‑canvas" bind:touchstart="paintStart" bind:touchmove="paintMove"></canvas> <view class="btn‑layout"> <button type="primary" size="mini" bind:tap="clear">清空画布</button> <button type="primary" size="mini" bind:tap="changePenColor">改变画笔线条颜色</button> </view> </view> </scroll-view>

2、样式代码

pages/index/index.wxss

/*index.wxss*/ page { height: 100vh; display: flex; flex-direction: column; } .scrollarea { flex: 1; overflow‑y: hidden; } canvas { width: 100%; height: 800rpx; background‑color: cornflowerblue; } .btn‑layout { margin‑top: 20rpx; display: flex; justify‑content: space‑evenly; gap:20rpx; }

app.wxss 全局样式

/**app.wxss**/ .box { margin: 20rpx; padding: 20rpx; border: 2rpx solid purple; } .title { font‑size: 40rpx; font‑weight: bolder; text‑align: center; margin‑bottom: 30rpx; color: red; }

3、业务逻辑 index.js【核心代码】

// index.js Page({ data:{ // 画笔颜色数组,循环切换 colorList:["#ff0000","#00ff00","#0000ff","#ffff00"], colorIndex:0 }, onReady() { const query = wx.createSelectorQuery() query.select('#my‑canvas') .fields({ node: true, size: true }) .exec((res) => { const canvas = res[0].node const ctx = canvas.getContext('2d') // 获取设备像素比 const dpr = wx.getSystemInfoSync().pixelRatio // 设置画布实际像素宽高 canvas.width = res[0].width * dpr canvas.height = res[0].height * dpr // 坐标缩放适配设备像素 ctx.scale(dpr, dpr) this.canvas = canvas this.ctx = ctx }) }, // 触摸开始 paintStart(e) { let x = e.touches[0].x let y = e.touches[0].y let ctx = this.ctx // 获取当前选中画笔颜色 let currentColor = this.data.colorList[this.data.colorIndex] ctx.strokeStyle = currentColor ctx.lineCap = 'round' ctx.lineJoin = 'round' ctx.lineWidth = 5 ctx.moveTo(x, y) }, // 触摸移动,绘制线条 paintMove(e) { let x = e.touches[0].x let y = e.touches[0].y let ctx = this.ctx let currentColor = this.data.colorList[this.data.colorIndex] ctx.strokeStyle = currentColor ctx.lineTo(x, y) ctx.stroke() }, // 清空画布 clear() { let canvas = this.canvas let ctx = this.ctx ctx.beginPath() ctx.clearRect(0, 0, canvas.width, canvas.height) }, //作业扩展:切换画笔颜色 changePenColor(){ let idx = this.data.colorIndex idx = idx +1 if(idx >= this.data.colorList.length){ idx =0 } this.setData({ colorIndex: idx }) wx.showToast({ title:`已切换画笔颜色`, icon:"none", duration:800 }) } })

三 运行效果说明

  1. 页面初始化:蓝色背景画布,默认画笔红色,手指滑动就可以涂鸦写字;
  2. 清空画布按钮:点击画布全部清除,回到空白画板;
  3. 改变画笔线条颜色按钮:点击弹出提示,之后新绘制线条切换颜色(红→绿→蓝→黄循环);已经画好的笔迹不会变色,属于 Canvas2D 特性;
  4. 清空画布之后,继续绘画使用已经切换后的画笔颜色,和课程作业截图效果完全一致。

四 核心知识点总结

1.canvas 2D 组件

新版<canvas type="2d">不再使用旧版canvas‑id,通过SelectorQuery拿到原生 node 对象,调用getContext('2d')获取绘图上下文。

2. 绘图常用 API

表格

API作用
moveTo(x,y)将画笔移动到起始坐标
lineTo(x,y)绘制直线到目标坐标
stroke()执行描边,真正绘制线条
lineCap:'round'设置线条端点圆润
lineJoin:'round'设置线条拐角圆润
clearRect(x,y,w,h)清空指定矩形画布区域
beginPath()开启全新绘图路径

3. 设备像素比 dpr

手机屏幕物理像素远大于 css 像素,画布宽高需要乘以 dpr,同时执行ctx.scale(dpr,dpr),否则真机绘制线条模糊。

4. 切换画笔颜色逻辑

维护颜色数组,点击按钮修改颜色索引;必须在paintStart、paintMove事件内部重新赋值strokeStyle,否则绘制的时候颜色会失效。

⚠注意:Canvas 绘制完成之后像素直接渲染到画布,不会保存绘图对象,旧笔迹不能直接修改颜色;如果想要修改旧笔迹颜色,需要自己保存全部笔画点位,清空画布再全部重绘。

⚠踩坑记录

  1. 真机线条模糊:忘记设置canvas.width = res[0].width*dpr,没有执行 scale 缩放;
  2. 清空画布残留线条:清空画布前没有调用beginPath()开启新路径;
  3. 切换颜色失效:仅仅在 changePenColor 修改 strokeStyle,没有在触摸事件重新赋值;
  4. canvas 属于原生组件,部分 css 样式会有兼容性限制。
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/29 2:09:20

轻松上手大模型:Langchain入门指南,小白程序员必备(收藏版)

Langchain作为大模型的高度封装工具&#xff0c;简化了原生大模型的使用。文章详细介绍了Langchain的调用方式&#xff0c;包括本地部署、标准接口和request模式&#xff0c;并深入讲解了Langchain的异步调用、流式输出、batch模式、多轮对话、Message封装、模板构建以及输出格…

作者头像 李华
网站建设 2026/10/29 2:08:02

MATLAB实战:毫米波雷达与摄像头融合,如何用卡尔曼滤波稳定追踪前车?

MATLAB实战:毫米波雷达与摄像头融合,如何用卡尔曼滤波稳定追踪前车? 关键词:MATLAB、ADAS、毫米波雷达、摄像头融合、卡尔曼滤波、EKF、目标跟踪、传感器融合 在智能驾驶开发中,摄像头能够识别车辆外观、车道线和交通标志,但在强光、夜间和恶劣天气下,视觉检测可能受到…

作者头像 李华
网站建设 2026/10/29 2:07:33

2. 字符串/模拟题/链表-lc-python

3. 无重复字符的最长子串 - 力扣&#xff08;LeetCode&#xff09; 给定一个字符串 s &#xff0c;请你找出其中不含有重复字符的 最长子串 的长度。 示例 1: 输入: s "abcabcbb" 输出: 3 解释: 因为无重复字符的最长子串是 "abc"&#xff0c;所以其长…

作者头像 李华
网站建设 2026/10/29 2:05:31

OE_HP910安装双系统二

OE&#xff1a;Operation and Engineering 重点结论先讲清楚现在纠正了关键信息&#xff1a;Windows 和给 Ubuntu 的 158G 空闲分区&#xff0c;都在同一块 512G GPT 固态&#xff08;磁盘 0&#xff0c;nvme0n1&#xff09;上&#xff0c;不是跨两块盘。 ✅ 方案本身可以做&am…

作者头像 李华
网站建设 2026/10/29 2:04:31

MIRED 色温尺度与直方图插值详解

MIRED 色温尺度与直方图插值详解 —— 兼论普朗克轨迹投影中"投影距离"的几何语义 本文回答两个问题: 投影投票法中的"投影距离"到底是什么?——是的,它是色度点到普朗克轨迹垂足(投影点)的垂直距离(“高”),即沿等温线方向的偏移量,本质就是 Du…

作者头像 李华