Play part of a video in a canvas

淺唱寂寞╮ 提交于 2019-12-13 15:15:35

问题


I would like to play only half of my video on a canvas but truncated on the diagonal. At the moment I can play my full video in a canvas easyli using this little javascript:

var video = document.getElementById('video');
var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d');

var drawFrame = function drawFrame() {
    context.drawImage(video, 0, 0, canvas.width, canvas.height);
    requestAnimationFrame(drawFrame);
};

requestAnimationFrame(drawFrame);

In the end, I want to be able to play 2 videos, at the same time (I just have to call drawImage on each video), but each will be cut on diagonal, to render something like this:

I then want to move the separator depending on the mouse position.


回答1:


You can use composition to achieve this.

Compositions uses the alpha channel to combine non-alpha data in various way, for example "source-in" will paint source image/video where there exist pixels while "destination-over" will keep the existing pixels where there is non-alpha and only paint new ones where there is alpha (these are also known as Porter-Duff or alpha composition. Blending comes under the same umbrella but has a different purpose than compositing).

There are many modes but the above mentioned ones will allow us to combine them to get the part we want just by defining an alpha region that function as a mask for both. I'll include an overview to show how the operators work for each mode to better understand what they do (from Wikipedia):


(A = source, B = destination)

The steps needed in this case would be:

  • Initialize with composition mode "source-over" as we use this in a loop
  • Clear canvas to make sure we have an alpha channel to work with
  • Draw diagonal half relative to the mouse position
  • Draw video source 2 on top using "source-in" (to place it at the left side)
  • Draw video source 1 on top using "destination-over"

Working Example

This will load two different videos (links borrowed from here) and when loaded sets up the loop as described above (just give the videos a few seconds to load):

var ctx = c.getContext("2d"), pos = c.width * 0.5, count = 2;
ctx.fillText("Please wait while videos are loading...", 20, 20);
video1.oncanplay = video2.oncanplay = function() {if (!--count) renderFrame()};

function renderFrame() {
  ctx.globalCompositeOperation = "source-over";
  ctx.clearRect(0, 0, c.width, c.height);     // makes sure we have an alpha channel

  ctx.beginPath();                            // draw diagonal half
  ctx.moveTo(0, 0);
  ctx.lineTo(pos - 50, 0);
  ctx.lineTo(pos + 50, c.height);
  ctx.lineTo(0, c.height);
  ctx.fill();

  // video source 2
  ctx.globalCompositeOperation = "source-in";        // comp in source 2
  ctx.drawImage(video2, 0, 0, c.width, c.height);
  
  // video source 1
  ctx.globalCompositeOperation = "destination-atop"; // comp in source 1
  ctx.drawImage(video1, 0, 0, c.width, c.height);

  requestAnimationFrame(renderFrame)
}

c.onmousemove = function(e) {
  pos = e.clientX - c.getBoundingClientRect().left;
}
video {display:none}
<canvas id=c width=640 height=400></canvas>
<video id=video1 muted autoplay loop src="http://media.w3.org/2010/05/sintel/trailer.mp4"></video>
<video id=video2 muted autoplay loop src="http://media.w3.org/2010/05/video/movie_300.webm"></video>


来源:https://stackoverflow.com/questions/37547659/play-part-of-a-video-in-a-canvas

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!