The video is not played correctly when a clipPath is attached to the object.
The video updates the frames only when you resize the object.
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);
});
Looks like fabric.js relies heavily on caching when Image object has a clipPath.
During the render call, it checks this.needsItsOwnCache()
which returns true
because this.clipPath
is present.
Then it calls this.renderCache()
, which only updates the cached canvas if this.isCacheDirty()
returns true
.
For it to return true, you can utilize the object's statefullCache
and cacheProperties
setting a custom videoTime
property with a value of video element's currentTime
.
Then you just make sure to update videoTime
on each animation frame.
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>