我最近收到一位客户提出的提供此功能的请求,它必须是 CMS 友好的。该技术涉及三大理念
- 绘图功能
- 重复调用同一个绘图函数
- 使用
requestAnimationFrame 绘制下一帧
假设您已经有一个视频元素,您将采取以下步骤
- 隐藏视频元素
- 创建一个高度/宽度与视频元素匹配的画布元素,并将其存储在某处
- 使用 `canvas.getContext('2d') 获取画布元素的上下文并将其存储在某处
- 创建绘图函数
- 在该绘图函数中,您可以使用
canvas.drawImage(src, x, y),其中src 是视频当前帧的编辑版本;
- 在该绘图函数中,使用递归再次调用自身
我可以给你两个例子来说明这一点(并且可用于内容管理系统)
第一个在这里:https://jsfiddle.net/yywL381w/19/
一家名为 SDL 的公司开发了一种名为 Media Manager 的工具来托管视频。您看到的是一个 jQuery 插件,它从 data-* 获取其参数,从 Media Manager Rest API 发出请求,创建视频,并完全基于 data* 属性添加效果。该插件可以轻松调整以处理从其他来源调用的视频。您可以查看repo 以获取有关使用的更多详细信息。
另一个例子在这里:http://codepen.io/paceaux/pen/egLOeR
那不是 jQuery 插件;它是一个 ES6 类。您可以使用以下方法创建图像/视频并应用裁剪效果:
let imageModule = new ImageCanvasModule(module);
imageModule.createCanvas();
imageModule.drawOnCanvas();
imageModule.hideOriginal();
您将在 ImageCanvasModule 类中观察到这个方法:
drawFrame () {
if (this.isVideo && this.media.paused) return false;
let x = 0;
let width = this.media.offsetWidth;
let y = 0;
this.imageFrames[this.module.dataset.imageFrame](this.backContext);
this.backContext.drawImage(this.media, x, y, width, this.canvas.height);
this.context.drawImage(this.backCanvas, 0, 0);
if (this.isVideo) {
window.requestAnimationFrame(()=>{
this.drawFrame();
});
}
}
该类创建了第二个画布,用于绘图。该画布是不可见的,这只是他们为浏览器节省了一些心痛。
内容可管理的“操纵”是this.imageFrames[this.module.dataset.imageFrame](this.backContext);
“帧”是存储在图像/视频上的属性(可以通过 CMS 中的模板输出)。这将获取 imageFrame 的名称,并将其作为匹配函数运行。它还会在上下文中发送(因此如果需要,我可以在背面画布或主画布上的绘图之间切换)
然后this.backContext.drawImage(this.media, x, y, width, this.canvas.height); 在后面的上下文中绘制图像。
最后,这出现在带有this.context.drawImage(this.backCanvas, 0, 0); 的主画布上,我在其中取出后画布,并将其绘制到主画布上。因此可见的画布具有最少的操作量。
最后,因为这是一个视频,我们要绘制一个新帧。所以我们有函数调用本身:
if (this.isVideo) {
window.requestAnimationFrame(()=>{
this.drawFrame();
});
整个设置允许我们使用 CMS 输出 data-* 属性,其中包含用户想要在图像周围绘制的框架类型。 JavaScript 然后生成该图像或视频的画布版本。示例标记可能如下所示:
<video muted loop autoplay data-image-frame="wedgeTop">