0

I want to fadeOut the Tv Noise after some timeOut with smoother transition. Can it be possible to fadeOut the noise. The code I am posting is already present on stakcoverflow https://stackoverflow.com/a/22085531/7935298

var canvas = document.getElementById('canvas'),
      ctx = canvas.getContext('2d');

  // closer to analouge appearance
  canvas.width = canvas.height = 256;

  function resize() {
      canvas.style.width = window.innerWidth + 'px';
      canvas.style.height = window.innerHeight + 'px';
  }
  resize();
  window.onresize = resize;

  function noise(ctx) {

      var w = ctx.canvas.width,
          h = ctx.canvas.height,
          idata = ctx.createImageData(w, h),
          buffer32 = new Uint32Array(idata.data.buffer),
          len = buffer32.length,
          run = 0,
          color = 10,
          m = Math.random() * 6 + 4,
          band = Math.random() * 256 * 256,
          p = 0,
          i = 0;

      for (; i < len;) {
          if (run < 0) {
              run = m * Math.random();
              p = Math.pow(Math.random(), 0.1);
              if (i > band && i < band + 48 * 256) {
                  p = Math.random();
              }
              color = (255 * p) << 25;
          }
          run -= 1;
          buffer32[i++] = color;
      }

      ctx.putImageData(idata, 0, 0);
  }

  var frame = 0;

  // added toggle to get 30 FPS instead of 60 FPS
  (function loop() {
      frame += 1;
      if (frame % 3) {
          requestAnimationFrame(loop);
          return;
      }
      noise(ctx);
      requestAnimationFrame(loop);
  })();
<canvas id="canvas"></canvas>
Community
  • 1
  • 1

1 Answers1

0

Adding noise to a video.

Yes it is possible to fade out some noise.

Use ctx.globalAlpha to mix in the noise. As noise effects the frame content you should do the noise as a double pass. Once using ctx.globalCompositeOperation="multiply", that adds noise to the existing pixels and once using ctx.globalCompositeOperation="source-over" that desaturates the noise. For a good high speed noise FX I pre calculate the noise with a little chroma noise then cut random parts from the noise array to fill the pixel data array. As the old fashioned noise is usually a little drawn out along the x direction (and to reduce CPU load) I create the noise at 1/3rd the resolution of the canvas and stretch the noise to fit. This give a much better feel to the noise FX.

The noise function

The following will add noise to a canvas (assuming that video is already rendered onto the canvas. The first argument is the amount of noise you want. With 0 no noise and 1 full noise.

    // following variable are set when noise function first called.
    var canvasNoise; // canvas to hold the noise
    var ctxNoise;    // context of above canvas
    var rawPixels;   // pixel image data
    var rawPixel32Arr;  // pixel image data as 32bit array
    var randomPix;    // array of precalculated noise.

   // FXMix the amount of noise to add 0 no noise 1 full noise
   function noise(FXMix) {
        var i,d;
        // if noise canvas not created create it now
        if(canvasNoise === undefined){
            canvasNoise = document.createElement("canvas");
            canvasNoise.width = Math.floor(canvas.width / 3);
            canvasNoise.height = canvas.height;
            ctxNoise = canvasNoise.getContext("2d");
            rawPixels = ctxNoise.createImageData(canvasNoise.width, canvasNoise.height);
            rawPixel32Arr = new Uint32Array(rawPixels.data.buffer);
            // create array of random noise
            randomPix = new Uint32Array(canvasNoise.width * 10);
            i = canvasNoise.width * 10;
            d = randomPix; // alias to make code readable
            while(i--){
                var r = Math.floor(Math.random() * 255);
                // create slight croma noise
                var g = Math.min(255, Math.max(0,Math.floor(r + (Math.random()-0.5) * 32)));
                var b = Math.min(255, Math.max(0,Math.floor(r + (Math.random()-0.5) * 32)));

                d[i] = 0xFF000000 + (r<<16) + (g<<8) + b;
            }
        }
        // fill the pixel data with random noise from the randomPix array
        i = rawPixel32Arr.length;
        d = rawPixel32Arr; // alias to make code readable
        while(i){
            var len = Math.floor(Math.random() * 100) + 20;
            var start = Math.floor(Math.random() * randomPix.length - len);
            i -= len;
            i = i < 0 ? 0 : i;
            d.set(randomPix.subarray(start,start + len), i);
        }
        // put noise onto canvas
        ctxNoise.putImageData(rawPixels, 0, 0);

        // now mix noise over video 
        ctx.globalAlpha = FXMix;
        ctx.globalCompositeOperation = "multiply"; 
        ctx.drawImage(canvasNoise,0,0,canvas.width,canvas.height)
        ctx.globalCompositeOperation = "source-over"; 
        ctx.drawImage(canvasNoise,0,0,canvas.width,canvas.height)
        ctx.globalAlpha = 1;
    }

Demo.

The following demo is an update on an existing demo I used in the answer to Fade from black & white to color I have added the noise FX to the FX list you can find if you hover the mouse over the right of the video (once loaded) The noise is controlled by the mix slider you can find if you hover over the bottom of the video.

The FX are just slight modification of the above snippet function noise.

Update I have added a second noise that uses a 3rd layer (draws noise canvas with ctx.globalCompositeOperation = "lighter" to keep the total luminance level consistent by adding what multiply operation removes. See noise function for more info. And fixed filter select bug because FX list was too long and FX mix slider was getting in the way of bottom filter.

Video attribution can be found in the opening and closing title/credits of the video ( as specified by author/s)

    //==========================================================================
    // 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 noise variables. Created when filter first used.
    var canvasNoise;
    var ctxNoise;
    var rawPixels;
    var rawPixel32Arr;
    
    //==========================================================================
    // 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 noise(type) {
        var i,d;
        if(canvasNoise === undefined){
            canvasNoise = document.createElement("canvas");
            canvasNoise.width = Math.floor(canvas.width / 3);
            canvasNoise.height = canvas.height;
            ctxNoise = canvasNoise.getContext("2d");
            rawPixels = ctxNoise.createImageData(canvasNoise.width, canvasNoise.height);
            rawPixel32Arr = new Uint32Array(rawPixels.data.buffer);
            randomPix = new Uint32Array(canvasNoise.width * 10);
            i = canvasNoise.width * 10;
            d = randomPix; // alias to make code readable
            while(i--){
                var r = Math.floor(Math.random() * 255);
                // create slight croma noise
                var g = Math.min(255, Math.max(0,Math.floor(r + (Math.random()-0.5) * 32)));
                var b = Math.min(255, Math.max(0,Math.floor(r + (Math.random()-0.5) * 32)));

                d[i] = 0xFF000000 + (r<<16) + (g<<8) + b;
            }
        }
        i = rawPixel32Arr.length;
        d = rawPixel32Arr; // alias to make code readable
        while(i){
            var len = Math.floor(Math.random() * 100) + 20;
            var start = Math.floor(Math.random() * randomPix.length - len);
            i -= len;
            i = i < 0 ? 0 : i;
            d.set(randomPix.subarray(start,start + len), i);
        }

        ctxNoise.putImageData(rawPixels, 0, 0);
    if(type === "Addative"){
        ctx.globalAlpha = FXMix;
        ctx.globalCompositeOperation = "multiply"; 
        ctx.drawImage(canvasNoise,0,0,canvas.width,canvas.height)
        ctx.globalCompositeOperation = "lighter"; 
        ctx.drawImage(canvasNoise,0,0,canvas.width,canvas.height)
        ctx.globalCompositeOperation = "source-over"; 
        ctx.drawImage(canvasNoise,0,0,canvas.width,canvas.height)
        ctx.globalAlpha = 1;
        
        
    }else{
        ctx.globalAlpha = FXMix;
        ctx.globalCompositeOperation = "multiply"; 
        ctx.drawImage(canvasNoise,0,0,canvas.width,canvas.height)
        ctx.globalCompositeOperation = "source-over"; 
        ctx.drawImage(canvasNoise,0,0,canvas.width,canvas.height)
        ctx.globalAlpha = 1;
    }
    }
    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("Noise",       (vid)=>{ noise() })
    addFX("Noise 2",       (vid)=>{ noise("Addative") })
    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* 1.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. 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>
Graham
  • 7,431
  • 18
  • 59
  • 84
Blindman67
  • 51,134
  • 11
  • 73
  • 136