HTML5 Canvas气泡背景特效

2026-05-13 23:40:29

1、新建html文档。

HTML5 Canvas气泡背景特效

2、书写页面html,css引用js。

<!DOCTYPE html>

<html>

<head>

<meta charset="UTF-8">

<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">

<meta name="viewport" content="width=device-width, initial-scale=1.0">

<title>HTML5 Canvas气泡背景特效</title>

<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>

</head>

<body>

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

<script async type="text/javascript" src="js/background.js"></script>

</body>

</html>

HTML5 Canvas气泡背景特效

3、书写js特效。

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();

});

4、查看效果。

HTML5 Canvas气泡背景特效

声明:本网站引用、摘录或转载内容仅供网站访问者交流或参考,不代表本站立场,如存在版权或非法内容,请联系站长删除,联系邮箱:site.kefu@qq.com。
相关推荐
  • 阅读量:34
  • 阅读量:102
  • 阅读量:170
  • 阅读量:144
  • 阅读量:163
  • 猜你喜欢