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

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



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


用户传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绘制图片功能)