【问题标题】:How to animate scanner effect line with canvas如何使用画布为扫描仪效果线设置动画
【发布时间】:2017-04-28 07:05:16
【问题描述】:

是否可以使用 html5 画布制作扫描仪效果动画,上下移动发光线?

Effect example.

我想在我的 html5 视频窗口上使用这个效果。如果可能的话,您能否分享代码示例或我必须开始的地方?

【问题讨论】:

  • 只移动一行还是行移动时必须出现内容?
  • 移动线

标签: javascript html canvas html5-canvas html5-video


【解决方案1】:

是的,这是可能的。以下是您实现这一目标的方法...

var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
var x = 4,
    y = 4,
    speed = 1,
    isBottom = false;

function draw() {
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    ctx.fillStyle = '#07C';
    ctx.lineCap = 'round';
    ctx.shadowBlur = 18;
    ctx.shadowColor = "#07C";
    ctx.fillRect(x, y, 210, 10);
	
    if (!isBottom && y < canvas.height - 14) y += speed;
    else if (y === canvas.height - 14) isBottom = true;
	
    if (isBottom && y > 4) y -= speed;
    else if (y === 4) isBottom = false;
	
    requestAnimationFrame(draw);
}

draw();
body{margin:0;overflow:hidden}canvas{border:1px solid #d3d3d3}
&lt;canvas id="canvas" width="218" height="218"&gt;&lt;/canvas&gt;

【讨论】:

  • 非常感谢您提供了清晰而简单的代码并获得了出色的结果。另一个问题是,当我将这种效果与网络摄像头流一起使用时,每一帧的速度都会增加到无限速度。有没有限速的方法?
  • @Streem 你的意思是,酒吧移动得太快了?如果是这样,您可以通过使用浮点数来降低速度,例如0.5 左右..
  • 感谢您的帮助,我很感激。我不知道为什么,但是当我在视频上使用这个漂亮的效果时,每个帧条的移动速度都在增加,我的意思是它开始缓慢,10 秒后它移动得如此之快,就像疯了一样:)) 我会尝试上传我的今晚给 jsfiddle 写代码,看看我的意思:)
  • 是的,这样会更好。 上传到 jsfiddle
  • @ɢʀᴜɴᴛ 我们如何控制该条应移动的高度和深度。就像我不希望这个酒吧一直走到顶部,也不想到底部,而是在两者之间移动一段距离。请你帮忙。
【解决方案2】:

视频和画布。

使用 HTML5 画布和 2D API 实现以下动画发光交叉淡入淡出到背景 FX

图片出处可以在本答案底部演示中视频的开头和结尾标题/字幕中找到

使用蒙版裁剪。

可以使用蒙版来屏蔽掉您不想看到的视频部分来实现 FX。

ctx.globalCompositeoperation 设置为“destination-out”将删除您渲染的任何现有像素,直到您使用ctx.globalCompositeoperation = "source-over";(默认设置)关闭复合操作您可以使用“destination-in”获得反向效果"

由于您希望在分割时显示背景,您可以使用压缩模式"destination-atop" 在蒙版视频上绘制背景。背景可以是空白黑色(在下面的代码中)或其他视频源,以创建一种交叉淡入淡出 FX。

注意如果您让背景保持透明,那么发光条将无法在画布背景(DOM 背景)上正确执行较亮的 FX

注意两个代码 sn-ps 都假定视频已经渲染到画布上。

// direction is the direction of the sweeping FX
// FXMix is the position of the mask normalised for canvas width or height
//       FXMix has a range of 0-1 inclusive with 0 being top or left and
//       1 being bottom or right.
// negate if true reverses the FX mask.
// Assuming that canvas and ctx (2D context) are in scope of this function
function mask(direction, FXMix, negate){
    ctx.globalCompositeOperation = negate ? "destination-out" : "destination-in"; 
    ctx.fillStyle = "black";
    ctx.globalAlpha = 1;
    if(direction === "Vertical"){
        ctx.fillRect(0, 0, canvas.width, canvas.height * FXMix);
    }else if(direction === "Horizontal"){
        ctx.fillRect(0, 0, canvas.width  * FXMix, canvas.height);
    }
    ctx.globalCompositeOperation = "destination-atop"; 
    // assuming background is black. But you could use anything including a second video
    // using "destination-atop" only draws on transparent pixels.
    ctx.fillRect(0, 0, canvas.width, canvas.height);
    ctx.globalCompositeOperation = "source-over"; 
}

简单的发光条。

然后可以使用渐变和填充矩形在顶部绘制扫描光 FX。为了让发光体更加丰满,我画了两次,一次没有任何合成效果,第二次使用ctx.globalCompositeOperation = "lighter" 稍大一点。我不必移动渐变,而是使用 setTransform 来定位渐变。如果您不想更改发光条颜色,则只需创建渐变即可节省一点 CPU 时间。

// RGB is an array of channel values for R,G,B in the range 0-255
//     NOTE RGB must be integer values. Please floor them befor passing
// direction is the direction of the sweeping FX
// FXMix is the position of the mask normalised for canvas width or height
//       FXMix has a range of 0-1 inclusive with 0 being top or left and
//       1 being bottom or right.
// negate if true reverses the FX mask.
// Assuming that canvas and ctx (2D context) are in scope of this function
// size is size of bar as a fraction pf canvas width or height. 
//     A good value is 0.1
function glowBar(RGB, direction, FXMix, size){ 
    var grad;
    var col = "rgba("+RGB[0]+","+RGB[1]+","+RGB[2]+",";
    if(direction === "Vertical"){
        grad = ctx.createLinearGradient(0,0,0,canvas.height * size);
    }else if(direction === "Horizontal"){
        grad = ctx.createLinearGradient(0,0,canvas.width * size,0);
    }
    grad.addColorStop(0.0, col + "0.0)");
    grad.addColorStop(0.3, col + "0.8)");
    grad.addColorStop(0.4, col + "1.0)");
    grad.addColorStop(0.6, col + "1.0)");
    grad.addColorStop(0.7, col + "0.8)");
    grad.addColorStop(1.0, col + "0.0)");
    ctx.fillStyle = grad;
    if(direction === "Vertical"){
        // draw first time with standard comp 
        ctx.setTransform(1,0,0,1,0,canvas.height * FXMix - canvas.height * size * 0.5);
        ctx.fillRect(0, 0, canvas.width, canvas.height * size);
        // draw second time slightly bigger and with lighten to get a glow FX

        ctx.setTransform(1,0,0,1.1,0,canvas.height * FXMix -canvas.height * size * 0.5 * 1.1 );
        ctx.globalCompositeOperation = "lighter"; 
        ctx.fillRect(0, 0, canvas.width, canvas.height *size);
    }else if(direction === "Horizontal"){
        ctx.setTransform(1,0,0,1,canvas.width * FXMix -canvas.width * size * 0.5, 0);
        ctx.fillRect(0, 0, canvas.width * size, canvas.height);
        ctx.setTransform(1.1,0,0,1,canvas.width * FXMix -canvas.width * size * 0.5 * 1.1, 0);
        ctx.globalCompositeOperation = "lighter"; 
        ctx.fillRect(0, 0, canvas.width * size, canvas.height);
    }
    ctx.globalCompositeOperation = "source-over"; 
    ctx.setTransform(1,0,0,1,0,0);
}

演示。

以下演示是对我在回答Fade from black & white to color 时使用的现有演示的更新扫描仪和水平扫描仪将进行动画处理,但可以通过将鼠标悬停在视频底部找到的混合滑块手动控制。

FX只是对上面两个sn-ps函数maskglowBar的轻微修改。

视频署名可以在视频的开头和结尾标题/字幕中找到(由作者指定)

    //==========================================================================
    // start canvas animation after all the code below has been parsed and executed
    setTimeout(()=>requestAnimationFrame(updateCanvas),0);
    //==========================================================================
    // UI variables
    var showFXName = 0;
    var cursor = "default";
    var overUI = false;
    var sliderAlpha = 1;
    var listAlpha = 1;
    var dragging = false;
    var listWidth = null;
    var playClick = false;


    //==========================================================================
    // Media setup
    
    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
    //==========================================================================
    var FXMix = 1;
    var FX = {}
    var FXList = [];
    var currentFX = "";
    var animateFXMix = false; // if true thr FXMix is animated over time. This flag is cleared to false once a frame

    //==========================================================================
    // Mix function are in this section
    function addOverlay(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"; 
        }
    }
    function addMix(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"; 
        }
    }
    function fill(style){  // draws a rectangle over the canvas using style as the colour
        ctx.globalAlpha = FXMix;
        ctx.fillStyle = style;
        ctx.fillRect(0, 0, canvas.width, canvas.height);
        ctx.globalAlpha = 1;
    }
    function mask(direction){
        ctx.globalCompositeOperation = "destination-in"; 
        ctx.fillStyle = "black";
        ctx.globalAlpha = 1;
        if(direction === "Vertical"){
            ctx.fillRect(0, 0, canvas.width, canvas.height * FXMix);
        }else if(direction === "Horizontal"){
            ctx.fillRect(0, 0, canvas.width  * FXMix, canvas.height);
        }
        ctx.globalCompositeOperation = "destination-atop"; 
        // assuming bacground is black. But you could use anything including a second video
        // using "destination-atop" only draws on transparent pixels.
        ctx.fillRect(0, 0, canvas.width, canvas.height);
        ctx.globalCompositeOperation = "source-over"; 
    }
    function glowBar(RGB, direction){ // RGB is array of channel values 0-255
        var grad;
        var col = "rgba("+RGB[0]+","+RGB[1]+","+RGB[2]+",";
        if(direction === "Vertical"){
            grad = ctx.createLinearGradient(0,0,0,canvas.height * 0.1);
        }else if(direction === "Horizontal"){
            grad = ctx.createLinearGradient(0,0,canvas.width * 0.1,0);
        }
        grad.addColorStop(0.0, col + "0.0)");
        grad.addColorStop(0.3, col + "0.8)");
        grad.addColorStop(0.4, col + "1.0)");
        grad.addColorStop(0.6, col + "1.0)");
        grad.addColorStop(0.7, col + "0.8)");
        grad.addColorStop(1.0, col + "0.0)");
        ctx.fillStyle = grad;
        if(direction === "Vertical"){
            ctx.setTransform(1,0,0,1,0,canvas.height * FXMix - canvas.height * 0.05);
            ctx.fillRect(0, 0, canvas.width, canvas.height * 0.1);
            ctx.setTransform(1,0,0,1.1,0,canvas.height * FXMix -canvas.height * 0.05 * 1.1 );
            ctx.globalCompositeOperation = "lighter"; 
            ctx.fillRect(0, 0, canvas.width, canvas.height * 0.1);
        }else if(direction === "Horizontal"){
            ctx.setTransform(1,0,0,1,canvas.width * FXMix -canvas.width * 0.05, 0);
            ctx.fillRect(0, 0, canvas.width * 0.1, canvas.height);
            ctx.setTransform(1.1,0,0,1,canvas.width * FXMix -canvas.width * 0.05 * 1.1, 0);
            ctx.globalCompositeOperation = "lighter"; 
            ctx.fillRect(0, 0, canvas.width * 0.1, canvas.height);
        }
        ctx.globalCompositeOperation = "source-over"; 
        ctx.setTransform(1,0,0,1,0,0);
    }
    function addFX(name, func) {
        FXList.push(name);
        FX[name] = func;
        currentFX = name;
    }

    //==========================================================================
    // avialable composite operations 
    // multiply,screen,overlay,color-dodge,color-burn,hard-light,soft-light,difference,
    // exclusion,hue,saturation,color,luminosity
    addFX("V scanner",   (vid)=>{ animateFXMix = true; mask("Vertical"); glowBar([100,200,255], "Vertical") })
    addFX("H scanner",   (vid)=>{ animateFXMix = true; mask("Horizontal"); glowBar([100,255,200], "Horizontal") })
    addFX("Ligher",      (vid)=>{ addMix("lighter",vid) } );
    addFX("Ligher+",     (vid)=>{ addMix("lighter", vid); addMix("lighter",vid); addMix("lighter", vid) } );
    addFX("Darken",      (vid)=>{ addMix("multiply", vid) } );
    addFX("Darken+",     (vid)=>{ addMix("multiply", vid); addMix("multiply",vid); addMix("multiply", vid) } );
    addFX("Saturate",    ()   =>{ ctx.fillStyle = "#F00"; addOverlay("saturation") });
    addFX("Negative",    (vid)=>{ ctx.fillStyle = "#FFF"; addOverlay("difference") } );
    addFX("Sepia",       (vid)=>{ fill("#F94"); addMix("luminosity", vid) } );
    addFX("BlackWhite",  (vid)=>{ ctx.fillStyle = "#888"; addOverlay("color") } );
    addFX("B&W Negative",(vid)=>{ ctx.fillStyle = "#FFF";   addOverlay("difference"); ctx.fillStyle = "#888"; addOverlay("color") } );
    addFX("B&W Lighten", (vid)=>{ addMix("lighter", vid); ctx.fillStyle = "#888"; addOverlay("color") } );
    addFX("None",        ()   =>{});

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


    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

        // add instruction
        document.getElementById("playPause").textContent = "Click video to play/pause.";
        document.querySelector(".mute").textContent = "Mute";
    }
    function updateCanvas(time){
        ctx.fillStyle = "#222";
        ctx.fillRect(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;
            if(animateFXMix){
                FXMix = Math.sin(time / 400) * 0.5 + 0.5;
                FXMix = FXMix < 0 ? 0 : FXMix > 1 ? 1 : FXMix; // Clamp to 0-1 or may get flicker on some FX
                
                animateFXMix = false;
            }
        }else{
            drawLoadingAnim(time);
        }
        // all done for display 
        // request the next frame in 1/60th of a second
        requestAnimationFrame(updateCanvas);
    }
    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;
        }
        if(dragging){
            animateFXMix = false;  // dont animate if slider being dragged
        }
        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;
            }
        }
        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 = "#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
    }
    function drawLoadingAnim(time){
         ctx.strokeStyle = "#8DF"; // colour of play icon
         ctx.lineCap = "round";
         ctx.globalAlpha = 0.75; // partly transparent
         ctx.lineWidth = 6;
         ctx.beginPath(); // create the path for the icon
         var size = (canvas.height / 2) * 0.5;  // the size of the icon
         ctx.arc(canvas.width / 2 , canvas.height / 2, size, time / 100, time / 100 + 2);
         ctx.stroke();
         ctx.lineWidth = 1;
         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. V and H scanner FX are animated. You can use the slider to move the glowbar position manualy. 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>

【讨论】:

    猜你喜欢
    • 2012-02-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多