uni-app canvas组件在H5环境下效率非常低

uni-app canvas组件在H5环境下效率非常低

项目信息 详情
产品分类 uniapp/H5
PC开发环境操作系统 Mac
PC开发环境操作系统版本号 11.2.1
HBuilderX类型 正式
HBuilderX版本号 3.1.4
浏览器平台 Chrome
浏览器版本 88.0.4324.192
项目创建方式 HBuilderX

示例代码:

示例代码:

drawImageQueue(images, obj, done) {  
    //  
    console.log('打印图片', images);  
    let queue = [];  
    let self = this;  
    let ctx = this.getCanvasContext(obj);  
    let isClear = false;  
    if (typeof (images) === 'string') {  
      images = [images];  
    }  
    for (let img of images) {  
      if (img.length > 0) {  
        queue.push(img);  
      }  
    }  
    let doQueue = function () {  
      let src = null;  
      if (queue.length > 0) {  
        src = queue[0];  
        queue.splice(0, 1);  
        uni.getImageInfo({  
          src: src,  
          success(res) {  
            if (!isClear) {  
              isClear = true;  
              ctx.clearRect(0, 0, self.size.width, self.size.height);  
            }  
            ctx.drawImage(res.path, 0, 0, self.size.width, self.size.height)  
            if (queue.length > 0) {  
              doQueue();  
            } else {  
              ctx.draw(true,() => {  
                typeof (done) === 'function' && done.call();  
              });  
            }  
          },  
          fail(res) {  
            console.error('img fail', src,res);  
            if (queue.length > 0) {  
              doQueue();  
            } else {  
              ctx.draw(true,() => {  
                typeof (done) === 'function' && done.call();  
              });  
            }  
          }  
        });  
      }  
    }  
    doQueue();  
},  

使用console.time+console.timeEnd 平均执行时间在200ms以上

function drawImage(images,done) {  

    console.log('打印图片', images);  
    var queue = [];  
    var isClear = false;  
    if (typeof (images) === 'string') {  
        images = [images];  
    }  
    for (var i = 0;i<images.length;i++) {  
        var img = images[i];  
        if (img.length > 0) {  
            queue.push(img);  
        }  
    }  
    var doQueue = function () {  
        var src = null;  
        if (queue.length > 0) {  
            src = queue[0];  
            queue.splice(0, 1);  
            getImage({  
                src: src,  
                success:function(res) {  
                    console.log('res',res)  
                    if (!isClear) {  
                        isClear = true;  
                        ctx.clearRect(0, 0, size.width, size.height);  
                    }  
                    ctx.drawImage(res.path[0], 0, 0, size.width, size.height)  
                    if (queue.length > 0) {  
                        doQueue();  
                    } else {  
                        typeof (done) === 'function' && done.call();  
                    }  
                },  
                fail:function(res) {  
                    console.error('img fail', src,res);  
                    if (queue.length > 0) {  
                        doQueue();  
                    } else {  
                        typeof (done) === 'function' && done.call();  
                    }  
                }  
            });  
        }  
    }  
    doQueue();  
}  

function getImage(opt) {  
    var img = new Image(1920,1080);  
    img.src = opt.src;  
    img.onload = opt.success;  
    img.oncompvare = opt.success;  
}

使用console.time+console.timeEnd 平均执行时间在60ms以内

图片使用同样的地址。使用的本机图片,加载耗时不超过5ms


### 操作步骤:


#### 操作步骤:

```javascript
drawImageQueue(images, obj, done) {  
    //  
    console.log('打印图片', images);  
    let queue = [];  
    let self = this;  
    let ctx = this.getCanvasContext(obj);  
    let isClear = false;  
    if (typeof (images) === 'string') {  
      images = [images];  
    }  
    for (let img of images) {  
      if (img.length > 0) {  
        queue.push(img);  
      }  
    }  
    let doQueue = function () {  
      let src = null;  
      if (queue.length > 0) {  
        src = queue[0];  
        queue.splice(0, 1);  
        uni.getImageInfo({  
          src: src,  
          success(res) {  
            if (!isClear) {  
              isClear = true;  
              ctx.clearRect(0, 0, self.size.width, self.size.height);  
            }  
            ctx.drawImage(res.path, 0, 0, self.size.width, self.size.height)  
            if (queue.length > 0) {  
              doQueue();  
            } else {  
              ctx.draw(true,() => {  
                typeof (done) === 'function' && done.call();  
              });  
            }  
          },  
          fail(res) {  
            console.error('img fail', src,res);  
            if (queue.length > 0) {  
              doQueue();  
            } else {  
              ctx.draw(true,() => {  
                typeof (done) === 'function' && done.call();  
              });  
            }  
          }  
        });  
      }  
    }  
    doQueue();  
},

### 预期结果:


#### 预期结果:


无

### 实际结果:


#### 实际结果:


无

### bug描述:


#### bug描述:

绘制多张图片到画布上的过程中,
使用uni-app的 `drawImage+draw` 相比原生H5中使用`drawImage`的方式,
执行效率相差非常大  

这个版本还存在图片base64后如果里面有rpx 或upx 时,会导致base64的值错误。

更多关于uni-app canvas组件在H5环境下效率非常低的实战教程也可以访问 https://www.itying.com/category-93-b0.html

3 回复

你是说drawImage使用 base64 的时候包含 rpx 会报错吗?

更多关于uni-app canvas组件在H5环境下效率非常低的实战教程也可以访问 https://www.itying.com/category-93-b0.html


我现在使用的 3.1.4.20210305 还是有这个问题。 是在从canvas里获取图片转为base64 到外面的image中使用时,如果内容里含有 rpx 还是会导致图片无法显示, 只能使用img标签来处理。 image组件 中的img标签是可以显示图片的, 但是同级的div中背景图片无法显示,导致空白

在H5环境下,uni-app的Canvas性能问题主要源于其API封装机制。uni.getImageInfo()和ctx.draw()涉及跨层通信和额外的数据序列化开销,这显著增加了执行时间。

原生H5的Image对象直接加载图片并绘制到Canvas上,整个过程在浏览器渲染线程内完成,效率更高。而uni-app的API需要经过框架桥接,每次调用都涉及JavaScript与原生层的交互,特别是在连续绘制多张图片时,这种开销会被放大。

建议在H5场景下,如果对性能要求较高,可以直接使用原生Canvas API。uni-app支持条件编译,可以在H5平台使用原生代码,其他平台继续使用uni-app API:

// #ifdef H5
// 使用原生Canvas API
// #endif
// #ifndef H5  
// 使用uni-app API
// #endif
回到顶部