canvas实现webgl线圈绕组动画效果代码

代码语言:html

所属分类:动画

代码描述:canvas实现webgl线圈绕组动画效果代码,可通过dat.gui更换图形,选择圆圈、星星等图形样式、还可更改背景颜色。

代码标签: canvas webgl 线圈 绕组 动画

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

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

<head>

  <meta charset="UTF-8">
  

  
  
  
  
<style>
body {
    background-color: #fff;    
    margin: 0;
		overflow: hidden;
}
canvas {
	position: absolute;
  background-color: #999;
  width: 100%;
  height: 100%;
  vertical-align: middle;
	display:inline-block;
}
</style>



</head>

<body >

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


<script type="text/javascript" src="//repo.bfw.wiki/bfwrepo/js/dat.gui-min.js"></script>
      <script  >
/*
*  The winding number of a point describes how many full revolutions a curve makes around it.
*  Open curves produce interesting visuals. We discretise parametric curves into linear
*  segments and find the signed angle between the vectors connecting a point to the segment.
*  The sum of these angles, divided by 2PI radians, gives the winding number.
*
*  Based on:
*      https://en.wikipedia.org/wiki/Winding_number
*  [1] https://igl.ethz.ch/projects/winding-number/
*      https://twitter.com/keenanisalive/status/1448036393012322313
*      https://www.shadertoy.com/view/Wddyz2
*
*/

let canvas = document.getElementById("canvas");

canvas.width = window.innerWidth;
canvas.height = window.innerHeight;

// MSAA
let multiplier = 2.0;

var AA = true;

// Initialize the GL context
let gl = canvas.getContext('webgl');
if (!gl) {
  console.error("Unable to initialize WebGL.");
}

let time = 0.0;
let scene = 0;
let palette = 0;

let sceneNames = ["Circle", "Heart", "Star", "Infinity"];
let paletteNames = ["Grayscale", "Rainbow", "Red", "Blue"];

let sceneSelector = { scene: "Circle" };
let paletteSelector = { palette: "Rainbow" };

setScene(sceneSelector.scene);
setPalette(paletteSelector.palette);

//************* GUI ***************

let gui = new dat.GUI();

gui.add(sceneSelector, 'scene').options(sceneNames).onChange(name => {setScene(name);});
gui.add(paletteSelector, 'palette').options(paletteNames).onChange(name => {setPalette(name);});
gui.add(this, 'AA').onChange(b => {b ? multiplier = 2 : multiplier = 1;onWindowResize();}).listen();
gui.close();

//******** Shader sources *********

let vertexSource = `
attribute vec2 position;
void main() {
	// Screenspace position of vertices can use the data passed from the CPU
	// Set z-component to 0
  gl_Position = vec4(position, 0.0, 1.0);
}
`;

//Replace with GLSL fragment shader code
let fragmentSource = `
	precision highp float;

	uniform vec2 resolution;
	uniform float time;
	uniform float u_scene;
	uniform float u_palette;

	#define PI 3.1415926536
	#define TWO_PI 6.2831853072

	// https://math.stackexchange.com/questions/3020095/signed-angle-in-plane:
	// "the ratio of the cross product and scalar product is the tangent of the angle"
	// From [1]: "The tangent of the signed angle between a and b is det([ab]) / dot(ab)"
	float signedAngle(vec2 a, vec2 b){
		// atan(y, x) returns the angle whose arctangent is y / x. Value in [-pi, pi]
		return atan(a.x*b.y - a.y*b.x, dot(a, b));
	}


	// https://iquilezles.org/articles/palettes/
	vec3 getColour(float t, int palette){

		if(palette == 0){
			// Black and white
			return vec3(-0.5 * t + 0.45);
		}

		vec3 a;
		vec3 b;
		vec3 c;
		vec3 d;

		if(palette == 1){
			// Pastel rainbow
			// Animated

			t *= 0.45;
			t += 0.1 * time;

			a = vec3(0.65);
			b = 1.0 - a;
			c = vec3(1.0,1.0,1.0);
			d = vec3(0.15,0.5,0.75);

		}else if(palette == 2){

			// Red and purple

			t *= -0.3;
			t += 0.65;

			a = vec3(0.55, 0.5, 0.7);
			b = 1.0-a;
			c = vec3(1.0,1.0,1.0);
			d = vec3(0.15,0.95,0.8);

		}else if(palette == 3){

			// Blue
			// Same as above with different t

			t *= 0.35;
			t += 0.3;

			a = vec3(0.55, 0.5, 0.7);
			b = 1.0-a;
			c = vec3(1.0,1.0,1.0);
			d = vec3(0.15,0.95,0.8);

		}
		return a + b * cos(TWO_PI *(c * t + d));
	}

	vec2 getCircle(float t){
		return vec2(sin(t), cos(t));
	}

	// http://mathworld.wolfram.com/Lemniscate.html
	vec2 getLemniscate(float t){
		float a = 1.5;
		return vec2((a * cos(t)) / (1.0 + (sin(t) * sin(t))), 
								(a * sin(t) * cos(t))/ (1.0 + (sin(t) * sin(t))));
	}

	// http://mathworld.wolfram.com/HeartCurve.html
	vec2 getHeart(float t){
		return 0.05 * vec2(1, -1) * vec2(16.0 * sin(t) * sin(t) * sin(t),
								-(13.0 * cos(t) - 5.0 * cos(2.0 * t)
								- 2.0 * cos(3.0 * t) - cos(4.0 * t))) + vec2(0, 0.1);
	}

	vec2 rotate2d(vec2 v, float a){
		return v * mat2(cos(a),-sin(a), sin(a), cos(a));
	}

	// https://en.wikipedia.org/wiki/Hypotrochoid
	// https://mathworld.wolfram.com/Hypotrochoid.html
	vec2 getHypotrochoid(float t){
		float a = 5.0;
		float b = 3.0;
		float h = 5.0;
		float a_b  = a - b;
		float t_ab = t * a_b / b;
		return vec2(a_b * cos(t) + h * cos(t_ab), a_b * sin(t) - h * sin(t_ab));
	}


	vec2 getPosition(float t, int scene){

		if(scene == 0){
			return getCircle(t);
		}else if(scene == 1){
			return getHeart(t);
		}else if(scene == 2){
			return getHypotrochoid(t);
		}else{
			return getLemniscate(t);
		}

	}

	void main(){

		// Normalized pixel coordinates (from 0 to 1)
		vec2 uv = gl_FragCoord.xy/resolution;

		uv -= 0.5;
		uv.y /= resolution.x / resolution.y;
		uv *= 4.0 + max(0.0, (resolution.x / resolution.y) - 0.5);

		float angle = 0.0;
		float segments = 16.0;

		float delta = (0.25 * (TWO_PI)) / segments;

		float speed = 2.0;
		float radius = 1.0;
		
		int scene = int(u_scene);
		int palette = int(u_palette);

		// Hear.........完整代码请登录后点击上方下载按钮下载查看

网友评论0