FabricJS 视频上的 clipPath 问题

FabricJS Problem with clipPath on a video

当 clipPath 附加到对象时,视频无法正确播放。

视频仅在您调整对象大小时更新帧。

var canvas = new fabric.Canvas('canvas');
var videoEl = document.getElementById('video');

var clipText = new fabric.Text('My Custom Text', { 
    left: 'center',
    top: 'center', 
    fontSize: 40,
});

var video = new fabric.Image(videoEl, {
    left: 10,
    top: 10,
    angle: 0,
    originX: 0,
    originY: 0,
    objectCaching: false,
    clipPath: clipText,
    backgroundColor: '#ff0000'
});

canvas.add(video);
video.getElement().play();

fabric.util.requestAnimFrame(function render() {
  canvas.renderAll();
  fabric.util.requestAnimFrame(render);
});

当 Image 对象具有 clipPath 时,看起来 fabric.js 严重依赖缓存。

在渲染调用期间,它会检查 this.needsItsOwnCache() 哪个 return 和 true,因为存在 this.clipPath。 然后它调用 this.renderCache(),它只更新缓存的 canvas if this.isCacheDirty() returns true.

要使其 return 为真,您可以利用对象的 statefullCache and cacheProperties 设置自定义 videoTime 属性,其值为视频元素的 currentTime。 然后你只需确保在每个动画帧上更新 videoTime

const canvas = new fabric.Canvas("c");
const clipText = new fabric.Text("My Custom Text", {
  left: "center",
  top: "center",
  fontSize: 36
});
const videoEl = document.querySelector("#video");
const video = new fabric.Image(videoEl, {
  left: 10,
  top: 10,
  angle: 0,
  originX: 0,
  originY: 0,
  objectCaching: true,
  statefullCache: true,
  cacheProperties: ['videoTime'],
  clipPath: clipText,
  backgroundColor: "#ff0000"
});
canvas.add(video);
video.getElement().play();
fabric.util.requestAnimFrame(function render() {
  canvas.renderAll();
  video.videoTime = videoEl.currentTime;
  fabric.util.requestAnimFrame(render);
});
document.querySelector("#button").onclick = () => {
  video.clipPath = video.clipPath == null ? clipText : null;
};
body {
  background: ivory;
}

.row {
  display: flex;
  flex-direction: row;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/3.5.0/fabric.js"></script>
<div class="row">
  <canvas id="c" width="300" height="200"></canvas>
  <video id="video" width="240" height="180" autoplay loop muted >
    <source src="https://html5demos.com/assets/dizzy.mp4">
  </video>
</div>
<button id="button">toggle</button>