webgl+canvas实现炫酷柔和多彩背景动画效果代码

代码语言:html

所属分类:动画

代码描述:webgl+canvas实现炫酷柔和多彩背景动画效果代码

代码标签: webgl canvas 炫酷 柔和 多彩 背景 动画

下面为部分代码预览,完整代码请点击下载或在bfwstudio webide中打开

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <style>
        * {
    	margin: 0;
    	padding: 0;
    }
    
    body {
    	height: 100vh;
    	width: 100%;
    	display: grid;
    	place-items: stretch;
    }
    
    #gradient-canvas {
    	height: 100vh;
    	width: 100%;
    	background: lightgrey;
    }
    </style>

</head>

<body>
    <!-- partial:index.partial.html -->
    <canvas style="--gradient-color-1:#ef008f;--gradient-color-2:#6ec3f4;--gradient-color-3:#7038ff;--gradient-color-4:#e2e2e2;" id="gradient-canvas" data-transition-in></canvas>

    <script>
        window.addEventListener('DOMContentLoaded', (e) => {
        		var gradient = new Gradient;
        		gradient.initGradient("#gradient-canvas");
        	});
    </script>
    <!-- partial -->
    <script>
        // https://kevinhufnagl.com/wp-content/themes/lightisol/dist/js/min/lightisol-gradient.min.js?ver=1.0
    //
    
    function normalizeColor(hexCode) {
    	return [
    		((hexCode >> 16) & 255) / 255,
    		((hexCode >> 8) & 255) / 255,
    		(255 & hexCode) / 255
    	];
    }
    ["SCREEN", "LINEAR_LIGHT"].reduce(
    	(hexCode, t, n) => Object.assign(hexCode, { [t]: n }),
    	{}
    );
    class MiniGl {
    	constructor(canvas, width, height, debug = !1) {
    		const _miniGl = this,
    			debug_output =
    				-1 !== document.location.search.toLowerCase().indexOf("debug=webgl");
    		(_miniGl.canvas = canvas),
    			(_miniGl.gl = _miniGl.canvas.getContext("webgl", { antialias: !0 })),
    			(_miniGl.meshes = []);
    		const context = _miniGl.gl;
    		width && height && this.setSize(width, height),
    			_miniGl.lastDebugMsg,
    			(_miniGl.debug =
    				debug && debug_output
    					? function (e) {
    							const t = new Date();
    							t - _miniGl.lastDebugMsg > 1e3 && console.log("---"),
    								console.log(
    									t.toLocaleTimeString() +
    										Array(Math.max(0, 32 - e.length)).join(" ") +
    										e +
    										": ",
    									...Array.from(arguments).slice(1)
    								),
    								(_miniGl.lastDebugMsg = t);
    					  }
    					: () => {}),
    			Object.defineProperties(_miniGl, {
    				Material: {
    					enumerable: !1,
    					value: class {
    						constructor(vertexShaders, fragments, uniforms = {}) {
    							const material = this;
    							function getShaderByType(type, source) {
    								const shader = context.createShader(type);
    								return (
    									context.shaderSource(shader, source),
    									context.compileShader(shader),
    									context.getShaderParameter(shader, context.COMPILE_STATUS) ||
    										console.error(context.getShaderInfoLog(shader)),
    									_miniGl.debug("Material.compileShaderSource", { source: source }),
    									shader
    								);
    							}
    							function getUniformVariableDeclarations(uniforms, type) {
    								return Object.entries(uniforms)
    									.map(([uniform, value]) => value.getDeclaration(uniform, type))
    									.join("\n");
    							}
    							(this.uniforms = uniforms), (this.uniformInstances = []);
    							const prefix = "\n              precision highp float;\n            ";
    							(this.vertexSource = `\n              ${prefix}\n              attribute vec4 position;\n              attribute vec2 uv;\n              attribute vec2 uvNorm;\n              ${getUniformVariableDeclarations(
    								_miniGl.commonUniforms,
    								"vertex"
    							)}\n              ${getUniformVariableDeclarations(
    								uniforms,
    								"vertex"
    							)}\n              ${vertexShaders}\n            `),
    								(this.Source = `\n              ${prefix}\n              ${getUniformVariableDeclarations(
    									_miniGl.commonUniforms,
    									"fragment"
    								)}\n              ${getUniformVariableDeclarations(
    									uniforms,
    									"fragment"
    								)}\n              ${fragments}\n            `),
    								(this.vertexShader = getShaderByType(
    									context.VERTEX_SHADER,
    									this.vertexSource
    								)),
    								(this.fragmentShader = getShaderByType(
    									context.FRAGMENT_SHADER,
    									this.Source
    								)),
    								(this.program = context.createProgram()),
    								context.attachShader(this.program, this.vertexShader),
    								context.attachShader(this.program, this.fragmentShader),
    								context.linkProgram(this.program),
    								context.getProgramParameter(this.program, context.LINK_STATUS) ||
    									console.error(context.getProgramInfoLog(this.program)),
    								context.useProgram(this.program),
    								this.attachUniforms(void 0, _miniGl.commonUniforms),
    								this.attachUniforms(void 0, this.uniforms);
    						}
    						attachUniforms(name, uniforms) {
    							const material = this;
    							void 0 === name
    								? Object.entries(uniforms).forEach(([name, uniform]) => {
    										material.attachUniforms(name, uniform);
    								  })
    								: "array" == uniforms.type
    								? uniforms.value.forEach((uniform, i) =>
    										material.attachUniforms(`${name}[${i}]`, uniform)
    								  )
    								: "struct" == uniforms.type
    								? Object.entries(uniforms.value).forEach(([uniform, i]) =>
    										material.attachUniforms(`${name}.${uniform}`, i)
    								  )
    								: (_miniGl.debug("Material.attachUniforms", {
    										name: name,
    										uniform: uniforms
    								  }),
    								  material.uniformInstances.push({
    										uniform: uniforms,
    										location: context.getUniformLocation(material.program, name)
    								  }));
    						}
    					}
    				},
    				Uniform: {
    					enumerable: !1,
    					value: class {
    						constructor(e) {
    							(this.type = "float"),
    								Object.assign(this, e),
    								(this.typeFn =
    									{
    										float: "1f",
    										int: "1i",
    										vec2: "2fv",
    										vec3: "3fv",
    										vec4: "4fv",
    										mat4: "Matrix4fv"
    									}[this.type] || "1f"),
    								this.update();
    						}
    						update(value) {
    							void 0 !== this.value &&
    								context[`uniform${this.typeFn}`](
    									value,
    									0 === this.typeFn.indexOf("Matrix") ? this.transpose : this.value,
    									0 === this.typeFn.indexOf("Matrix") ? this.value : null
    								);
    						}
    						getDeclaration(name, type, length) {
    							const uniform = this;
    							if (uniform.excludeFrom !== type) {
    								if ("array" === uniform.type)
    									return (
    										uniform.value[0].getDeclaration(name, type, uniform.value.length) +
    										`\nconst int ${name}_length = ${uniform.value.length};`
    									);
    								if ("struct" === uniform.type) {
    									let name_no_prefix = name.replace("u_", "");
    									return (
    										(name_no_prefix =
    											name_no_prefix.charAt(0).toUpperCase() + name_no_prefix.slice(1)),
    										`uniform struct ${name_no_prefix} \n                                {\n` +
    											Object.entries(uniform.value)
    												.map(([name, uniform]) =>
    													uniform.getDeclaration(name, type).replace(/^uniform/, "")
    												)
    												.join("") +
    											`\n} ${name}${length > 0 ? `[${length}]` : ""};`
    									);
    								}
    								return `uniform ${uniform.type} ${name}${
    									length > 0 ? `[${length}]` : ""
    								};`;
    							}
    						}
    					}
    				},
    				PlaneGeometry: {
    					enumerable: !1,
    					value: class {
    						constructor(width, height, n, i, orientation) {
    							context.createBuffer(),
    								(this.attributes = {
    									position: new _miniGl.Attribute({
    										target: context.ARRAY_BUFFER,
    										size: 3
    									}),
    									uv: new _miniGl.Attribute({ target: context.ARRAY_BUFFER, size: 2 }),
    									uvNorm: new _miniGl.Attribute({
    										target: context.ARRAY_BUFFER,
    										size: 2
    									}),
    									index: new _miniGl.Attribute({
    										target: context.ELEMENT_ARRAY_BUFFER,
    										size: 3,
    										type: context.UNSIGNED_SHORT
    									})
    								}),
    								this.setTopology(n, i),
    								this.setSize(width, height, orientation);
    						}
    						setTopology(e = 1, t = 1) {
    							const n = this;
    							(n.xSegCount = e),
    								(n.ySegCount = t),
    								(n.vertexCount = (n.xSegCount + 1) * (n.ySegCount + 1)),
    								(n.quadCount = n.xSegCount * n.ySegCount * 2),
    								(n.attributes.uv.values = new Float32Array(2 * n.vertexCount)),
    								(n.attributes.uvNorm.values = new Float32Array(2 * n.vertexCount)),
    								(n.attributes.index.values = new Uint16Array(3 * n.quadCount));
    							for (let e = 0; e <= n.ySegCount; e++)
    								for (let t = 0; t <= n.xSegCount; t++) {
    									const i = e * (n.xSegCount + 1) + t;
    									if (
    										((n.attributes.uv.values[2 * i] = t / n.xSegCount),
    										(n.attributes.uv.values[2 * i + 1] = 1 - e / n.ySegCount),
    										(n.attributes.uvNorm.values[2 * i] = (t / n.xSegCount) * 2 - 1),
    										(n.attributes.uvNorm.values[2 * i + 1] = 1 - (e / n.ySegCount) * 2),
    										t < n.xSegCount && e < n.ySegCount)
    									) {
    										const s = e * n.xSegCount + t;
    										(n.attributes.index.values[6 * s] = i),
    											(n.attributes.index.values[6 * s + 1] = i + 1 + n.xSegCount),
    											(n.attributes.index.values[6 * s + 2] = i + 1),
    											(n.attributes.index.values[6 * s + 3] = i + 1),
    											(n.attributes.index.values[6 * s + 4] = i + 1 + n.xSegCount),
    											(n.attributes.index.values[6 * s + 5] = i + 2 + n.xSegCount);
    									}
    								}
    							n.attributes.uv.update(),
    								n.attributes.uvNorm.update(),
    								n.attributes.index.update(),
    								_miniGl.debug("Geometry.setTopology", {
    									uv: n.attributes.uv,
    									uvNorm: n.attributes.uvNorm,
    									index: n.attributes.index
    								});
    						}
    						setSize(width = 1, height = 1, orientation = "xz") {
    							const geometry = this;
    							(geometry.width = width),
    								(geometry.height = height),
    								(geometry.orientation = orientation),
    								(geometry.attributes.position.values &&
    									geometry.attributes.position.values.length ===
    										3 * geometry.vertexCount) ||
    									(geometry.attributes.position.values = new Float32Array(
    										3 * geometry.vertexCount
    									));
    							const o = width / -2,
    								r = height / -2,
    								segment_width = width / geometry.xSegCount,
    								segment_height = height / geometry.ySegCount;
    							for (let yIndex = 0; yIndex <= geometry.ySegCount; yIndex++) {
    								const t = r + yIndex * segment_height;
    								for (let xIndex = 0; xIndex <= geometry.xSegCount; xIndex++) {
    									const r = o + xIndex * segment_width,
    										l = yIndex * (geometry.xSegCount + 1) + xIndex;
    									(geometry.attributes.position.values[
    										3 * l + "xyz".indexOf(orientation[0])
    									] = r),
    										(geometry.attributes.position.values[
    											3 * l + "xyz".indexOf(orientation[1])
    										] = -t);
    								}
    							}
    							geometry.attributes.position.update(),
    								_miniGl.debug("Geometry.setSize", {
    									position: geometry.attributes.position
    								});
    						}
    					}
    				},
    				Mesh: {
    					enumerable: !1,
    					value: class {
    						constructor(geometry, material) {
    							const mesh = this;
    							(mesh.geometry = geometry),
    								(mesh.material = material),
    								(mesh.wireframe = !1),
    								(mesh.attributeInstances = []),
    								Object.entries(mesh.geometry.attributes).forEach(([e, attribute]) => {
    									mesh.attributeInstances.push({
    										attribute: attribute,
    										location: attribute.attach(e, mesh.material.program)
    									});
    								}),
    								_miniGl.meshes.push(mesh),
    								_miniGl.debug("Mesh.constructor", { mesh: mesh });
    						}
    						draw() {
    							context.useProgram(this.material.program),
    								this.material.uniformInstances.forEach(({ uniform: e, location: t }) =>
    									e.update(t)
    								),
    								this.attributeInstances.forEach(({ attribute: e, location: t }) =>
    									e.use(t)
    								),
    								context.drawElements(
    									this.wireframe ? context.LINES : context.TRIANGLES,
    									this.geometry.attributes.index.values.length,
    									context.UNSIGNED_SHORT,
    									0
    								);
    						}
    						remove() {
    							_miniGl.meshes = _miniGl.meshes.filter((e) => e != this);
    						}
    					}
    				},
    				Attribute: {
    					enumerable: !1,
    					value: class {
    						constructor(e) {
    							(this.type = context.FLOAT),
    								(this.normalized = !1),
    								(this.buffer = context.createBuffer()),
    								Object.assign(this, e),
    								this.update();
    						}
    						update() {
    							void 0 !== this.values &&
    								(context.bindBuffer(this.target, this.buffer),
    								context.bufferData(this.target, this.values, context.STATIC_DRAW));
    						}
    						attach(e, t) {
    							const n = context.getAttribLocation(t, e);
    							return (
    								this.target === context.ARRAY_BUFFER &&
    									(context.enableVertexAttribArray(n),
    									context.vertexAttribPointer(
    										n,
    										this.size,
    										this.type,
    										this.normalized,
    										0,
    										0
    									)),
    								n
    							);
    						}
    						use(e) {
    							context.bindBuffer(this.target, this.buffer),
    								this.target === context.ARRAY_BUFFER &&
    									(context.enableVertexAttribArray(e),
    									context.vertexAttribPointer(
    										e,
    										this.size,
    										this.type,
    										this.normalized,
    										0,
    										0
    									));
    						}
    					}
    				}
    			});
    		const a = [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1];
    		_miniGl.commonUniforms = {
    			projectionMatrix: new _miniGl.Uniform({ type: "mat4", value: a }),
    			modelViewMatrix: new _miniGl.Uniform({ type: "mat4", value: a }),
    			resolution: new _miniGl.Uniform({ type: "vec2", value: [1, 1] }),
    			aspectRatio: new _miniGl.Uniform({ type: "float", value: 1 })
    		};
    	}
    	setSize(e = 640, t = 480) {
    		(this.width = e),
    			(this.height = t),
    			(this.canvas.width = e),
    			(this.canvas.height = t),
    			this.gl.viewport(0, 0, e, t),
    			(this.commonUniforms.resolution.value = [e, t]),
    			(this.commonUniforms.aspectRatio.value = e / t),
    			this.debug("MiniGL.setSize", { width: e, height: t });
    	}
    	setOrthographicCamera(e = 0, t = 0, n = 0, i = -2e3, s = 2e3) {
    		(this.commonUniforms.projectionMatrix.value = [
    			2 / this.width,
    			0,
    			0,
    			0,
    			0,
    			2 / this.height,
    			0,
    			0,
    			0,
    			0,
    			2 / (i - s),
    			0,
    			e,
    			t,
    			n,
    			1
    		]),
    			this.debug(
    				"setOrthographicCamera",
    				this.commonUniforms.projectionMatrix.value
    			);
    	}
    	render() {
    		this.gl.clearColor(0, 0, 0, 0),
    			this.gl.clearDepth(1),
    			this.meshes.forEach((e) => e.draw());
    	}
    }
    function e(object, propertyName, val) {
    	return (
    		propertyName in object
    			? Object.defineProperty(object, propertyName, {
    					value: val,
    					enumerable: !0,
    					configurable: !0,
    					writable: !0
    			  })
    			: (object[propertyName] = val),
    		object
    	);
    }
    class Gradient {
    	constructor(...t) {
    		e(this, "el", void 0),
    			e(this, "cssVarRetries", 0),
    			e(this, "maxCssVarRetries", 200),
    			e(this, "angle", 0),
    			e(this, "isLoadedClass", !1),
    			e(this, "isScrolling", !1),
    			e(this, "scrollingTimeout", void 0),
    			e(this, "scrollingRefreshDelay", 200),
    			e(this, "isIntersecting", !1),
    			e(this, "shaderFiles", void 0),
    			e(this, "vertexShader", void 0),
    			e(this, "sectionColors", void 0),
    			e(this, "computedCanvasStyle", void 0),
    			e(this, "conf", void 0),
    			e(this, "uniforms", void 0),
    			e(this, "t", 1253106),
    			e(this, "last", 0),
    			e(this, "width", void 0),
    			e(this, "minWidth", 1111),
    			e(this, "height", 600),
    			e(this, "xSegCount", void 0),
    			e(this, "ySegCount", void 0),
    			e(this, "mesh", void 0),
    			e(this, "material", void 0),
    			e(this, "geometry", void 0),
    			e(this, "minigl", void 0),
    			e(this, "scrollObserver", void 0),
    			e(this, "amp", 320),
    			e(this, "seed", 5),
    			e(this, "freqX", 14e-5),
    			e(this, "freqY", 29e-5),
    			e(this, "freqDelta", 1e-5),
    			e(this, "activeColors", [1, 1, 1, 1]),
    			e(this, "isMetaKey", !1),
    			e(this, "isGradientLegendVisible", !1),
    			e(this, "isMouseDown", !1),
    			e(this, "handleScroll", () => {
    				clearTimeout(this.scrollingTimeout),
    					(this.scrollingTimeout = setTimeout(
    						this.handleScrollEnd,
    						this.scrollingRefreshDelay
    					)),
    					this.isGradientLegendVisible && this.hideGradientLegend(),
    					this.conf.playing && ((this.isScrolling = !0), this.pause());
    			}),
    			e(this, "handleScrollEnd", () => {
    				(this.isScrolling = !1), this.isIntersecting && this.play();
    			}),
    			e(this, "resize", () => {
    				(this.wi.........完整代码请登录后点击上方下载按钮下载查看

网友评论0