首页 前端知识 如何用前端实现炫酷粒子效果(HTML)

如何用前端实现炫酷粒子效果(HTML)

2024-05-28 09:05:24 前端知识 前端哥 479 788 我要收藏

养成习惯先赞后看

效果图展示


1.初始化 WebGL 上下文,并创建顶点着色器和片元着色器。                                                                 

// 获取 canvas 元素,并设置 WebGL 上下文
var canvas = document.getElementById('myCanvas');
var gl = canvas.getContext('webgl');

// 定义顶点着色器
var vertexShaderSource = `
    attribute vec2 position;
    void main() {
        gl_Position = vec4(position, 0, 1.0);
    }
`;

// 定义片元着色器
var fragmentShaderSource = `
    void main() {
        gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
    }
`;

// 创建顶点着色器
var vertexShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertexShader, vertexShaderSource);
gl.compileShader(vertexShader);

// 创建片元睝色器
var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragmentShader, fragmentShaderSource);
gl.compileShader(fragmentShader);

2.创建程序,并设置视口大小和背景颜色。                                                                                             

// 创建程序
var program = gl.createProgram();
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
gl.linkProgram(program);
gl.useProgram(program);

// 设置视口大小和背景颜色
gl.viewport(0, 0, canvas.width, canvas.height);
gl.clearColor(0.0, 0.0, 0.0, 1.0);
gl.clear(gl.COLOR_BUFFER_BIT);

3.创建顶点数据,并传入缓冲区。                                                                                                       

// 创建顶点数据
var vertices = new Float32Array([
    -0.5, 0.5,
    -0.5, -0.5,
    0.5, -0.5,
    0.5, 0.5
]);

// 创建缓冲区并传入顶点数据
var vertexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);

4.获取位置属性并启用,然后定义绘制函数。                                                                              

// 获取位置属性并启用
var position = gl.getAttribLocation(program, 'position');
gl.vertexAttribPointer(position, 2, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(position);

// 绘制函数
function draw() {
    // 更新线条位置和形状的逻辑

    // 清除画布
    gl.clear(gl.COLOR_BUFFER_BIT);

    // 绘制三角形
    gl.drawArrays(gl.TRIANGLE_FAN, 0, 4);

    // 请求下一帧动画
    requestAnimationFrame(draw);
}

5.最后通过 requestAnimationFrame() 方法开始绘制动画。                                                                

// 开始绘制动画
requestAnimationFrame(draw);

全部代码如下:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
 <HEAD>
  <TITLE> New Document </TITLE>
  <META NAME="Generator" CONTENT="EditPlus">
  <META NAME="Author" CONTENT="">
  <META NAME="Keywords" CONTENT="">
  <META NAME="Description" CONTENT="">
  <style>@import "compass/css3";

@import "compass/reset";
@import "compass/css3";

body{
  overflow: hidden;
}

canvas{
  width: 100%;
  height: 100%;
}</style>
 </HEAD>

 <BODY>
 
<canvas id="c"></canvas>

<script id="shader-fs" type="x-shader/x-fragment">
				#ifdef GL_ES
				  precision highp float;
				  #endif
    		void main(void) {
    		 gl_FragColor = vec4(0.2, 0.3, 0.4, 1.0);
    		}
		</script>

  <script id="shader-vs" type="x-shader/x-vertex">
    	attribute vec3 vertexPosition;

  	uniform mat4 modelViewMatrix;
  	uniform mat4 perspectiveMatrix;

   	void main(void) {
  		gl_Position = perspectiveMatrix * modelViewMatrix * vec4(  vertexPosition, 1.0);
  	}
  </script>
  
  <script>window.onload = loadScene;

var canvas, gl,
  ratio,
  vertices,
  velocities,
  freqArr,
  cw,
  ch,
  colorLoc,
  thetaArr,
  velThetaArr,
  velRadArr,
  boldRateArr,
  drawType,
  numLines = 40000;
var target = [];
var randomTargetXArr = [], randomTargetYArr = [];
drawType = 2;


/**
 * Initialises WebGL and creates the 3D scene.
 */
function loadScene() {
  //    Get the canvas element
  canvas = document.getElementById("c");
  //    Get the WebGL context
  gl = canvas.getContext("experimental-webgl");
  //    Check whether the WebGL context is available or not
  //    if it's not available exit
  if (!gl) {
    alert("There's no WebGL context available.");
    return;
  }
  //    Set the viewport to the canvas width and height
  cw = window.innerWidth;
  ch = window.innerHeight;
  canvas.width = cw;
  canvas.height = ch;
  gl.viewport(0, 0, canvas.width, canvas.height);

  //    Load the vertex shader that's defined in a separate script
  //    block at the top of this page.
  //    More info about shaders: http://en.wikipedia.org/wiki/Shader_Model
  //    More info about GLSL: http://en.wikipedia.org/wiki/GLSL
  //    More info about vertex shaders: http://en.wikipedia.org/wiki/Vertex_shader

  //    Grab the script element
  var vertexShaderScript = document.getElementById("shader-vs");
  var vertexShader = gl.createShader(gl.VERTEX_SHADER);
  gl.shaderSource(vertexShader, vertexShaderScript.text);
  gl.compileShader(vertexShader);
  if (!gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS)) {
    alert("Couldn't compile the vertex shader");
    gl.deleteShader(vertexShader);
    return;
  }

  //    Load the fragment shader that's defined in a separate script
  //    More info about fragment shaders: http://en.wikipedia.org/wiki/Fragment_shader
  var fragmentShaderScript = document.getElementById("shader-fs");
  var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
  gl.shaderSource(fragmentShader, fragmentShaderScript.text);
  gl.compileShader(fragmentShader);
  if (!gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS)) {
    alert("Couldn't compile the fragment shader");
    gl.deleteShader(fragmentShader);
    return;
  }

  //    Create a shader program.
  gl.program = gl.createProgram();
  gl.attachShader(gl.program, vertexShader);
  gl.attachShader(gl.program, fragmentShader);
  gl.linkProgram(gl.program);
  if (!gl.getProgramParameter(gl.program, gl.LINK_STATUS)) {
    alert("Unable to initialise shaders");
    gl.deleteProgram(gl.program);
    gl.deleteProgram(vertexShader);
    gl.deleteProgram(fragmentShader);
    return;
  }
  //    Install the program as part of the current rendering state
  gl.useProgram(gl.program);
  //    Get the vertexPosition attribute from the linked shader program
  var vertexPosition = gl.getAttribLocation(gl.program, "vertexPosition");
  //    Enable the vertexPosition vertex attribute array. If enabled, the array
  //    will be accessed an used for rendering when calls are made to commands like
  //    gl.drawArrays, gl.drawElements, etc.
  gl.enableVertexAttribArray(vertexPosition);

  //    Clear the color buffer (r, g, b, a) with the specified color
  gl.clearColor(0.0, 0.0, 0.0, 1.0);
  //    Clear the depth buffer. The value specified is clamped to the range [0,1].
  //    More info about depth buffers: http://en.wikipedia.org/wiki/Depth_buffer
  gl.clearDepth(1.0);
  //    Enable depth testing. This is a technique used for hidden surface removal.
  //    It assigns a value (z) to each pixel that represents the distance from this
  //    pixel to the viewer. When another pixel is drawn at the same location the z
  //    values are compared in order to determine which pixel should be drawn.
  //gl.enable(gl.DEPTH_TEST);

  gl.enable(gl.BLEND);
  gl.disable(gl.DEPTH_TEST);
  gl.blendFunc(gl.SRC_ALPHA, gl.ONE);

  //    Specify which function to use for depth buffer comparisons. It compares the
  //    value of the incoming pixel against the one stored in the depth buffer.
  //    Possible values are (from the OpenGL documentation):
  //    GL_NEVER - Never passes.
  //    GL_LESS - Passes if the incoming depth value is less than the stored depth value.
  //    GL_EQUAL - Passes if the incoming depth value is equal to the stored depth value.
  //    GL_LEQUAL - Passes if the incoming depth value is less than or equal to the stored depth value.
  //    GL_GREATER - Passes if the incoming depth value is greater than the stored depth value.
  //    GL_NOTEQUAL - Passes if the incoming depth value is not equal to the stored depth value.
  //    GL_GEQUAL - Passes if the incoming depth value is greater than or equal to the stored depth value.
  //    GL_ALWAYS - Always passes.
  //gl.depthFunc(gl.LEQUAL);

  //    Now create a shape.
  //    First create a vertex buffer in which we can store our data.
  var vertexBuffer = gl.createBuffer();
  //    Bind the buffer object to the ARRAY_BUFFER target.
  gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
  //    Specify the vertex positions (x, y, z)

  // ------------------

  setup();

  // ------------------


  vertices = new Float32Array(vertices);
  velocities = new Float32Array(velocities);

  thetaArr = new Float32Array(thetaArr);
  velThetaArr = new Float32Array(velThetaArr);
  velRadArr = new Float32Array(velRadArr);


  //    Creates a new data store for the vertices array which is bound to the ARRAY_BUFFER.
  //    The third paramater indicates the usage pattern of the data store. Possible values are
  //    (from the OpenGL documentation):
  //    The frequency of access may be one of these:
  //    STREAM - The data store contents will be modified once and used at most a few times.
  //    STATIC - The data store contents will be modified once and used many times.
  //    DYNAMIC - The data store contents will be modified repeatedly and used many times.
  //    The nature of access may be one of these:
  //    DRAW - The data store contents are modified by the application, and used as the source for
  //           GL drawing and image specification commands.
  //    READ - The data store contents are modified by reading data from the GL, and used to return
  //           that data when queried by the application.
  //    COPY - The data store contents are modified by reading data from the GL, and used as the source
  //           for GL drawing and image specification commands.
  gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.DYNAMIC_DRAW);

  //    Clear the color buffer and the depth buffer
  gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

  //    Define the viewing frustum parameters
  //    More info: http://en.wikipedia.org/wiki/Viewing_frustum
  //    More info: https://knol.google.com/k/view-frustum
  var fieldOfView = 30.0;
  var aspectRatio = canvas.width / canvas.height;
  var nearPlane = 1.0;
  var farPlane = 10000.0;
  var top = nearPlane * Math.tan(fieldOfView * Math.PI / 360.0);
  var bottom = -top;
  var right = top * aspectRatio;
  var left = -right;

  //     Create the perspective matrix. The OpenGL function that's normally used for this,
  //     glFrustum() is not included in the WebGL API. That's why we have to do it manually here.
  //     More info: http://www.cs.utk.edu/~vose/c-stuff/opengl/glFrustum.html
  var a = (right + left) / (right - left);
  var b = (top + bottom) / (top - bottom);
  var c = (farPlane + nearPlane) / (farPlane - nearPlane);
  var d = (2 * farPlane * nearPlane) / (farPlane - nearPlane);
  var x = (2 * nearPlane) / (right - left);
  var y = (2 * nearPlane) / (top - bottom);
  var perspectiveMatrix = [
    x, 0, a, 0,
    0, y, b, 0,
    0, 0, c, d,
    0, 0, -1, 0
  ];

  //     Create the modelview matrix
  //     More info about the modelview matrix: http://3dengine.org/Modelview_matrix
  //     More info about the identity matrix: http://en.wikipedia.org/wiki/Identity_matrix
  var modelViewMatrix = [
    1, 0, 0, 0,
    0, 1, 0, 0,
    0, 0, 1, 0,
    0, 0, 0, 1
  ];
  //     Get the vertex position attribute location from the shader program
  var vertexPosAttribLocation = gl.getAttribLocation(gl.program, "vertexPosition");
  //				colorLoc = gl.getVaryingLocation(gl.program, "vColor");
  //				alert("color loc : " + colorLoc );
  //     Specify the location and format of the vertex position attribute
  gl.vertexAttribPointer(vertexPosAttribLocation, 3.0, gl.FLOAT, false, 0, 0);
  //gl.vertexAttribPointer(colorLoc, 4.0, gl.FLOAT, false, 0, 0);
  //     Get the location of the "modelViewMatrix" uniform variable from the
  //     shader program
  var uModelViewMatrix = gl.getUniformLocation(gl.program, "modelViewMatrix");
  //     Get the location of the "perspectiveMatrix" uniform variable from the
  //     shader program
  var uPerspectiveMatrix = gl.getUniformLocation(gl.program, "perspectiveMatrix");
  //     Set the values
  gl.uniformMatrix4fv(uModelViewMatrix, false, new Float32Array(perspectiveMatrix));
  gl.uniformMatrix4fv(uPerspectiveMatrix, false, new Float32Array(modelViewMatrix));
  //	gl.varyingVector4fv(
  //     Draw the triangles in the vertex buffer. The first parameter specifies what
  //     drawing mode to use. This can be GL_POINTS, GL_LINE_STRIP, GL_LINE_LOOP,
  //     GL_LINES, GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN, GL_TRIANGLES, GL_QUAD_STRIP,
  //     GL_QUADS, and GL_POLYGON
  //gl.drawArrays( gl.LINES, 0, numLines );
  //gl.flush();

  //setInterval( drawScene, 1000 / 40 );
  animate();
  setTimeout(timer, 1500);
}
var count = 0;
var cn = 0;

function animate() {
  requestAnimationFrame(animate);
  drawScene();
}


function drawScene() {
  draw();

  gl.lineWidth(1);
  gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.DYNAMIC_DRAW);

  gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

  //gl.drawArrays( gl.LINES_STRIP, 0, numLines );
  gl.drawArrays(gl.LINES, 0, numLines);
  //gl.drawArrays( gl.QUAD_STRIP, 0, numLines );

  gl.flush();
}

// ===================================
function setup() {
  setup2();
}


function draw() {
  switch (drawType) {
    case 0:
      draw0();
      break;
    case 1:
      draw1();
      break;
    case 2:
      draw2();
      break;
  }
}

// ===================================

function setup1() {

  vertices = [];
  velThetaArr = [];
  velRadArr = [];
  ratio = cw / ch;
  velocities = [];

  // -------------------------------

  for (var i = 0; i < numLines; i++) {

    var rad = Math.random() * 2 + .5;
    var theta = Math.random() * Math.PI * 2;
    var velTheta = Math.random() * Math.PI * 2;

    vertices.push(rad * Math.cos(theta), rad * Math.sin(theta), 1.83);//(Math.random() * 2 - 1)*ratio, Math.random() * 2 - 1, 1.83 );
    vertices.push(rad * Math.cos(theta), rad * Math.sin(theta), 1.83);

    velocities.push((Math.random() * 2 - 1) * .05, (Math.random() * 2 - 1) * .05, .93 + Math.random() * .02);
    velThetaArr.push(velTheta);
    velRadArr.push(rad);

  }

}

// -------------------------------

function setup2() {

  vertices = [];
  velThetaArr = [];
  velRadArr = [];
  ratio = cw / ch;
  velocities = [];
  thetaArr = [];
  freqArr = [];
  boldRateArr = [];

  // -------------------------------

  for (var ii = 0; ii < numLines; ii++) {
    var rad = ( 0.1 + .2 * Math.random() );
    var theta = Math.random() * Math.PI * 2;
    var velTheta = Math.random() * Math.PI * 2 / 30;
    var freq = Math.random() * 0.12 + 0.03;
    var boldRate = Math.random() * .04 + .01;
    var randomPosX = (Math.random() * 2  - 1) * window.innerWidth / window.innerHeight;
    var randomPosY = Math.random() * 2 - 1;

    vertices.push(rad * Math.cos(theta), rad * Math.sin(theta), 1.83);
    vertices.push(rad * Math.cos(theta), rad * Math.sin(theta), 1.83);

    thetaArr.push(theta);
    velThetaArr.push(velTheta);
    velRadArr.push(rad);
    freqArr.push(freq);
    boldRateArr.push(boldRate);


    randomTargetXArr.push(randomPosX);
    randomTargetYArr.push(randomPosY);
  }

  freqArr = new Float32Array(freqArr);

}

// -------------------------------


// ===================================

function draw0() {

  var i, n = vertices.length, p, bp;
  var px, py;
  var pTheta;
  var rad;
  var num;
  var targetX, targetY;

  for (i = 0; i < numLines * 2; i += 2) {
    count += .3;
    bp = i * 3;

    vertices[bp] = vertices[bp + 3];
    vertices[bp + 1] = vertices[bp + 4];

    num = parseInt(i / 2);
    targetX = randomTargetXArr[num];
    targetY = randomTargetYArr[num];


    px = vertices[bp + 3];
    px += (targetX - px) * (Math.random() * .04 + .06);
    vertices[bp + 3] = px;


    //py = (Math.sin(cn) + 1) * .2 * (Math.random() * .5 - .25);
    py = vertices[bp + 4];
    py += (targetY - py) * (Math.random() * .04 + .06);
    vertices[bp + 4] = py;

  }
}

// -------------------------------

function draw1() {

  var i, n = vertices.length, p, bp;
  var px, py;
  var pTheta;
  var rad;
  var num;
  var targetX, targetY;

  for (i = 0; i < numLines * 2; i += 2) {
    count += .3;
    bp = i * 3;

    vertices[bp] = vertices[bp + 3];
    vertices[bp + 1] = vertices[bp + 4];

    num = parseInt(i / 2);
    pTheta = thetaArr[num];
    rad = velRadArr[num];

    pTheta = pTheta + velThetaArr[num];
    thetaArr[num] = pTheta;

    targetX = rad * Math.cos(pTheta);
    targetY = rad * Math.sin(pTheta);

    px = vertices[bp + 3];
    px += (targetX - px) * (Math.random() * .1 + .1);
    vertices[bp + 3] = px;


    //py = (Math.sin(cn) + 1) * .2 * (Math.random() * .5 - .25);
    py = vertices[bp + 4];
    py += (targetY - py) * (Math.random() * .1 + .1);
    vertices[bp + 4] = py;
  }
}

// -------------------------------

function draw2() {
  cn += .1;

  var i, n = vertices.length, p, bp;
  var px, py;
  var pTheta;
  var rad;
  var num;

  for (i = 0; i < numLines * 2; i += 2) {
    count += .3;
    bp = i * 3;
    // copy old positions

    vertices[bp] = vertices[bp + 3];
    vertices[bp + 1] = vertices[bp + 4];

    num = parseInt(i / 2);
    pTheta = thetaArr[num];

    rad = velRadArr[num];// + Math.cos(pTheta + i * freqArr[i]) *  boldRateArr[num];

    pTheta = pTheta + velThetaArr[num];
    thetaArr[num] = pTheta;

    px = vertices[bp + 3];
    px = rad * Math.cos(pTheta) * 0.1 + px;
    vertices[bp + 3] = px;


    //py = (Math.sin(cn) + 1) * .2 * (Math.random() * .5 - .25);
    py = vertices[bp + 4];

    py = py + rad * Math.sin(pTheta) * 0.1;
    //p *= ( Math.random() -.5);
    vertices[bp + 4] = py;
  }
}

// -------------------------------


function timer() {
  drawType = (drawType + 1) % 3;

  setTimeout(timer, 1500);
}
</script>
 </BODY>
</HTML>

光看不点赞,罚款50

转载请注明出处或者链接地址:https://www.qianduange.cn//article/9871.html
标签
pycharm
评论
会员中心 联系我 留言建议 回顶部
复制成功!