Анимация абстракции

151
25 ноября 2020, 21:40

Есть вот такая абстракция

знаю что через canvas такое анимируется, но не силен в данной области, может кто видел или знает как анимировать?

Answer 1

Примерная анимация на Three.js

var planeVertShader = ` 
#define PI 3.1415926 
uniform float time; 
uniform float amplitude; 
uniform float waveLength; 
uniform vec3 pos; 
uniform float timeSpeed; 
uniform float planeHeight; 
uniform float initRotation; 
uniform float speedRotation; 
varying vec3 varPos; 
void main() { 
 
  vec3 p = position + pos + vec3(0., .1, 0.); 
  float wLength = 1. / waveLength; 
  float heightNormal = position.y / planeHeight; 
  float oneRound = heightNormal * PI * 4.; 
  //вращение 
  p.y += sin(p.x * wLength + time) * cos(p.z * wLength  + time) * amplitude; 
  p.x = cos(-time * speedRotation + oneRound + initRotation) * position.x; 
  p.z = sin(-time * speedRotation + oneRound + initRotation) * position.x; 
 
  //скручивание 
  p.x += cos(-time * speedRotation + oneRound) * heightNormal * 5.; 
  p.z += sin(-time * speedRotation + oneRound) * heightNormal * 5.; 
 
  p += pos + vec3(0., .1, 0.); 
 
  varPos = position; 
 
  vec4 mvPosition = modelViewMatrix * vec4( p, 1.0 ); 
  gl_Position = projectionMatrix * mvPosition; 
} 
`; 
var planeFragShader = ` 
void main() { 
  gl_FragColor = vec4(0.366,0.048,0.515,1.000); 
} 
`; 
 
var scene = new THREE.Scene(); 
var camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 1, 1000); 
camera.position.set(0, 25, 150); 
camera.rotation.set(0, 0, 1.57); 
var renderer = new THREE.WebGLRenderer({ 
    antialias: true 
}); 
renderer.setClearColor(0x000000); 
renderer.setSize(window.innerWidth, window.innerHeight); 
document.body.appendChild(renderer.domElement); 
window.addEventListener('resize', function () { 
 
    camera.aspect = window.innerWidth / window.innerHeight; 
    camera.updateProjectionMatrix(); 
 
    renderer.setSize(window.innerWidth, window.innerHeight); 
 
}, false); 
 
// plane 
var planes = []; 
var planeHeight = 125; 
var planeWidth = 15; 
var planeGeom = new THREE.PlaneBufferGeometry(planeWidth, planeHeight, 15, 100); 
planeGeom.translate(4, 0, 0); 
for (let i = 0; i < 2; i++) { 
    let pos = new THREE.Vector3(0, 10, 110); 
 
    let plane = new THREE.LineSegments(planeGeom, new THREE.ShaderMaterial({ 
        uniforms: { 
            time: { 
                value: 0 
            }, 
            amplitude: { 
                value: 5 
            }, 
            waveLength: { 
                value: Math.PI * 5 
            }, 
            pos: { 
                value: pos 
            }, 
            timeSpeed: { 
                value: THREE.Math.randFloat(Math.PI * .5, Math.PI) 
            }, 
            planeHeight: { 
                value: planeHeight 
            }, 
            initRotation: { 
                value: THREE.Math.randFloat(0, Math.PI) 
            }, 
            speedRotation: { 
                value: THREE.Math.randFloat(Math.PI * 0.5, Math.PI) 
            } 
        }, 
        vertexShader: planeVertShader, 
        fragmentShader: planeFragShader 
    })); 
    scene.add(plane); 
    planes.push(plane) 
} 
 
var clock = new THREE.Clock(); 
var t = 0; 
var delta = 0; 
render(); 
 
function render() { 
 
    requestAnimationFrame(render); 
    delta = clock.getDelta(); 
    t += delta; 
    planes.forEach(sw => { 
        sw.material.uniforms.time.value = t 
    }); 
    renderer.render(scene, camera); 
 
}
body { 
    overflow: hidden; 
    margin: 0; 
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/88/three.min.js"></script> 
<div></div>

Answer 2

WebGL. Поверхность задана при помощи signed distance, на нее наложен математический шум, который сдвигается со временем. Поверхность находится при помощи raymarch, все это дело вычисляется во фрагментном шейдере.

let canvas = document.querySelector('canvas'); 
let gl = canvas.getContext('webgl'); 
let pid = gl.createProgram(); 
 
shader(` 
  attribute vec2 coords; 
  void main(void) { 
    gl_Position = vec4(coords.xy, 0.0, 1.0); 
  } 
`, gl.VERTEX_SHADER); 
 
shader(` 
  precision highp float;  
  uniform vec4 mr;  
  uniform float time;  
 
  #define rot(a) mat2(cos(a),-sin(a),sin(a),cos(a)) 
 
  #define hash31(p) fract(sin(dot(p,vec3(127.1,311.7, 74.7)))*43758.5453123) 
 
  float noise3(vec3 p) { 
      vec3 i = floor(p); 
      vec3 f = fract(p); f = f*f*(3.-2.*f);  
      return mix( mix( mix(hash31(i+vec3(0,0,0)), 
                           hash31(i+vec3(1,0,0)),f.x), 
                       mix(hash31(i+vec3(0,1,0)), 
                           hash31(i+vec3(1,1,0)),f.x), f.y),  
                  mix( mix(hash31(i+vec3(0,0,1)), 
                           hash31(i+vec3(1,0,1)),f.x), 
                       mix(hash31(i+vec3(0,1,1)), 
                           hash31(i+vec3(1,1,1)),f.x), f.y), f.z); 
  } 
 
  float fbm3(vec3 p) { 
      float v = 0.,  a = .5; 
      mat2 R = rot(.37); 
      for (int i = 0; i < 2; i++) { 
          p *= 2.; 
          a /= 2.; 
          p.xy *= R;  
          p.yz *= R; 
          v += a * noise3(p); 
      } 
      return v; 
  } 
 
  float map( in vec3 pos ){ 
       
      return pos.y + fbm3(vec3(pos.x+time,pos.yz)); 
  } 
 
  float rayMarch( in vec3 ro, in vec3 rd, float tmax ){ 
      float t = 0.0; 
      float h = (1.0-ro.y)/rd.y; 
      for( int i=0; i<10; i++ ){         
          vec3 pos = ro + t*rd; 
          float h = map( pos ); 
          if( h<0.001 || t>tmax ) break; 
          t += h; 
      } 
      return t;     
  } 
 
  vec3 render( in vec3 ro, in vec3 rd ) { 
      vec3 col = vec3(0.);  
      float t = rayMarch( ro, rd, 10. );     
      vec3 pos = ro + t*rd; 
      vec2 scp = sin(23.*pos.xz); 
      col += 2.0*exp(-5.0*abs(scp.x)); 
      col += 2.0*exp(-5.0*abs(scp.y)); 
      return col*0.5*exp(-0.1*t*t); 
  } 
 
  mat3 setCamera( in vec3 ro, in vec3 rt, in float cr ) { 
    vec3 cw = normalize(rt-ro); 
    vec3 cp = vec3(sin(cr), cos(cr),0.0); 
    vec3 cu = normalize( cross(cw,cp) ); 
    vec3 cv = normalize( cross(cu,cw) ); 
    return mat3( cu, cv, -cw ); 
  } 
 
  void main(void) { 
    vec2 uv = gl_FragCoord.xy/mr.zw; 
	  vec2 p = uv-0.5; 
    float an = time*0.5 + 6.0*mr.x/mr.z; 
    vec3 ro = vec3( 2.0*cos(an), 1.0, 2.0*sin(an) ); 
    vec3 rt = vec3( 1.0, 0.0, 0.0 ); 
    mat3 cam = setCamera( ro, rt, 0.35 ); 
    vec3 rd = normalize( cam * vec3( p, -1.0) ); 
    vec3 c = render( ro, rd )*vec3( 0.3, 0.4, 0.8 ); 
    gl_FragColor = vec4(c, 1.0 );  
  } 
 
`, gl.FRAGMENT_SHADER); 
 
gl.linkProgram(pid); 
gl.useProgram(pid); 
 
let array = new Float32Array([-1,  3, -1, -1, 3, -1]); 
gl.bindBuffer(gl.ARRAY_BUFFER, gl.createBuffer()); 
gl.bufferData(gl.ARRAY_BUFFER, array, gl.STATIC_DRAW); 
 
let coords = gl.getAttribLocation(pid, "coords"); 
gl.vertexAttribPointer(coords, 2, gl.FLOAT, false, 0, 0); 
gl.enableVertexAttribArray(coords); 
 
let mr = gl.getUniformLocation(pid, 'mr'); 
let time = gl.getUniformLocation(pid, 'time'); 
 
let x = 0, y = 0; 
let changeCenter = e => { 
  e = e.touches ? e.touches[0] : e; 
  let z = window.getComputedStyle(canvas).zoom || 1; 
  let d = document.documentElement; 
  x = (e.clientX + d.scrollLeft - canvas.offsetLeft*z) / z; 
  y = (e.clientY + d.scrollTop - canvas.offsetTop*z) / z 
} 
 
window.addEventListener('mousemove', e => changeCenter(e)); 
window.addEventListener('touchmove', e => changeCenter(e)); 
window.addEventListener('resize', resize); 
 
resize(); 
 
function draw(t) { 
  gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight); 
  gl.clearColor(0, 0, 0, 0); 
  gl.uniform4f(mr, x, y, gl.drawingBufferWidth, gl.drawingBufferHeight); 
  gl.uniform1f(time, t/1000); 
  gl.drawArrays(gl.TRIANGLES, 0, 3); 
  requestAnimationFrame(draw) 
} 
 
function shader(src, type) { 
  let sid = gl.createShader(type); 
  gl.shaderSource(sid, src); 
  gl.compileShader(sid); 
  var message = gl.getShaderInfoLog(sid); 
  gl.attachShader(pid, sid); 
  if (message.length > 0) { 
    console.log(src.split('\n').map(function (str, i) { 
      return ("" + (1 + i)).padStart(4, "0") + ": " + str 
    }).join('\n')); 
    throw message; 
  } 
} 
 
function resize(){ 
  canvas.width = window.innerWidth; 
  canvas.height = window.innerHeight; 
  draw(); 
}
<body style="margin:0; overflow:hidden"><canvas/></body>

READ ALSO
weppack output.publicPath

weppack output.publicPath

Имею такую настройку в конфиге webpack:

81
метод unshift не работает нужным образом

метод unshift не работает нужным образом

Может есть какие то идеи, почему unshift добавляем в конец массива, а не в начало? И сортировка что то не помогает

116