美文网首页
input[type=file]选择图片兼容问题以及canvas

input[type=file]选择图片兼容问题以及canvas

作者: AAA前端 | 来源:发表于2021-09-02 13:03 被阅读0次

    本次需求需要用户选择照片或拍照后,把图片用canvas绘制(添加其他的文字,背景图等),生成照片让用户可以保存。
    开始限制用户不能传gif图片。所有 input

    <input
          type="file"
          value="上传图片"
          class="upload"
          @change="handleFileChange"
          ref="inputer"
          accept="image/png,image/jpeg,image/jpg"
        />
    
    

    实际开发中,发现ios没问题。但是安卓只能用相册,无法唤起相机。
    所有这里只能用

    <input
          type="file"
          value="上传图片"
          class="upload"
          @change="handleFileChange"
          ref="inputer"
          accept="image/*"
        />
    

    用户传gif后,只是绘制gif图第一帧。

    other
    记录下本次主要绘制的核心代码
    drawPoster函数绘制一个数组,由于照片要等待加载好之后才能继续绘制,不然有遮挡。
    然后绘制用户照片的时候,可能用户传的照片与实际绘制区域不一样,用coverImg转换。实现img的cover效果
    util.js

    
    /**
     * @param {Number} box_w 固定盒子的宽, box_h 固定盒子的高
     * @param {Number} source_w 原图片的宽, source_h 原图片的高
     * @return {Object} {截取的图片信息},对应drawImage(imageResource, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight)参数
    */
    function coverImg(sx, sy, box_w, box_h, source_w, source_h) {
      var sx = 0,
        sy = 0,
        sWidth = source_w,
        sHeight = source_h;
      if (source_w > source_h || (source_w == source_h && box_w < box_h)) {
        sWidth = box_w * sHeight / box_h;
        sx = (source_w - sWidth) / 2;
      } else if (source_w < source_h || (source_w == source_h && box_w > box_h)) {
        sHeight = box_h * sWidth / box_w;
        sy = (source_h - sHeight) / 2;
      }
      return {
        sx,
        sy,
        sWidth,
        sHeight
      }
    }
    
    export function drawPoster(obj, list) {
    
      return new Promise(async (resolve, reject) => {
    
        const oCanvas = document.createElement('canvas');
        const context = oCanvas.getContext('2d');
        oCanvas.width = obj.w;
        oCanvas.height = obj.h;
    
        for (var i in list) {
          await addPoster(list[i])
        }
        async function addPoster(item) {
          return new Promise((_res, _rej) => {
            if (item.type == 2) {
              QRCode.toDataURL(item.keyword).then((qrCodeSrc) => {
    
                const qrCodeImg = new Image();
                qrCodeImg.crossOrigin = 'anonymous';
                qrCodeImg.src = qrCodeSrc;
                qrCodeImg.onload = () => {
                  // 计算x、y值
                  const x = item.dx;
                  const y = item.dy;
                  console.log(111, item);
                  // 绘制
                  context.drawImage(qrCodeImg, x, y, item.width, item.height);
                  _res(2222);
                };
              }).catch((err) => {
                _rej(err);
                throw new Error('海报生成失败');
              });
            } else if (item.type == 3) {
              const otherImg = new Image();
              otherImg.crossOrigin = 'anonymous';
              otherImg.src = item.keyword;
              otherImg.onload = () => {
                // 计算x、y值
                const x = item.dx;
                const y = item.dy;
                if (item.origin) {
                  context.drawImage(otherImg, x, y, item.width, item.height)
                  _res(3333);
                  return false
                }
                var imgRect = coverImg(0, 0, item.width, item.height, otherImg.width, otherImg.height);
                context.drawImage(otherImg, imgRect.sx, imgRect.sy, imgRect.sWidth, imgRect.sHeight, x, y, item.width, item.height)
                _res(3333);
              };
            } else {
              context.font = `400 ${item.fontSize}px PingFang SC`;
              if (item.color) {
                context.fillStyle = item.color;
                // context.strokeStyle = '#fff';
              }
              context.fillText(item.keyword, item.dx, item.dy);
              // context.strokeText(item.keyword, item.dx + 1, item.dy + 1);
              context.stroke();
              _res(11111);
            }
          });
        }
        resolve(oCanvas.toDataURL('image/png', 1));
    
      });
    }
    
    

    实际调用的代码(由于展示,有些东西需要自己修改)

     async canvasP1() {
          // 第一个参数:绘制区域大小   , 第二个参数:需要绘制的内容
          const r = await drawPoster({ w: 696, h: 1074 }, [
            {
              type: 3,
              keyword: this.headImg,
              dx: 60,
              dy: 60,
              width: 600,
              height: 700,
            },
            {
              type: 3,
              keyword:
                'https://daxueui-oss.koocdn.com/images/fe_upload/2021/8/2021-8-27-1630055577557.png',
              dx: 0,
              dy: 0,
              width: 696,
              height: 1074,
              origin: true,
            },
            {
              color: '#011232',
              fontSize: 26,
              keyword: this.label,
              dx: 510,
              dy: 778,
            },
            {
              color: '#fff',
              fontSize: 23,
              keyword: '@' + this.name,
              dx: 100 - this.nameX,
              dy: 115,
            },
            {
              color: '#005256',
              fontSize: 22,
              keyword: this.declarationObj.declaration1,
              dx: 30,
              dy: 865,
            },
            {
              color: '#005256',
              fontSize: 22,
              keyword: this.declarationObj.declaration2,
              dx: 30,
              dy: 925,
            },
            {
              color: '#005256',
              fontSize: 22,
              keyword: this.declarationObj.declaration3,
              dx: 30,
              dy: 985,
            },
          ])
          this.canvasSrc1 = r
        },
    ...
    

    相关文章

      网友评论

          本文标题:input[type=file]选择图片兼容问题以及canvas

          本文链接:https://www.haomeiwen.com/subject/gpnqwltx.html