uni-app oneplus+8手机canvas超级卡顿
uni-app oneplus+8手机canvas超级卡顿
| 开发环境 | 版本号 | 项目创建方式 |
|---|---|---|
| Mac | 11.3 | HBuilderX |
产品分类:uniapp/App
PC开发环境操作系统:Mac
PC开发环境操作系统版本号:11.3
HBuilderX类型:正式
HBuilderX版本号:3.2.16
手机系统:Android
手机系统版本号:Android 11
手机厂商:oppo旗下一加手机
手机机型:Oneplus 8T
页面类型:vue
vue版本:vue2
打包方式:云端
项目创建方式:HBuilderX
示例代码:
<view id="canvasPanel" :style="'width:' + ctxWidth + 'px;height:' + ctxWidth + 'px;margin:0 auto;position:relative;'">
<canvas type="2d" canvas-id="myCanvas" id="myCanvas"
:style="'width:' + ctxWidth + 'px;height:' + ctxWidth + 'px;position:absolute;top:0;left:0;right:0;'" >
<p style="color:white;"></p>
</canvas>
<canvas type="2d" canvas-id="pointCanvas" id="pointCanvas"
@touchstart="canvasTouchStartHandler"
@touchend="canvasTouchEndHandler" @touchmove="canvasTouchMoveHandler"
:style="'width:' + ctxWidth + 'px;height:' + ctxWidth + 'px;position:absolute;top:0;left:0;right:0;z-index:8888;'">
</canvas>
</view>
canvasTouchStartHandler(event) {
var eventPos = this.getOtherToucchIntOffset(event);
// this.bigEventImg();
const { x, y } = event.changedTouches[0];
this.reDrawEventImg(x, y);
},
canvasTouchEndHandler(event) {
var eventPos = this.getToucchEndIntOffset(event);
// this.smallerEventImg();
const { x, y } = event.changedTouches[0];
// this.reDrawEventImg(x, y);
this.updateColor(eventPos.X, eventPos.Y);
},
getOtherToucchIntOffset(event) {
return this.getToucchIntOffset(event.changedTouches[0]);
},
getToucchEndIntOffset(event) {
return this.getToucchIntOffset(event.changedTouches[0]);
},
getToucchIntOffset(touch) {
var pageX = parseInt(touch.x);
var pageY = parseInt(touch.y);
return { X: pageX, Y: pageY };
},
getToucchSelectorQuery() {
uni.createSelectorQuery().select('#canvasPanel').boundingClientRect(data => {
if (!data || data.length === 0) {
setTimeout(() => this.getToucchSelectorQuery(), 20)
return
}
this.position = data;
}).exec();
},
canvasTouchMoveHandler(event) {
event.preventDefault();
var eventPos = this.getOtherToucchIntOffset(event);
// this.reDrawEventImg(eventPos.X, eventPos.Y);
this.updateColor(eventPos.X, eventPos.Y);
},
reDrawEventImg(mouseX, mouseY) {
if (!this.pointInWheel(mouseX, mouseY)) {
return;
}
// this.pointCanvas.clearRect(mouseX - 20, mouseY - 20, 40, 40);
this.pointCanvas.drawImage(this.strawIcon, mouseX - 20, mouseY - 20, 40, 40);
this.pointCanvas.draw()
},
generateImageData() {
const that = this;
uni.canvasGetImageData({
canvasId: 'myCanvas',
x: 0,
y: 0,
width: that.ctxWidth,
height: that.ctxHeight,
success(res) {
that.imageData = res.data;
}
})
},
updateColor(mouseX, mouseY) {
if (this.pointInWheel(mouseX, mouseY) == false) {
return;
}
// 3. redraw the wheel event img
this.reDrawEventImg(mouseX, mouseY);
const that = this;
if(this.imageData.length > 0) {
let data = this.imageData;
var i = ((mouseY * that.ctxWidth) + mouseX) * 4;
// get RGBA values
var hexVal = (that.d2Hex(data[i]) + that.d2Hex(data[i + 1]) + that.d2Hex(data[i + 2]));
that.setCurrentColor(data[i], data[i + 1], data[i + 2]);
that.hexVal = hexVal
} else {
uni.canvasGetImageData({
canvasId: 'myCanvas',
x: 0,
y: 0,
width: that.ctxWidth,
height: that.ctxHeight,
success(res) {
var data = res.data;
that.imageData = data;
var i = ((mouseY * that.ctxWidth) + mouseX) * 4;
// get RGBA values
var hexVal = (that.d2Hex(data[i]) + that.d2Hex(data[i + 1]) + that.d2Hex(data[i + 2]));
that.setCurrentColor(data[i], data[i + 1], data[i + 2]);
that.hexVal = hexVal
}
})
}
}
操作步骤: 参照以上代码实现方式
预期结果: 色环取值滑动流畅,不卡顿
实际结果: 色环取值滑动超级卡顿
bug描述: canvas实时画图超级卡顿
更多关于uni-app oneplus+8手机canvas超级卡顿的实战教程也可以访问 https://www.itying.com/category-93-b0.html
1 回复
更多关于uni-app oneplus+8手机canvas超级卡顿的实战教程也可以访问 https://www.itying.com/category-93-b0.html
根据你的代码和描述,问题主要出在频繁调用uni.canvasGetImageData导致的性能瓶颈。在touchmove事件中实时获取整个canvas的像素数据,对OnePlus 8这类机型也会造成明显卡顿。
核心优化方案:
-
避免高频获取完整ImageData
- 将
generateImageData()的调用移至色环初始化阶段,仅执行一次 - 在
updateColor中直接使用已缓存的this.imageData
- 将
-
优化坐标计算逻辑
updateColor(mouseX, mouseY) { if (!this.pointInWheel(mouseX, mouseY)) return; // 使用缓存的imageData if (this.imageData && this.imageData.length > 0) { const index = ((mouseY * this.ctxWidth) + mouseX) * 4; const [r, g, b] = [ this.imageData[index], this.imageData[index + 1], this.imageData[index + 2] ]; this.setCurrentColor(r, g, b); this.hexVal = this.d2Hex(r) + this.d2Hex(g) + this.d2Hex(b); } // 减少重绘频率 this.throttleRedraw(mouseX, mouseY); } -
添加绘制节流
let lastDrawTime = 0; throttleRedraw(x, y) { const now = Date.now(); if (now - lastDrawTime > 16) { // 约60fps this.reDrawEventImg(x, y); lastDrawTime = now; } }

