Tạo hình nền bong bóng chuyển động tuyệt đẹp với Javascript

23.6.19 | 0 nhận xét | lượt xem
Nội Dung Chính
    Bài viết hướng dẫn bạn sử dụng JavaScript cho phép bạn tạo các bong bóng chuyển động với màu sắc đẹp tuyệt vời, mượt mà cho nền blog/website và không cần dùng hình ảnh

    File JS tạo bong bóng chuyển động

    Bạn sử dụng đoạn code bên dưới
    <script async src="background.js"></script>
    
    Nội dung file JS
    /* 
     * background.js - simple abstract background generator
     *
     * Changes:
     *  21-Jan-2016
     *   > Cap frames to 10 on mobile to prevent scroll lag
     *  20-Jan-2016
     *   + Added more versatile mobile options
     *   > Using tabs and 80 width
     *   > Settings object instead of lotsa variables
     *   > Bokeh jitter now assumes inverted min/max, added x/y options instead
     *   - Removed previous change of rounding values, for better looks
     *   - Removed gradient jitter, not useful
     *  6-Jan-2016
     *   > Stored PI * 2 in var for better framerate on mobile
     *   > Drawing circles to off-screen canvas only once, reducing .arc() ops
     *   + Added mobile detection
     *   + In-depth mobile+debug options
     *
     * @author  pbondoer - http://bondoer.fr/
     * @license CC0 - https://creativecommons.org/publicdomain/zero/1.0/
     */
    
    window.addEventListener("load", function() {
     var ctx = document.getElementById('background').getContext('2d');
     //gradient
     var options =
     {
      resolution: 1,
      gradient:
      {
       resolution: 4,
       smallRadius: 0,
       hue:
       {
        min: 0,
        max: 360
       },
       saturation:
       {
        min: 40,
        max: 80
       },
       lightness:
       {
        min: 25,
        max: 35
       }
      },
      bokeh:
      {
       count: 30,
       size:
       {
        min: 0.1,
        max: 0.3
       },
       alpha:
       {
        min: 0.05,
        max: 0.4
       },
       jitter:
       {
        x: 0.3,
        y: 0.3
       }
      },
      speed:
      {
       min: 0.0001,
       max: 0.001
      },
      debug:
      {
       strokeBokeh: false,
       showFps: false
      }
     };
     var mobile =
     {
      force: false,
      resolution: 0.5,
      bokeh:
      {
       count: 6
      }
     };
     //buffers
     var gradientBuffer = document.createElement('canvas').getContext('2d');
     var circleBuffer = document.createElement('canvas').getContext('2d');
     //render time, fps calculations, debug
     var time;
     var targetFps = 60; //not actual fps, but updates per second
     var curFps = 0;
     var cntFps = 0;
     var fps = 0;
     var w = 0;
     var h = 0;
     var scale = 0;
     //constants for faster calcs
     var pi2 = Math.PI * 2;
     //util functions
     function lerp(a, b, step) {
      return step * (b - a) + a;
     }
     function clamp(a) {
      if (a < 0) return 0;
      if (a > 1) return 1;
      return a;
     }
     function rand(obj) {
      return Math.random() * (obj.max - obj.min) + obj.min;
     }
     function newColor() {
      return new Color(
        rand(options.gradient.hue),
        rand(options.gradient.saturation),
        rand(options.gradient.lightness)
        );
     }
    
     function isMobile() { 
      return (
        mobile.force
        || navigator.userAgent.match(/Android/i)
        || navigator.userAgent.match(/webOS/i)
        || navigator.userAgent.match(/iPhone/i)
        || navigator.userAgent.match(/iPad/i)
        || navigator.userAgent.match(/iPod/i)
        || navigator.userAgent.match(/BlackBerry/i)
        || navigator.userAgent.match(/Windows Phone/i)
          );
     }
    
     window.requestAnimFrame = (function(callback) {
      if (isMobile())
       return function(callback) {
        window.setTimeout(callback, 1000 / 10);
       };
      return window.requestAnimationFrame || window.webkitRequestAnimationFrame
       || window.mozRequestAnimationFrame || window.oRequestAnimationFrame
       || window.msRequestAnimationFrame || function(callback) {
        window.setTimeout(callback, 1000 / 60);
       };
     })();
    
     //classes
     function Color(h, s, l) {
      this.h = h;
      this.s = s;
      this.l = l;
    
      this.str = function() {
       return this.h + ", " + this.s + "%, " + this.l +"%";
      }
     }
     function ColorPoint(x, y, color) {
      this.x = x;
      this.y = y;
      this.oldColor = color;
      this.newColor = color;
      this.step = 0;
      this.speed = 0;
    
      this.color = function() {
       return new Color(lerp(this.oldColor.h, this.newColor.h, this.step),
         lerp(this.oldColor.s, this.newColor.s, this.step),
         lerp(this.oldColor.l, this.newColor.l, this.step));
      }
    
     }
     var colorPoints = [
      new ColorPoint(0, 0, new Color(196, 59, 34)),
      new ColorPoint(0, 1, new Color(269, 79, 32)),
      new ColorPoint(1, 0, new Color(30, 42, 33)),
      new ColorPoint(1, 1, new Color(304, 47, 27))
     ];
    
     function BokehCircle(x, y, size, alpha) {
      this.oldX = x;
      this.oldY = y;
      this.oldSize = size;
      this.oldAlpha = alpha;
      this.newX = 0;
      this.newY = 0;
      this.newAlpha = 0;
      this.newSize = 0;
      this.step = 0;
      this.speed = 0;
    
      this.x = function() {
       return lerp(this.oldX, this.newX, this.step);
      }
      this.y = function() {
       return lerp(this.oldY, this.newY, this.step);
      }
      this.alpha = function() {
       return lerp(this.oldAlpha, this.newAlpha, this.step);
      }
      this.size = function() {
       return lerp(this.oldSize, this.newSize, this.step);
      }
     }
     var circles = [];
    
     function setJitter(circle) {
      circle.newX = clamp(circle.oldX + rand({
       min: -options.bokeh.jitter.x,
       max: options.bokeh.jitter.x
      }));
      circle.newY = clamp(circle.oldY + rand({
       min: -options.bokeh.jitter.y,
       max: options.bokeh.jitter.y
      }));
     }
     function resize() {
      var width = window.innerWidth;
      var height = window.innerHeight;
    
      w = width * options.resolution;
      h = height * options.resolution;
      scale = Math.sqrt(w * h);
    
      //actual canvas
      ctx.canvas.width = width;
      ctx.canvas.height = height;
      ctx.scale(1 / options.resolution, 1 / options.resolution);
    
      //circle canvas
      var circleSize = options.bokeh.size.max * scale;
      circleBuffer.canvas.width = circleSize * 2 + 1;
      circleBuffer.canvas.height = circleSize * 2 + 1;
    
      circleBuffer.fillStyle = "rgb(255, 255, 255)";
      circleBuffer.beginPath();
      circleBuffer.arc(circleSize, circleSize, circleSize, 0, pi2);
      circleBuffer.closePath();
      circleBuffer.fill();
    
      //force render on mobile
      if (isMobile())
       render();
     }
     function softCopy(src, dest)
     {
      var i = 0;
    
      for (var property in src)
      {
       if (dest.hasOwnProperty(property))
        if (softCopy(src[property], dest[property]) == 0)
         dest[property] = src[property];
       i++;
      }
      return i;
     }
     function init() {
      gradientBuffer.canvas.height = options.gradient.resolution;
      gradientBuffer.canvas.width = options.gradient.resolution;
    
      if (isMobile())
       softCopy(mobile, options);
    
      resize();
    
      colorPoints.forEach(function(point) {
       point.oldColor = newColor();
       point.newColor = newColor()
        point.speed = rand(options.speed);
      });
    
      for(i = 0; i < options.bokeh.count; i++) {
       circles.push(new BokehCircle(Math.random(), Math.random(),
          rand(options.bokeh.size), rand(options.bokeh.alpha)));
       circles[i].newAlpha = rand(options.bokeh.alpha);
       circles[i].newSize = rand(options.bokeh.size);
       circles[i].speed = rand(options.speed);
       setJitter(circles[i]);
      }
     }
     function iterate() {
      var now = Date.now();
      curFps += (now - (time || now));
      cntFps++;
      var delta = (now - (time || now)) / (1000 / targetFps);
      time = now;
    
      if(curFps > 1000) {
       fps = 1000 / (curFps / cntFps);
       curFps -= 1000;
       cntFps = 0;
      }
    
      colorPoints.forEach(function(point) {
       point.step += point.speed * delta;
    
       if (point.step >= 1) {
        point.step = 0;
    
        point.oldColor = point.newColor;
    
        point.newColor = newColor();
        point.speed = rand(options.speed);
       }
      });
    
      circles.forEach(function(circle) {
       circle.step += circle.speed * delta;
       if(circle.step >= 1) {
        circle.step = 0;
    
        circle.oldX = circle.newX;
        circle.oldY = circle.newY;
        circle.oldAlpha = circle.newAlpha;
        circle.oldSize = circle.newSize;
    
        setJitter(circle);
        circle.newAlpha = rand(options.bokeh.alpha);
        circle.newSize = rand(options.bokeh.size);
        circle.speed = rand(options.speed);
       }
      });
     }
    
     function render() {
      iterate();
    
      //draw point gradient to buffer
      colorPoints.forEach(function(point) {
       var x = point.x * options.gradient.resolution;
       var y = point.y * options.gradient.resolution;
       var grad = gradientBuffer.createRadialGradient(x, y,
         options.gradient.smallRadius, x, y,
         options.gradient.resolution);
       grad.addColorStop(0, 'hsla(' + point.color().str() + ', 255)');
       grad.addColorStop(1, 'hsla(' + point.color().str() + ', 0)');
    
       gradientBuffer.fillStyle = grad;
       gradientBuffer.fillRect(0, 0,
         options.gradient.resolution, options.gradient.resolution);
      });
    
      //draw gradient from memory
      ctx.globalCompositeOperation = "source-over";
      ctx.drawImage(gradientBuffer.canvas, 0, 0, w, h);
    
      //draw bokeh
      ctx.globalCompositeOperation = "overlay";
      if (options.debug.strokeBokeh)
       ctx.strokeStyle = "yellow";
    
      circles.forEach(function(circle) {
       var size = circle.size() * scale;
    
       ctx.globalAlpha = circle.alpha();
       ctx.drawImage(circleBuffer.canvas,
         circle.x() * w - size / 2, circle.y() * h - size / 2,
         size, size);
    
       if(options.debug.strokeBokeh) {
        ctx.globalAlpha = 1;
        ctx.globalCompositeOperation = "source-over";
        ctx.strokeRect(circle.x() * w - size / 2,
          circle.y() * h - size / 2, size, size);
        ctx.globalCompositeOperation = "overlay";
       }
      });
      ctx.globalAlpha = 1;
    
      //debug info
      if (options.debug.showFps) {
       if(fps <= 10) ctx.fillStyle = 'red';
       else ctx.fillStyle = 'yellow';
    
       ctx.font = "20px sans-serif";
       ctx.fillText(Math.round(fps) + " fps", 10, 20);
      }
    
      //done rendering, wait for frame
      window.requestAnimFrame(render);
     }
    
     //does not seem to impact performance
     window.addEventListener("resize", resize);
    
     //init and render :)
     init();
     render();
    });

    Sử dụng HTML để hiển thị nền bong bóng

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

    Sử dụng CSS để cố định nền

    <style>
      body, html {
       position: absolute;
       top: 0;
       bottom: 0;
       left: 0;
       right: 0;
    
       margin: 0;
       padding: 0;
      }
      #background {
       position: fixed;
       top: 0;
       left: 0;
       z-index: -100;
      }
    </style>
    
    Cảm ơn đã theo dõi và chúc thành công! ./.
    Nguồn: cssscript.com
    Bạn đang xem bài viết "Tạo hình nền bong bóng chuyển động tuyệt đẹp với Javascript" tại chuyên mục: CSS , HTML , Javascript

    Bình luận

    Chèn hình ảnh: Chỉ cần dán link hình ảnh - Upload ảnh

    Chèn code: [pre]Code đã mã hóa [/pre]

    Chèn emoji: Nhấn tổ hợp phím “Windows + . (dấu chấm)”

    Chèn link: Click để chèn link