Last active
          July 19, 2018 07:46 
        
      - 
      
 - 
        
Save JSoon/4dac8d2d901958eaf902025a1e95c1b7 to your computer and use it in GitHub Desktop.  
    【canvas】电视机无信号噪点动效,利用正弦函数模拟真实噪声影像
  
        
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
  | <!DOCTYPE html> | |
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <meta http-equiv="X-UA-Compatible" content="ie=edge"> | |
| <title>电视机无信号噪点动效,利用正弦函数模拟真实噪声影像</title> | |
| <style> | |
| .tv-box { | |
| position: relative; | |
| width: 600px; | |
| height: 400px; | |
| } | |
| .tv-box canvas { | |
| position: absolute; | |
| top: 0; | |
| right: 0; | |
| bottom: 0; | |
| left: 0; | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <div id="J_TVBox" class="tv-box"></div> | |
| <script> | |
| tvNoiseEffect({ | |
| containerId: 'J_TVBox', | |
| cycleFactor: 50000, | |
| grayscale: 10 | |
| }); | |
| /** | |
| * @description | |
| * 电视机无信号噪点动效,利用正弦函数模拟真实噪声影像 | |
| * @author J.Soon <[email protected]> | |
| * @date 2018-07-17 | |
| * @see {@link https://stackoverflow.com/questions/22003491/animating-canvas-to-look-like-tv-noise/23572465} | |
| * @param {object} opts 配置参数对象 | |
| * @param {string} opts.containerId 播放器容器id | |
| * @param {number} opts.interval 噪声绘制时间频率,单位毫秒 | |
| * @param {number} opts.grayscale 噪声灰度 | |
| * @param {number} opts.opacity 画布像素不透明度 | |
| * @param {number} opts.cycleFactor 周期系数,影响正弦周期大小,该值越小,则正弦周期越小,反之越大 | |
| * @returns {object} 包含销毁画布方法的对象 | |
| */ | |
| function tvNoiseEffect(opts) { | |
| var canvas = null; // 画布 | |
| var context = null; // 画布上下文(这里是2D画布) | |
| var time = 0; // 噪声带生成次数系数(最多不超过噪声画布高度,计算方式为取模) | |
| var intervalId = 0; // 噪声绘制定时器id | |
| var interval = opts.internal || 50; // 噪声绘制时间频率,单位毫秒 | |
| var grayscale = opts.grayscale || 8; // 噪声灰度 | |
| var opacity = opts.opacity || 255; // 画布像素不透明度,默认完全不透明 | |
| var cycleFactor = opts.cycleFactor || 80000; // 周期系数,影响正弦周期大小,该值越小,则正弦周期越小,反之越大 | |
| var containerId = opts.containerId; // 播放器容器id | |
| if (!containerId) { | |
| throw new Error('请指定播放器容器id!'); | |
| } | |
| var makeNoise = function () { | |
| if (!canvas.parentNode) { | |
| return; | |
| } | |
| var canvasWidth = canvas.parentNode.clientWidth; | |
| var canvasHeight = canvas.parentNode.clientHeight; | |
| if (!canvasWidth || !canvasHeight) { | |
| return; | |
| } | |
| canvas.width = canvasWidth; | |
| canvas.height = canvasHeight; | |
| var imgData = context.createImageData(canvasWidth, canvasHeight); | |
| var pix = imgData.data; | |
| // 由下至上渲染噪声带,绘制整幅噪声图像 | |
| for (var i = 0, n = pix.length; i < n; i += 4) { | |
| var c = 7 + Math.sin(i / cycleFactor + time / 7); // A sine wave of the form sin(ax + bt) | |
| pix[i] = pix[i + 1] = pix[i + 2] = grayscale * Math.random() * c; // Set a random gray | |
| pix[i + 3] = opacity; // 100% opaque | |
| } | |
| context.putImageData(imgData, 0, 0); | |
| time = (time + 1) % canvas.height; // 取模,保证噪声带渲染不会超过画布 | |
| }; | |
| var setup = function () { | |
| canvas = document.createElement('canvas'); | |
| canvas.setAttribute('class', 'video-player-tv-noise'); | |
| document.getElementById(containerId).appendChild(canvas); | |
| context = canvas.getContext('2d'); | |
| }; | |
| // 销毁噪声动效 | |
| var destroy = function() { | |
| if (canvas.parentNode) { | |
| canvas.parentNode.removeChild(canvas); | |
| } | |
| if (intervalId) { | |
| window.clearInterval(intervalId); | |
| } | |
| }; | |
| setup(); | |
| intervalId = setInterval(makeNoise, interval); | |
| return { | |
| destroy: destroy | |
| }; | |
| } | |
| </script> | |
| </body> | |
| </html> | 
  
    Sign up for free
    to join this conversation on GitHub.
    Already have an account?
    Sign in to comment