程小玄o
程小玄o
  • 发布:2024-03-13 18:10
  • 更新:2024-04-12 11:51
  • 阅读:702

[微信小程序] canvasToTempFilePath:fail Failed

分类:uni-app

返回的错误信息:

{"errMsg":"canvasToTempFilePath:fail Failed to execute 'drawImage' on 'CanvasRenderingContext2D': The provided value is not of type '(CSSImageValue or HTMLImageElement or SVGImageElement or HTMLVideoElement or HTMLCanvasElement or ImageBitmap or OffscreenCanvas or VideoFrame)'"}

代码如下:

<template>  
  <view class="c-display-flex-V-center my-page-container" @click="downloadImg">  
    <!-- <view class="my-page-canvas-core">  
      <image src="../../static/images/invitation_head.png" class="core-head-image" />  
      <view class="core-content-image" />  
    </view> -->  
    <!-- <canvas canvas-id="myCanvas" class="my-page-canvas" /> -->  
    <canvas type="2d" id="myCanvas" class="my-page-canvas" />  
  </view>  
</template>  

<script>  
  const ctxW = 280;  
  const ctxH = 275;  
  export default {  
    name: 'invitation',  
    components: {  
      myGridItem,  
    },  
    data() {  
      return {  
        canvasObject: undefined,  
      };  
    },  
    beforeCreate() {  
      console.log('beforeCreate enter');  
    },  
    created() {  
      console.log('created enter');  
    },  
    mounted() {  
      console.log('mounted enter');  
    },  
    onLoad(option) {  
      console.log('onLoad');  
    },  
    onReady() {  
      this.drawCanvas();  
    },  
    methods: {  
      /* 注: 使用createCanvasContext绘制出来的画面模糊。 */  
      // drawCanvas() {  
      //   let offsetY = 15;  
      //   const ctxW = 280;  
      //   const ctxH = 275;  

      //   const ctx = uni.createCanvasContext('myCanvas', this);  

      //   /* 绘制背景颜色 */  
      //   // ctx.setFillStyle('orange');  
      //   // ctx.fillRect(0, 0, ctxW, ctxH);  

      //   /* 绘制头部图片 */  
      //   ctx.drawImage('../../static/images/invitation_head.png', (ctxW - 250) / 2, offsetY, 250, 35);  

      //   /* 绘制二维码 */  
      //   offsetY += (35 + 10);  
      //   ctx.setFillStyle('#f3f3f3');  
      //   ctx.fillRect((ctxW - 200) / 2, offsetY, 200, 200);  

      //   ctx.draw();  
      // },  
      drawCanvas() {  
        /* query.select("#id") / uery.select(".class") */  
        const query = uni.createSelectorQuery().in(this);  
        let _this = this;  

        // query.select("#myCanvas")  
        //   .boundingClientRect((data) => {  
        //     console.log("得到布局信息: " + JSON.stringify(data));  
        //   })  
        //   .exec();  

        query.select("#myCanvas")  
          .fields({  
            node: true,  
            size: true,  
          })  
          .exec(async (res) => {  
            console.log("res: " + JSON.stringify(res));  
            _this.canvasObject = res[0].node.id;  
            const canvas = res[0].node;  
            const ctx = canvas.getContext('2d');  
            console.log('canvas.ctx', ctx.drawImage);  

            let offsetY = 15;  
            const dpr = wx.getSystemInfoSync().pixelRatio;  
            canvas.width = ctxW * dpr;  
            canvas.height = ctxH * dpr;  
            console.log('canvas.size', canvas.width, canvas.height);  
            ctx.scale(dpr, dpr);  

            /* 绘制背景颜色 */  
            // ctx.fillStyle = 'orange';  
            // ctx.fillRect(0, 0, ctxW, ctxH);  

            /* 绘制头部图片 */  
            let _offsetY = offsetY;  
            const imageSrc = '../../static/images/invitation_head.png';  
            //let image = new Image();  
            let image = canvas.createImage();  
            // image.src = imageSrc;  
            // image.onload = () => {  
            //   ctx.drawImage(image, (ctxW - 250) / 2, _offsetY, 250, 35);  
            // };  
            await new Promise(resolve => {  
              image.onload = resolve;  
              image.src = imageSrc;  
            });  
            ctx.drawImage(image, (ctxW - 250) / 2, _offsetY, 250, 35);  

            /* 绘制二维码 */  
            offsetY += (35 + 10);  
            ctx.fillStyle = '#f3f3f3';  
            ctx.fillRect((ctxW - 200) / 2, offsetY, 200, 200);  
          });  
      },  
      downloadImg() {  
        uni.showLoading({  
          title: '正在下载...',  
        });  
        uni.canvasToTempFilePath({  
          //canvasId: 'myCanvas',  
          canvas: this.canvasObject,  
          x: 0,  
          y: 0,  
          width: ctxW,  
          height: ctxH,  
          destWidth: ctxW,  
          destHeight: ctxH,  
          quality: 1.0,  
          success: function(res) {  
            console.log('canvasToTempFilePath_success');  
            uni.saveImageToPhotosAlbum({  
              filePath: res.tempFilePath,  
              success: function(saveRes) {  
                uni.showToast({  
                  title: '保存成功',  
                });  
              },  
              fail: function(saveErr) {  
                if (saveErr.errMsg === 'saveImageToPhotosAlbum:fail:auth denied' ||  
                  saveErr.errMsg === 'saveImageToPhotosAlbum:fail auth deny' ||  
                  saveErr.errMsg === 'saveImageToPhotosAlbum:fail authorize no response'  
                ) {  
                  uni.showModal({  
                    title: '需要您授权保存相册',  
                    modalType: false,  
                    success: modalRes => {  
                      uni.openSetting({  
                        success(settingRes) {  
                          console.log('settingRes', JSON.stringify(settingRes));  
                          if (settingRes.authSetting['scope.writePhotosAlbum']) {  
                            wx.showModal({  
                              title: '温馨提醒',  
                              content: '获取权限成功,再次点击保存即可~',  
                              modalType: false,  
                            })  
                          } else {  
                            wx.showModal({  
                              title: '温馨提醒',  
                              content: '获取权限失败,将无法保存到相册哦~',  
                              modalType: false,  
                            })  
                          }  
                        },  
                        fail(settingError) {  
                          console.log('settingError', JSON.stringify(settingError));  
                        },  
                      });  
                    },  
                  });  
                }  
              },  
            });  
          },  
          fail: function(err) {  
            console.log('canvasToTempFilePath_fail', JSON.stringify(err));  
            uni.showToast({  
              title: '生成图片失败',  
            });  
          },  
        }, this);  
      },  
    },  
  }  
</script>  

<style scoped>  
  .my-page-container {  
    background-color: white;  
    height: 500px;  
  }  

  .my-page-canvas {  
    width: 280px;  
    height: 275px;  
  }  

  .my-page-canvas-core {  
    box-sizing: border-box;  
    width: 280px;  
    height: 275px;  
    padding: 15px;  
    display: flex;  
    flex-direction: column;  
    align-items: center;  
  }  

    .core-head-image {  
      width: 250px;  
      height: 35px;  
    }  

    .core-content-image {  
      margin-top: 10px;  
      width: 200px;  
      height: 200px;  
      background-color: #f3f3f3;  
    }  
</style>
2024-03-13 18:10 负责人:无 分享
已邀请:
喜欢技术的前端

喜欢技术的前端 - QQ---445849201

加上 canvas-id="myCanvas"

<canvas type="2d" id="myCanvas" canvas-id="myCanvas" class="my-page-canvas" />
  • 程小玄o (作者)

    谢谢,我刚这样试了一下,报错信息:{"errMsg":"canvasToTempFilePath:fail fail canvas is empty"}

    2024-03-14 09:55

  • 喜欢技术的前端

    回复 程小玄o: 这个报错是因为你的canvas 没有画出来内容,你需要调整下业务逻辑,我写了个例子


    <template>  
    <view class="c-display-flex-V-center my-page-container" @click="downloadImg">
    <canvas style="width: 300px; height: 200px;" canvas-id="myCanvas" id="myCanvas"></canvas>
    </view>
    </template>

    <script>
    const ctxW = 280;
    const ctxH = 275;
    export default {
    onReady() {
    var context = uni.createCanvasContext('myCanvas')
    context.setStrokeStyle("#00ff00")
    context.setLineWidth(5)
    context.rect(0, 0, 200, 200)
    context.stroke()
    context.draw()
    },
    methods: {
    downloadImg() {
    uni.showLoading({
    title: '正在下载...',
    });
    console.log(ctxW, ctxH)
    uni.canvasToTempFilePath({
    canvasId: 'myCanvas',
    x: 0,
    y: 0,
    width: ctxW,
    height: ctxH,
    destWidth: ctxW,
    destHeight: ctxH,
    quality: 1.0,
    success: function(res) {
    console.log('canvasToTempFilePath_success');
    uni.saveImageToPhotosAlbum({
    filePath: res.tempFilePath,
    success: function(saveRes) {
    uni.showToast({
    title: '保存成功',
    });
    },
    fail: function(saveErr) {
    if (saveErr.errMsg === 'saveImageToPhotosAlbum:fail:auth denied' ||
    saveErr.errMsg === 'saveImageToPhotosAlbum:fail auth deny' ||
    saveErr.errMsg ===
    'saveImageToPhotosAlbum:fail authorize no response'
    ) {
    uni.showModal({
    title: '需要您授权保存相册',
    modalType: false,
    success: modalRes => {
    uni.openSetting({
    success(settingRes) {
    console.log('settingRes',
    JSON.stringify(
    settingRes));
    if (settingRes.authSetting[
    'scope.writePhotosAlbum'
    ]) {
    wx.showModal({
    title: '温馨提醒',
    content: '获取权限成功,再次点击保存即可~',
    modalType: false,
    })
    } else {
    wx.showModal({
    title: '温馨提醒',
    content: '获取权限失败,将无法保存到相册哦~',
    modalType: false,
    })
    }
    },
    fail(settingError) {
    console.log('settingError',
    JSON.stringify(
    settingError));
    },
    });
    },
    });
    }
    },
    });
    },
    fail: function(err) {
    console.log(JSON.stringify(err));
    uni.showToast({
    title: '生成图片失败',
    });
    },
    }, this);
    },
    },
    }
    </script>

    <style scoped>
    .my-page-container {
    background-color: white;
    height: 500px;
    }

    .my-page-canvas {
    width: 280px;
    height: 275px;
    }

    .my-page-canvas-core {
    box-sizing: border-box;
    width: 280px;
    height: 275px;
    padding: 15px;
    display: flex;
    flex-direction: column;
    align-items: center;
    }

    .core-head-image {
    width: 250px;
    height: 35px;
    }

    .core-content-image {
    margin-top: 10px;
    width: 200px;
    height: 200px;
    background-color: #f3f3f3;
    }
    </style>

    2024-03-14 11:22

  • 程小玄o (作者)

    这样确实可以,但是往canvas上绘制的图片很模糊,而且这个canvas-id在微信小程序中要废弃了 https://developers.weixin.qq.com/miniprogram/dev/api/canvas/wx.createCanvasContext.html#参数

    2024-03-14 13:58

程小玄o

程小玄o (作者)

已解决。canvas在下载的时候再先使用createSelectorQuery查找到,而不是使用之前查找的对象。参考链接 https://developers.weixin.qq.com/community/develop/article/doc/000242073903a04e082ab595b52013 。

  • z***@163.com

    大佬你好 能给出最终代码学习一下吗

    2024-10-28 11:51

要回复问题请先登录注册