ANTON072
1/13/2015 - 5:08 PM

canvasのlighter http://bl.ocks.org/ANTON072/raw/eb188691973152d75d8c/

<!doctype html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Document</title>
  <style>
    html,body{
      padding:0;
      margin:0;
    }
    canvas{position:absolute;top:0;left:0}
  </style>
</head>
<body>

  <canvas id="canvas"></canvas>

  <script>
    var canvas = document.getElementById('canvas');
    var context = canvas.getContext('2d');
    var width = window.innerWidth;
    var height = window.innerHeight;

    canvas.width = width;
    canvas.height = height;
    context.fillRect(0, 0, width, height); // 黒で塗る
    context.lineWidth = 2;

    /**
     * ■■■■■■■■ Circle Class ■■■■■■■■■■■■■■■■■■■■■■■■■■■■
     */
    function Circle() {

      this.x = Math.floor(Math.random() * width);
      this.y = Math.floor(Math.random() * height);
      this.size = Math.floor(Math.random() * 20) + 15;
      this.speed = (Math.random() * 1) + 1;
      this.color = {r: 0, g: 0, b: 0};

      var colorAvg = 0;
      // colorを150以下のランダム値に設定する
      while(colorAvg < 150) {
//        console.log('a'); // 299;
        this.color.r = Math.floor(Math.random() * 255);
        this.color.g = Math.floor(Math.random() * 255);
        this.color.b = Math.floor(Math.random() * 255);
//        console.log(this.color.r + this.color.g + this.color.b) / 3;
        colorAvg = (this.color.r + this.color.g + this.color.b) / 3;
      }
//      console.log(colorAvg, this.color);
    }

    /**
     * ■■■■■■■■ Bokeh Class ■■■■■■■■■■■■■■■■■■■■■■■■■■■■
     */
    function Bokeh() {
      this.circles = [];
      this.blurCanvas = document.createElement('canvas');
//      this.blurCanvas.width = canvas.width;
//      this.blurCanvas.height = canvas.height;
      // 1/2サイズにしてわざとぼかしている
      this.blurCanvas.width = canvas.width / 2;
      this.blurCanvas.height = canvas.height / 2;
      this.blurContext = this.blurCanvas.getContext('2d');

      for (var i = 0, len = Math.floor(width / 12); i < len; i++) {
        this.circles.push( new Circle() );
      }
      this.tick();
    }

    Bokeh.prototype = {
      tick: function() {
        // 画像合成
        // http://www.htmq.com/canvas/globalCompositeOperation.shtml
        // source-over: 初期値 ここではリセットの意味
        // lighter: 加算。光の混合と同じ。
        // circleが重なった部分をlighterで表現している
        context.globalCompositeOperation = "source-over";
        context.fillStyle = 'rgba(0, 0, 0, 1)'; // 背景
        context.fillRect(0, 0, canvas.width, canvas.height);
        context.globalCompositeOperation = "lighter";
        var circs = this.circles.length;
        while(circs--) {
          var circle = this.circles[circs];
          var color = circle.color;
//          console.log(color);
          context.fillStyle = 'rgba(' + color.r + ',' + color.g + ',' + color.b + ', 0.2)';
          circle.x += circle.speed;
          circle.y += circle.speed;
          if (circle.x > width + circle.size) {
            circle.x = -circle.size;
          }
          if (circle.y > height + circle.size) {
            circle.y = -circle.size;
          }
          context.beginPath();
          context.arc(circle.x, circle.y, circle.size, 0, 360);
          context.fill();
//          context.beginPath();
//          context.strokeStyle = 'rgba(' + color.r + ',' + color.g + ',' + color.b + ', 0.8)';
//          context.arc(circle.x, circle.y, circle.size, 0, 360);
//          context.stroke();
        }
        // 一旦1/2スケールのcanvasに書き出して、再度canvasに書き出す
        this.blurContext.drawImage(canvas, 0, 0, width, height);
        context.drawImage(this.blurCanvas, 0, 0, width, height);
        // 再帰
        setTimeout(this.tick.bind(this), 10);
      }
    };

    new Bokeh();

  </script>

</body>
</html>