淡入淡出从灰度到彩色的画布视频 [英] Fade canvas video from greyscale to color

查看:142
本文介绍了淡入淡出从灰度到彩色的画布视频的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有两个元素 - 视频和画布。在视频播放事件中,一个函数仅在画布上以灰度绘制相同的视频。然后我有一个按钮,应该从灰度淡出画布视频回到颜色。到目前为止,我已经设法在按钮点击时恢复颜色,但我需要淡入淡出 - 从灰度到彩色,不仅仅是即时显示颜色。



我怎么能做到这一点?或者......这甚至有可能吗?



以下是代码:

  function gray(){
if(!stop){
bgContext.drawImage(video,0,0,w,h);
var pixelData = bgContext.getImageData(0,0,w,h);
for(var i = 0; i< pixelData.data.length; i + = 4){
var r = pixelData.data [i];
var g = pixelData.data [i + 1];
var b = pixelData.data [i + 2];
var averageColour =(r + g + b)/ 3;
pixelData.data [i] = averageColour;
pixelData.data [i + 1] = averageColour;
pixelData.data [i + 2] = averageColour;
}
context.putImageData(pixelData,0,0);



function color(){
bgContext.drawImage(video,0,0,w,h);
var pixelData = bgContext.getImageData(0,0,w,h);
for(var i = 0; i< pixelData.data.length; i + = 4){
var r = pixelData.data [i];
var g = pixelData.data [i + 1];
var b = pixelData.data [i + 2];
pixelData.data [i] = r;
pixelData.data [i + 1] = g;
pixelData.data [i + 2] = b;
}
context.putImageData(pixelData,0,0);
}

video.addEventListener('play',function(){
setInterval(gray(),0);
},false);

button.addEventListener('click',function(){
stop = true;
setInterval(color(),0);
},false );


解决方案

实时视频/动画的画布过滤器



黑色&白色滤镜



做一个黑白滤镜很简单。

  // mixAmount是一个从0到1的值0 =没有混合1 =完整的FX 
//视频是视频
ctx.drawImage(video,0,0); //绘制视频
//设置过滤器
ctx.fillStyle =#888; //灰色
ctx.globalAlpha = mixAmount; // FX
的数量ctx.globalCompositeOperation =color; //设置为黑/白
ctx.fillRect(0,0,video.width,video.height); //在视频上绘制灰色
ctx.globalAlpha = 1; // reset alpha
ctx.globalCompositeOperation =source-over; // reset comp

或者您可以将视频渲染到其他FX上,演示显示黑色和白色过滤器,并通过使用上面的代码和一些额外的层数更多。



更多信息



有关显示视频的更多信息,请参阅



标题归属。 FX上下左右减轻,黑白,棕褐色,饱和度和负面。

该Demo具有以下FX打火机,变暗,黑/白,阴性,饱和度,棕褐色,B& W负值等。

Javascript



与问题相关的代码全部在顶部并标记。其余的是UI加载等。

每个FX都会调用 addMix addOverlay 来应用过滤器,如上面代码片段所示。 addMix 函数略有不同,因为它通过视频获取视频以获得FX而不是填充。



请注意,并非所有的浏览器都支持所有的模式(为什么?谁知道!! :()也没有办法成为100 %b





$ b $ p $%$% snippetdata-lang =jsdata-hide =falsedata-console =truedata-babel =false>

  // ================================= ========================================= //所有的混音功能都在这里sectionvar FXMix = 1; var addOverlay = function(type){if(FXMix> 0){ctx.globalCompositeOperation = type; ctx.globalAlpha = FXMix; ctx.fillRect(0,0,canvas.width,canvas.height); ctx.globalAlpha = 1; ctx.globalCompositeOperat ion =source-over; }} var addMix = function(type,video){if(FXMix> 0){ctx.globalCompositeOperation = type; ctx.globalAlpha = FXMix; ctx.drawImage(视频,0,0,canvas.width,canvas.height); ctx.globalAlpha = 1; ctx.globalCompositeOperation =source-over; }} var fill = function(style){ctx.globalAlpha = FXMix; ctx.fillStyle = style; ctx.fillRect(0,0,canvas.width,canvas.height); var FX = {} var FXList = []; var currentFX =; var addFX = function(name,func){FXList.push(name); FX [name] = func; currentFX = name;} // multiply,screen,overlay,color-dodge,color-burn,hard-light,soft-light,difference,exclusion,hue,saturation,color,luminosityaddFX(Ligher,(vid)=> ; {addMix(lighter,vid);}); addFX(BlackWhite,(vid)=> {ctx.fillStyle =#888; addOverlay(color);}); addFX(Negative (vid)=> {ctx.fillStyle =#FFF; addOverlay(difference);}); addFX(Sepia,(vid)=> {fill(#F94); addMix (luminosity,vid);;}); addFX(B& W Negative,(vid)=> {ctx.fillStyle =#FFF; addOverlay(difference); ctx.fillStyle =# 888; addOverlay(color);}); addFX(Ligher +,(vid)=> {addMix(lighter,vid); addMix(lighter,vid); addMix(lighter vid);}); addFX(B& W Lighten,(vid)=> {addMix(lighter,vid); ctx.fillStyle =#888; addOverlay(color);}); addFX(Darken +,(vid)=> {addMix(multiply,vid); addMix(multiply,vid); addMix(multiply,vid);}); addFX(Darken,( vid)=> {addMix(multiply,vid);}); addFX(Saturate,()=> {ctx.fillStyle =#F00; addOverlay(saturation) ;}); addFX(None,()=> {}); // FX混音结束// ======================= ================================================== = var mediaSource =http://video.webmfiles.org/big-buck-bunny_trailer.webm\";var mediaSource =http://upload.wikimedia.org/wikipedia/commons/7/79/Big_Buck_Bunny_small.ogv ; var muted = true; var canvas = document.getElementById(myCanvas); //从pagevar获取画布ctx = canvas.getContext(2d); var videoContainer; //对象来保存视频和相关的infovar视频= document.createElement(video); //创建一个视频elementvideo.src = mediaSource; //现在开始加载视频//因为需要一些额外的信息,我们会将视频放置在一个// contains对象中,以便于使用easevideo.autoPlay = false; //确保视频不会自动播放play.loop = true; //将视频设置为loop.video.muted = muted; videoContainer = {//我们将根据需要添加属性video:video,ready:false,}; //处理错误。这不是当前例子的一部分。只修复不喜欢ogv格式的Edge videovideo.onerror = function(e){document.body.removeChild(canvas); document.body.innerHTML + =< h2>加载视频< / h2>< br>< br>时出现问题; document.body.innerHTML + =IE9 +的用户,浏览器不支持此演示使用的WebM视频; document.body.innerHTML + =< br>< a href ='https://tools.google.com/dlpage/webmmf/'>从tools.google.com<下载IE9 + WebM支持< / a> br>这包括Edge和Windows 10; } video.oncanplay = readyToPlayVideo; //将事件设置为播放函数//可以在函数中找到readyToPlayVideo(event){//这是对视频的参考//视频可能与画布大小不匹配,因此找到适合videoContainer.scale = Math.min(canvas.width / this.videoWidth,canvas.height / this.videoHeight); videoContainer.ready = true; //可以播放视频,以便将它交给显示功能requestAnimationFrame(updateCanvas); //添加指令document.getElementById(playPause)。textContent =点击视频播放/暂停。; document.querySelector(。mute)。textContent =Mute;} var playClick = false; function updateCanvas(){ctx.clearRect(0,0,canvas.width,canvas.height);如果已加载并准备好,则只绘制if(videoContainer!== undefined&& videoContainer.ready){//在画布上找到视频的左上角video.muted =静音; var scale = videoContainer.scale; var vidH = videoContainer.video.videoHeight; var vidW = videoContainer.video.videoWidth; var top = canvas.height / 2  - (vidH / 2)* scale; var left = canvas.width / 2  - (vidW / 2)* scale; //现在只需绘制正确大小的视频ctx.drawImage(videoContainer.video,left,top,vidW * scale,vidH * scale); FX [currentFX](videoContainer.video);如果(videoContainer.video.paused){//如果不播放显示暂停的屏幕drawPayIcon(); } overUI = false; cursor =default; drawSlider(); drawList();如果(mouse.over){if(!overUI){if((mouse.button& 1)=== 1){// bit field playClick = true; } if((mouse.button& 1)=== 0&& playClick){//位字段playClick = false; playPauseClick(); } cursor =pointer; }} if(showFXName> 0){showFXName = Math.max(0,showFXName  -  0.05); ctx.globalAlpha = Math.min(1,showFXName); ctx.font =32px Arial; ctx.textAlign =center; ctx.textbaseLine =middle; ctx.fillStyle =white; ctx.strokeStyle =黑色; ctx.lineJoin =roundctx.strokeText(currentFX,canvas.width / 2,canvas.height / 2); ctx.fillText(currentFX,canvas.width / 2,canvas.height / 2); ctx.globalAlpha = 1; } canvas.style.cursor = cursor; } //全部用于显示//请求第二个requestAnimationFrame(updateCanvas)的1/60秒中的下一帧;} var showFXName = 0; var cursor =default; var overUI = false; var sliderAlpha = 1; var listAlpha = 1; var dragging = false; var listWidth = null; function getMaxListWidth(){ctx.font =12px arial; FXList.forEach(text => {listWidth = Math.max(listWidth,ctx.measureText(text).width)})} function drawList(){if(listWidth === null){getMaxListWidth(); listWidth + = 10; } if(!overUI&& mouse.over&& mouse.x> canvas.width  -  listWidth){listAlpha = 1; overUI = true; } else {listAlpha = Math.max(0,listAlpha  -  0.05); } if(listAlpha> 0){ctx.font =12px arial; var textH = 14; var border = 10; ctx.textAlign =right; ctx.textBaseline =middle; ctx.globalAlpha = listAlpha; ctx.fillStyle =black; ctx.strokeStyle =white; var len = FXList.length; var h = len * textH; var y = canvas.height / 2  -  h / 2; var x = canvas.width  -  border * 2; ctx.fillRect(x  -  listWidth,y  -  border,listWidth + border,h + border); ctx.strokeRect(x  -  listWidth,y  -  border,listWidth + border,h + border); ctx.fillStyle =whitefor(var i = 0; i< len; i ++){var yy = y + i * textH; if(FXList [i] === currentFX){ctx.fillStyle =#0FF; ctx.fillText(FXList [I]中,x,日); ctx.fillStyle =white}否则if(mouse.x> canvas.width  -  listWidth&& mouse.y> yy  -  textH / 2&& mouse.y< yy + textH / 2) {ctx.fillStyle =#0F0; ctx.fillText(FXList [I]中,x,日); ctx.fillStyle =whitecursor =pointer; ((mouse.button& 1)=== 1){currentFX = FXList [i]; showFXName = 4; } else {ctx.fillText(FXList [i],x,yy); }} ctx.globalAlpha = 1; }} function drawSlider(){if(currentFX ===None){sliderAlpha = 0;返回; } var cw = canvas.width; var ch = canvas.height; var handle = 5; var inset = 10 var x = inset; var w = cw  -  inset * 2; var h = 20; var y = ch  -  inset  -  h; var pos = FXMix * w + x ;; if(mouse.y> y  -  h * 2){cursor =e-resize; overUI = true; ((mouse.button& 1)&&!dragging){//位域拖动=真; }} else {cursor =pointer; } if(draging){overUI = true; cursor =e-resize; sliderAlpha = 1; pos = mouse.x  -  x; FXMix = Math.min(1,Math.max(0,pos / w)); if((mouse.button& 1)=== 0){//位域拖动= false; }} else {} if(!drag&& mouse.y> y-h * 2&& mouse.over){sliderAlpha = 1; } else {if(sliderAlpha> 0){sliderAlpha = Math.max(0,sliderAlpha- 0.05); if(sliderAlpha === 0){return;} } ctx.globalAlpha = sliderAlpha; ctx.font =18px arial; ctx.textAlign =center; ctx.textBaseline =middle; var amount = FXMix; ctx.fillStyle =black; ctx.strokeStyle =white; ctx.fillRect(X,Y,W,H); ctx.strokeRect(X,Y,W,H); ctx.fillStyle =white; ctx.fillText(currentFX ++(FXMix * 100).toFixed(0)+%,w / 2,y + h / 2); pos = amount * w + x; ctx.fillStyle =white; ctx.strokeStyle =黑色; ctx.fillRect(pos-handle * 2,y-handle,handle * 4,h + handle * 2); ctx.strokeRect(pos-handle * 2,y-handle,handle * 4,h + handle * 2); ctx.strokeRect(pos-1,y-handle * 0.5,2,h + handle); ctx.globalAlpha = 1; } function drawPayIcon(){// ctx.fillStyle =black; //变暗显示// ctx.globalAlpha = 0.5; // ctx.fillRect(0,0,canvas.width,canvas.height); ctx.fillStyle =#DDD; //播放图标的颜色ctx.globalAlpha = 0.75; //部分透明ctx.beginPath(); //为图标创建路径var size =(canvas.height / 2)* 0.5; //图标的大小ctx.moveTo(canvas.width / 2 + size / 2,canvas.height / 2); //从尖端开始ctx.lineTo(canvas.width / 2  -  size / 2,canvas.height / 2 + size); ctx.lineTo(canvas.width / 2  -  size / 2,canvas.height / 2  -  size); ctx.closePath(); ctx.fill(); ctx.globalAlpha = 1; //恢复alpha} mouse =(function(){var mouse = {x:0,y:0,w:0,button:0,over:false,bm:[1,2,4,6,5,3 ],active:false,bounds:null,border:{top:10,left:10},mouseEvents:mousemove,mousedown,mouseup,mouseout,mouseover,contextmenu.split(,)}; var m = mouse ; function mouseMove(e){var t = e.type; m.bounds = m.element.getBoundingClientRect(); mx = e.clientX  -  m.bounds.left  -  m.border.left; my = e.clientY  - m.bounds.top  -  m.border.top; if(t ===mousedown){m.button | = m.bm [e.which-1];} else if(t ===mouseup ){m.button& = m.bm [e.which + 2];}否则if(t ===mouseout){m.button = 0; m.over = false;} else if(t = ==mouseover){m.over = true;} e.preventDefault();} m.start = function(element){m.element = elem耳鼻喉科; (m =鼠标移动);}); m.active = true; //m.border.top = Number(element.style.borderTopWidth.replace(/ [a-zA-Z] / g,)); //m.border.left = Number(element.style.borderLeftWidth.replace(/ [a-zA-Z] / g,)); } m.remove = function(){if(m.element!== undefined){m.mouseEvents.forEach(n => {m.element.removeEventListener(n,mouseMove);}); m.active = false; m.element =未定义; ();}} return mouse;})(); function playPauseClick(){if(videoContainer!== undefined&& videoContainer.ready){if(videoContainer.video.paused){videoContainer.video.play(); } else {videoContainer.video.pause();函数videoMute(){muted =!muted; if(muted){document.querySelector(。mute)。textContent =Mute; } else {document.querySelector(。mute)。textContent =Sound on; }} //注册事件// canvas.addEventListener(click,playPauseClick); document.querySelector(。mute)。addEventListener(click,videoMute)setTimeout(()=> {mouse.start( canvas)},100);  

  body {font:14px宋体; text-align:center;背景:#36A;} h2 {color:white;} canvas {border:10px white solid; cursor:pointer;} a {color:#F93;}。mute {cursor:pointer;显示:初始; }  

< h2>简单的视频效果通过画布globalCompositeOperation < / h2>< p>此示例显示如何使用2d上下文globalCompositeOperation属性来创建各种FX。视频可能需要一些时间才能加载。< / p>< p>通过点击播放暂停视频。移至视频底部以查看效果器混合滑块(如果过滤器无则不可用)。向右移动以获取过滤器选择并选择过滤器示例。快乐过滤< / p>< canvas id =myCanvaswidth =532height =300>< / canvas>< br>< h3>< div id =playPause>正在加载content。< / div>< / h3>< div class =mute>< / div>< br>


I have 2 elements - video and canvas. On video play event, a functions draws the same video on canvas only greyscale. Then I have a button which is supposed to fade canvas video from greyscale back to color. So far I've managed to get back colors on button click, but I need it to fade - from greyscale to color, not just instantly show color.

Any ideas on how could I accomplish that? Or.. is it even possible?

Here's the code:

function grey() {
    if (!stop) {
    bgContext.drawImage(video, 0, 0, w, h);
    var pixelData = bgContext.getImageData(0, 0, w, h);
    for (var i = 0; i < pixelData.data.length; i += 4 ) {
        var r = pixelData.data[i];
        var g = pixelData.data[i+1];
        var b = pixelData.data[i+2];
        var averageColour = (r + g + b) / 3;
        pixelData.data[i] = averageColour;
        pixelData.data[i+1] = averageColour;
        pixelData.data[i+2] = averageColour;
    }
    context.putImageData(pixelData, 0, 0);
    }
}

function color() {
    bgContext.drawImage(video, 0, 0, w, h);
    var pixelData = bgContext.getImageData(0, 0, w, h);
    for (var i = 0; i < pixelData.data.length; i += 4 ) {
        var r = pixelData.data[i];
        var g = pixelData.data[i+1];
        var b = pixelData.data[i+2];
        pixelData.data[i] = r;
        pixelData.data[i+1] = g;
        pixelData.data[i+2] = b;
    }
    context.putImageData(pixelData, 0, 0);
}

video.addEventListener('play', function() {
    setInterval("grey()", 0);
}, false);

button.addEventListener('click', function() {
    stop = true;
    setInterval("color()", 0);
}, false);

解决方案

Canvas Filters for real-time Video/Animation.

Black & White filter

To do a black and white filter is easy.

 // mixAmount is a value from 0 - 1 0 = no mix 1 = full FX
 // video is the video
 ctx.drawImage(video,0,0); // draw the video
 // set up filter
 ctx.fillStyle = "#888"; // gray colour
 ctx.globalAlpha = mixAmount;   // amount of FX
 ctx.globalCompositeOperation = "color";  // The comp setting to do BLACK/WHITE
 ctx.fillRect(0,0,video.width,video.height);  // Draw gray over the video
 ctx.globalAlpha = 1;  // reset alpha
 ctx.globalCompositeOperation = "source-over";  // reset comp

Or you can render the video over itself to get other FX, the demo shows the Black and White filter and several more by just using the above code and a few extra layers.

More info

For more on displaying a video see Display video inside canvas


Demo

The demo show how to do Black and white and some other FX while I am at it.

How to use.

See video title for attribution. FX on left from top to bottom "Lighten", "Black & white", "Sepia", "Saturate", and "Negative".

The Demo has the following FX Lighter, Darken, Black/White, Negative, Saturate, Sepia, B&W negative, and more.

The Javascript

The code relating to the question is all at the top and marked. The rest is UI loading etc..

Each FX is a function that will call either addMix or addOverlay to apply the filter as shown in the snippet above. The addMix function is slightly different as it draws the video over the video to get the FX rather than a fill.

Instructions are on the demo.

Please note not all browser support all comp modes (WHY?? who knows!! :( ) Nor is there a way to be 100% sure if a browser supports a mode or not. The safe bet is Firefox, Chrome, and Edge for all other browsers best of luck..

//==========================================================================
// All the mix function are in this section
var FXMix = 1;
var addOverlay = function(type){
    if(FXMix > 0){
        ctx.globalCompositeOperation = type; 
        ctx.globalAlpha = FXMix;
        ctx.fillRect(0, 0, canvas.width, canvas.height);
        ctx.globalAlpha = 1;
        ctx.globalCompositeOperation = "source-over"; 
    }
}
var addMix = function(type,video){
    if(FXMix > 0){
        ctx.globalCompositeOperation = type; 
        ctx.globalAlpha = FXMix;
        ctx.drawImage(video,0, 0, canvas.width, canvas.height);
        ctx.globalAlpha = 1;
        ctx.globalCompositeOperation = "source-over"; 
    }
}
var fill = function(style){
    ctx.globalAlpha = FXMix;
    ctx.fillStyle = style;
    ctx.fillRect(0, 0, canvas.width, canvas.height);
    ctx.globalAlpha = 1;
}
var FX = {
}
var FXList = [];
var currentFX = "";
var addFX = function(name,func){
    FXList.push(name);
    FX[name] = func;
    currentFX = name;
}
// multiply,screen,overlay,color-dodge,color-burn,hard-light,soft-light,difference,exclusion,hue,saturation,color,luminosity
addFX("Ligher",(vid)=>{ addMix("lighter",vid);} );
addFX("BlackWhite",(vid)=>{ ctx.fillStyle = "#888"; addOverlay("color");} );
addFX("Negative",(vid)=>{ ctx.fillStyle = "#FFF"; addOverlay("difference");} );
addFX("Sepia",(vid)=>{ fill("#F94"); addMix("luminosity",vid); ;} );
addFX("B&W Negative",(vid)=>{ ctx.fillStyle = "#FFF";   addOverlay("difference");ctx.fillStyle = "#888"; addOverlay("color");} );
addFX("Ligher+",(vid)=>{   addMix("lighter",vid);addMix("lighter",vid);addMix("lighter",vid);} );
addFX("B&W Lighten",(vid)=>{  addMix("lighter",vid);ctx.fillStyle = "#888"; addOverlay("color");} );
addFX("Darken+",(vid)=>{  addMix("multiply",vid);addMix("multiply",vid);addMix("multiply",vid);} );

addFX("Darken",(vid)=>{  addMix("multiply",vid);} );
addFX("Saturate",()=>{ ctx.fillStyle = "#F00";addOverlay("saturation");});
addFX("None",()=>{});



// end of FX mixing
//==========================================================================

var mediaSource = "http://video.webmfiles.org/big-buck-bunny_trailer.webm";
var mediaSource = "http://upload.wikimedia.org/wikipedia/commons/7/79/Big_Buck_Bunny_small.ogv";
var muted = true;
var canvas = document.getElementById("myCanvas"); // get the canvas from the page
var ctx = canvas.getContext("2d");
var videoContainer; // object to hold video and associated info
var video = document.createElement("video"); // create a video element
video.src = mediaSource;
// the video will now begin to load.
// As some additional info is needed we will place the video in a
// containing object for convenience
video.autoPlay = false; // ensure that the video does not auto play
video.loop = true; // set the video to loop.
video.muted = muted;
videoContainer = {  // we will add properties as needed
     video : video,
     ready : false,   
};
// To handle errors. This is not part of the example at the moment. Just fixing for Edge that did not like the ogv format video
video.onerror = function(e){
    document.body.removeChild(canvas);
    document.body.innerHTML += "<h2>There is a problem loading the video</h2><br>";
    document.body.innerHTML += "Users of IE9+ , the browser does not support WebM videos used by this demo";
    document.body.innerHTML += "<br><a href='https://tools.google.com/dlpage/webmmf/'> Download IE9+ WebM support</a> from tools.google.com<br> this includes Edge and Windows 10";
    
 }
video.oncanplay = readyToPlayVideo; // set the event to the play function that 
                                  // can be found below
function readyToPlayVideo(event){ // this is a referance to the video
    // the video may not match the canvas size so find a scale to fit
    videoContainer.scale = Math.min(
                         canvas.width / this.videoWidth, 
                         canvas.height / this.videoHeight); 
    videoContainer.ready = true;
    // the video can be played so hand it off to the display function
    requestAnimationFrame(updateCanvas);
    // add instruction
    document.getElementById("playPause").textContent = "Click video to play/pause.";
    document.querySelector(".mute").textContent = "Mute";
}
var playClick = false;
function updateCanvas(){
    ctx.clearRect(0,0,canvas.width,canvas.height); 
    // only draw if loaded and ready
    if(videoContainer !== undefined && videoContainer.ready){ 
        // find the top left of the video on the canvas
        video.muted = muted;
        var scale = videoContainer.scale;
        var vidH = videoContainer.video.videoHeight;
        var vidW = videoContainer.video.videoWidth;
        var top = canvas.height / 2 - (vidH /2 ) * scale;
        var left = canvas.width / 2 - (vidW /2 ) * scale;
        // now just draw the video the correct size
        ctx.drawImage(videoContainer.video, left, top, vidW * scale, vidH * scale);
        FX[currentFX](videoContainer.video);
        if(videoContainer.video.paused){ // if not playing show the paused screen 
            drawPayIcon();
        }
        overUI = false;
        cursor = "default";
        drawSlider();
        drawList();
        if(mouse.over){
            if(!overUI){
                if((mouse.button&1)===1){ // bit field
                    playClick = true;
                }
                if((mouse.button&1)===0 && playClick){ // bit field
                    playClick = false;
                    playPauseClick();
                }
                cursor = "pointer";
            }
        }
        if(showFXName > 0){
            showFXName = Math.max(0,showFXName - 0.05);
            ctx.globalAlpha = Math.min(1,showFXName);
            ctx.font = "32px Arial";
            ctx.textAlign = "center";
            ctx.textbaseLine = "middle";
            ctx.fillStyle = "white";
            ctx.strokeStyle = "black";
            ctx.lineJoin = "round"
            ctx.strokeText(currentFX,canvas.width/2,canvas.height/2);
            ctx.fillText(currentFX,canvas.width/2,canvas.height/2);
            ctx.globalAlpha = 1;
        }
        
        canvas.style.cursor = cursor;
    }
    // all done for display 
    // request the next frame in 1/60th of a second
    requestAnimationFrame(updateCanvas);
}
var showFXName = 0;
var cursor = "default";
var overUI = false;
var sliderAlpha = 1;
var listAlpha = 1;
var dragging = false;
var listWidth = null;
function getMaxListWidth(){
    ctx.font = "12px arial";
    FXList.forEach(text => {listWidth = Math.max(listWidth,ctx.measureText(text).width)})
    
}

function drawList(){
    if(listWidth === null){
        getMaxListWidth();
        listWidth += 10;
    }

    if(!overUI && mouse.over && mouse.x > canvas.width - listWidth){
        listAlpha = 1;
        overUI = true;
        
    }else{
        listAlpha = Math.max(0,listAlpha - 0.05);
    }
    if(listAlpha > 0){
        ctx.font = "12px arial";
        var textH = 14;
        var border = 10;
        ctx.textAlign = "right";
        ctx.textBaseline = "middle";
        ctx.globalAlpha = listAlpha;
         ctx.fillStyle = "black";
         ctx.strokeStyle = "white";        
        var len = FXList.length;
        var h = len * textH;
        var y = canvas.height / 2 - h/2;
        var x = canvas.width - border * 2;
        ctx.fillRect(x - listWidth,y - border, listWidth+border,h + border );
        ctx.strokeRect(x - listWidth,y - border, listWidth + border,h + border );
        ctx.fillStyle = "white"
        for(var i = 0; i < len; i ++){
            var yy = y + i * textH;
            if(FXList[i] === currentFX){
                ctx.fillStyle = "#0FF";
                ctx.fillText(FXList[i],x,yy);
                ctx.fillStyle = "white"
            }else
            if(mouse.x > canvas.width - listWidth && mouse.y > yy - textH/2 && mouse.y < yy + textH /2){
                ctx.fillStyle = "#0F0";
                ctx.fillText(FXList[i],x,yy);
                ctx.fillStyle = "white"
                cursor = "pointer";
                if((mouse.button & 1) === 1){
                    currentFX =FXList[i];
                    showFXName = 4;
                }
            }else{
                ctx.fillText(FXList[i],x,yy);
            }
            
            
        }
        ctx.globalAlpha = 1;

        
        
    }
    
    
}

function drawSlider(){
    if(currentFX === "None"){
        sliderAlpha = 0;
        return;
    }

    var cw = canvas.width;
    var ch = canvas.height;
    var handle = 5;
    var inset = 10
    var x = inset;
    var w = cw - inset*2;
    var h = 20;
    var y = ch - inset - h;
    var pos =  FXMix * w + x;;
    if(mouse.y > y - h* 2){
        cursor = "e-resize";
        overUI = true;
        if((mouse.button&1) && !dragging){  // bit field
            dragging = true;
        }
    }else{
        cursor = "pointer";

    }
    if(dragging){
        overUI = true;
        cursor = "e-resize";
        sliderAlpha = 1;
        pos = mouse.x - x;
        FXMix = Math.min(1,Math.max(0,pos / w));
        if( (mouse.button&1) === 0 ){ //bit field
            dragging = false;

        }
    }else{
        
    }
    if(!dragging && mouse.y > y-h*2 && mouse.over){
        sliderAlpha = 1;
    }else{
        if(sliderAlpha > 0){
            sliderAlpha = Math.max(0,sliderAlpha- 0.05);
        }
    }
    if(sliderAlpha === 0){
        return;
    }
    ctx.globalAlpha =  sliderAlpha;
    ctx.font = "18px arial";
    ctx.textAlign = "center";
    ctx.textBaseline = "middle";
    var amount = FXMix;
    ctx.fillStyle = "black";
    ctx.strokeStyle = "white";
    ctx.fillRect(x,y,w,h);
    ctx.strokeRect(x,y,w,h);
    ctx.fillStyle = "white";
    ctx.fillText(currentFX + " "+ (FXMix * 100).toFixed(0)+"%",w/2,y + h / 2);
    pos = amount * w + x;
    ctx.fillStyle = "white";
    ctx.strokeStyle = "black";
    ctx.fillRect(pos-handle*2,y-handle,handle* 4,h + handle * 2);
    ctx.strokeRect(pos-handle*2,y-handle,handle* 4,h + handle * 2);
    ctx.strokeRect(pos-1,y-handle * 0.5,2,h + handle);
    ctx.globalAlpha =  1;
    
    
    
}
function drawPayIcon(){
    // ctx.fillStyle = "black";  // darken display
    // ctx.globalAlpha = 0.5;
    // ctx.fillRect(0,0,canvas.width,canvas.height);
     ctx.fillStyle = "#DDD"; // colour of play icon
     ctx.globalAlpha = 0.75; // partly transparent
     ctx.beginPath(); // create the path for the icon
     var size = (canvas.height / 2) * 0.5;  // the size of the icon
     ctx.moveTo(canvas.width/2 + size/2, canvas.height / 2); // start at the pointy end
     ctx.lineTo(canvas.width/2 - size/2, canvas.height / 2 + size);
     ctx.lineTo(canvas.width/2 - size/2, canvas.height / 2 - size);
     ctx.closePath();
     ctx.fill();
     ctx.globalAlpha = 1; // restore alpha
}    


mouse = (function(){
    var mouse = {
        x : 0, y : 0, w : 0, 
        button : 0,
        over : false,
        bm : [1, 2, 4, 6, 5, 3], 
        active : false,
        bounds : null, 
        border : {top : 10, left : 10},
        mouseEvents : "mousemove,mousedown,mouseup,mouseout,mouseover,contextmenu".split(",")
    };
    var m = mouse;
    function mouseMove(e) {
        var t = e.type;
        m.bounds = m.element.getBoundingClientRect();
        m.x = e.clientX - m.bounds.left - m.border.left; 
        m.y = e.clientY - m.bounds.top - m.border.top;
        
        if (t === "mousedown") { 
            m.button |= m.bm[e.which-1]; 
        } else if (t === "mouseup") { 
            m.button &= m.bm[e.which + 2]; 
        }else if (t === "mouseout") { 
            m.button = 0; 
            m.over = false; 
        }else if (t === "mouseover") { 
            m.over = true; 
        }
        e.preventDefault();
    }
    m.start = function (element) {
        m.element = element;
        m.mouseEvents.forEach( n => { m.element.addEventListener(n, mouseMove); } );
        m.active = true;
        //m.border.top = Number(element.style.borderTopWidth.replace(/[a-zA-Z]/g,""));
        //m.border.left = Number(element.style.borderLeftWidth.replace(/[a-zA-Z]/g,""));
    }
    m.remove = function () {
        if (m.element !== undefined) {
            m.mouseEvents.forEach(n => { m.element.removeEventListener(n, mouseMove); } );
            m.active = false;
            m.element = undefined;
        }
    }
    return mouse;
})();




function playPauseClick(){
     if(videoContainer !== undefined && videoContainer.ready){
          if(videoContainer.video.paused){                                 
                videoContainer.video.play();
          }else{
                videoContainer.video.pause();
          }
     }
}
function videoMute(){
    muted = !muted;
	if(muted){
         document.querySelector(".mute").textContent = "Mute";
    }else{
         document.querySelector(".mute").textContent= "Sound on";
    }


}
// register the event
//canvas.addEventListener("click",playPauseClick);
document.querySelector(".mute").addEventListener("click",videoMute)
setTimeout(()=>{mouse.start(canvas)},100);

body {
    font :14px  arial;
    text-align : center;
    background : #36A;
}
h2 {
    color : white;
}
canvas {
    border : 10px white solid;
    cursor : pointer;
}
a {
  color : #F93;
}
.mute {
    cursor : pointer;
    display: initial;   
}

<h2>Simple video FX via canvas "globalCompositeOperation"</h2>
<p>This example show how to use the 2d context "globalCompositeOperation" property to create a variety of FX. Video may take a few moment to load.
</p>
<p>Play pause video with click. Move to bottom of video to see FX mix slider (Not available if filter None). Move to right to get filter selection and select the filter example. Happy filtering</p>
<canvas id="myCanvas" width = "532" height ="300" ></canvas><br>
<h3><div id = "playPause">Loading content.</div></h3>
<div class="mute"></div><br>

这篇关于淡入淡出从灰度到彩色的画布视频的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆