如何解决html2Canvas 截图video画面异常问题

502 阅读1分钟

前提

html2canvas 1.4.1 + 项目中使用到了video标签 + video标签设置了object-fit样式属性

问题:截取的video画面变形

解决方案,html2canvas.js源码中找到createVideoClone。然后替换内部实现。

```      DocumentCloner.prototype.createVideoClone = function (video) {
          var canvas = video.ownerDocument.createElement('canvas');
          canvas.width = video.offsetWidth;
          canvas.height = video.offsetHeight;
          var sx = 0, sy = 0, sWidth = video.videoWidth, // video.offsetWidth,
          sHeight = video.videoHeight, // video.offsetHeight,
          dx = 0, dy = 0, dWidth = canvas.width, dHeight = canvas.height;
          var scaleX = dWidth / sWidth;
          var scaleY = dHeight / sHeight;
          if (video.style.objectFit === 'cover') {
              var scale = Math.max(scaleX, scaleY);
              sx = (sWidth - dWidth / scale) / 2;
              sy = (sHeight - dHeight / scale) / 2;
              if (scaleX > scaleY) {
                  // 宽度撑满,高度截取
                  sHeight = dHeight / scale;
              }
              else {
                  // 高度撑满,宽度截取
                  sWidth = dWidth / scale;
              }
              this.context.logger.info('video1', video.style.objectFit, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight);
          }
          else if (video.style.objectFit === 'contain') {
              var scale = Math.min(scaleX, scaleY);
              dx = (dWidth - sWidth * scale) / 2;
              dy = (dHeight - sHeight * scale) / 2;
              if (scaleX > scaleY) {
                  // 高度撑满,宽度留白
                  dWidth = sWidth * scale;
              }
              else {
                  // 宽度撑满,高度留白
                  dHeight = sHeight * scale;
              }
              this.context.logger.info('video2', video.style.objectFit, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight);
          }
          var ctx = canvas.getContext('2d');
          try {
              if (ctx) {
                  // drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight)
                  ctx.drawImage(video, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight);
                  if (!this.options.allowTaint) {
                      // getImageData(sx, sy, sw, sh)
                      ctx.getImageData(0, 0, dWidth, dHeight);
                  }
              }
              return canvas;
          }
          catch (e) {
              this.context.logger.info("Unable to clone video as it is tainted", video);
          }
          var blankCanvas = video.ownerDocument.createElement('canvas');
          blankCanvas.width = video.offsetWidth;
          blankCanvas.height = video.offsetHeight;
          return blankCanvas;
      };