LOADING...

Preview

Pen ID
Unlock Campus Themeforest adv

 

Code
CSS
  html,
  body {
    width: 100%;
    height: 100%;
    margin: 0;
    overflow: hidden;
    background: black;
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen,
    Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif;
    font-size: 14px;
    color: #fff;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    -webkit-user-select: none;
       -moz-user-select: none;
        -ms-user-select: none;
            user-select: none;
    -webkit-tap-highlight-color: transparent;
  }

  canvas {
    position: fixed;
    width: 100%;
    height: 100%;
  }

  footer {
    position: fixed;
    right: 0;
    top: 0;
    right: 0;
    padding: 10px 10px;
    text-align: right;
    width: 240px;
  }

  a {
    display: inline-block;
    margin-left: 2px;
    padding: 2px 4px;
    color: rgba(52, 52, 54, 1);
    text-decoration: none;
    background-color: #fcd000;
    border-radius: 4px;
    opacity: 1;
    -webkit-transition: opacity 0.2s;
    transition: opacity 0.2s;
  }

  img {
    width: 300px;
    max-width: 30%;
    position: fixed;
    -webkit-transform: translate3d(0%, -50%, 0px);
            transform: translate3d(0%, -50%, 0px);
    top: 50%;
    left: 50%;
    pointer-events: none;
  }

  section {
    -webkit-transition: 0.4s ease;
    transition: 0.4s ease;
    opacity: 0;
    visibility: hidden;
    will-change: opacity, visibility;
    position: fixed;
    width: 100%;
    height: 100%;
    top: 0;
    left: 0;
  }

  button {
    -webkit-appearance: none;
    padding: 12px 24px;
    border-radius: 0;
    position: fixed;
    left: 50%;
    bottom: 24px;
    -webkit-transform: translateX(-50%);
            transform: translateX(-50%);
    text-transform: uppercase;
    letter-spacing: 2px;
    color: white;
    background: black;
    border: 1px solid white;
    cursor: none;
  }

  .output button {
    cursor: pointer;
  }

  button:focus,
  button:hover {
    color: black;
    background: white;
  }

  .input {
    cursor: none;
    opacity: 1;
    visibility: visible;
  }
JS
const segments = [];
const points = [];

const input = document.querySelector('.input');
const output = document.querySelector('.output');

// Input
{
  const canvas = input.querySelector('canvas');
  const image = input.querySelector('img');

  const context = canvas.getContext('2d');
 
  let current = [];
  let hold = false;
 
  const resize = () => {
   canvas.width = canvas.clientWidth * window.devicePixelRatio;
   canvas.height = canvas.clientHeight * window.devicePixelRatio;
  
   context.lineWidth = window.devicePixelRatio === 1 ? 1 : 3;
   context.strokeStyle = '#FEFEFE';
   
   segments.length = 0;
   points.length = 0;
  }
  
  resize();
  window.addEventListener('resize', resize);
 
  const midPointBtw = (p1, p2) => ({
    x: p1.x + ((p2.x - p1.x) / 2),
    y: p1.y + ((p2.y - p1.y) / 2),
  });

  const getCoordinatesFromEvent = (event) => {
    const touch = typeof event.changedTouches !== 'undefined';
    return {
      x: touch ? event.changedTouches[0].clientX : event.clientX,
      y: touch ? event.changedTouches[0].clientY : event.clientY,
    };
  };

  const drawSegments = (event) => {
    const coords = getCoordinatesFromEvent(event);
    current.push({
      x: coords.x * window.devicePixelRatio,
      y: coords.y * window.devicePixelRatio,
    });
    context.beginPath();
    context.moveTo(current[0].x, current[0].y);
    for (let i = 0; i < current.length - 1; i += 1) {
      const midPoint = midPointBtw(current[i], current[i + 1]);
      context.quadraticCurveTo(current[i].x, current[i].y, midPoint.x, midPoint.y);
    }
    context.stroke();
  };

  const start = (event) => {
    const coords = getCoordinatesFromEvent(event);
    hold = true;
    current = [{
      x: coords.x * window.devicePixelRatio,
      y: coords.y * window.devicePixelRatio,
    }];
  };

  const move = (event) => {
    const coords = getCoordinatesFromEvent(event);
    image.style.left = '0px';
    image.style.top = '0px';
    image.style.transform = `translate3d(${coords.x}px, ${coords.y}px, 0)`;
    if (hold) drawSegments(event);
  };

  const end = () => {
    hold = false;
    segments.push(current);
  };

  canvas.addEventListener('mousedown', start);
  canvas.addEventListener('touchstart', start);

  input.addEventListener('mousemove', move);
  input.addEventListener('touchmove', move);

  canvas.addEventListener('mouseup', end);
  canvas.addEventListener('touchend', end);
}

// Output
{
  const canvas = output.querySelector('canvas');

  const initialize = () => {
    const pixelRatio = window.devicePixelRatio;
    const multiplier = points.length;
    const duration = 0.4;
    const geometry = [{ x: 0, y: 0, z: 0 }];
    const pointSize = (4).toFixed(1);

    let step = 0;
    setTimeout(() => {
      step = 0.004;
    }, 400);

    const offset = 0.5;
    const attributes = [
      {
        name: 'aPositionStart',
        data: (i, total) => [
          points[i].x,
          points[i].y,
          0.2 - ((i / total) * 0.4),
        ],
      },
      {
        name: 'aControlPointOne',
        data: (i, total) => [
          points[i].x + getRandom(offset),
          points[i].y + getRandom(offset),
          0.2 - ((i / total) * 0.4) + getRandom(offset),
        ],
      },
      {
        name: 'aControlPointTwo',
        data: (i, total) => [
          points[i].x + getRandom(offset),
          points[i].y + getRandom(offset),
          0.2 - ((i / total) * 0.4) + getRandom(offset),
        ],
      },
      {
        name: 'aPositionEnd',
        data: (i, total) => [
          points[i].x,
          points[i].y,
          0.2 - ((i / total) * 0.4),
        ],
      },
      {
        name: 'aOffset',
        data: i => [i * ((1 - duration) / (multiplier - 1))],
      },
      {
        name: 'aColor',
        data: (i, total) => getHSL(i / total, 0.5, 0.5),
      },
    ];

    const uniforms = [
      {
        name: 'uProgress',
        type: 'float',
        value: 0.0,
      },
    ];

    const vertexShader = `
    attribute vec3 aPositionStart;
    attribute vec3 aControlPointOne;
    attribute vec3 aControlPointTwo;
    attribute vec3 aPositionEnd;
    attribute float aOffset;
    attribute vec3 aColor;

    uniform float uProgress;
    uniform mat4 uMVP;

    varying vec3 vColor;

    vec3 bezier4(vec3 a, vec3 b, vec3 c, vec3 d, float t) {
      return mix(mix(mix(a, b, t), mix(b, c, t), t), mix(mix(b, c, t), mix(c, d, t), t), t);
    }

    float easeInOutQuint(float t){
      return t < 0.5 ? 16.0 * t * t * t * t * t : 1.0 + 16.0 * (--t) * t * t * t * t;
    }

    void main () {
      float tProgress = easeInOutQuint(min(1.0, max(0.0, (uProgress - aOffset)) / ${duration}));
      vec3 newPosition = bezier4(aPositionStart, aControlPointOne, aControlPointTwo, aPositionEnd, tProgress);
      gl_PointSize = ${pointSize};
      gl_Position = uMVP * vec4(newPosition, 1.0);
      vColor = aColor;
    }
  `;

    const fragmentShader = `
    precision mediump float;

    varying vec3 vColor;

    void main() {
      //  vec2 pc = 2.0 * gl_PointCoord - 1.0;
      //  gl_FragColor = vec4(vColor, 1.0 - dot(pc, pc));
      gl_FragColor = vec4(vColor, 1.0);
    }
  `;

    const onSetup = (gl) => {
      gl.blendFunc(gl.SRC_ALPHA, gl.ONE);
      gl.enable(gl.BLEND);
    };

    const onRepeat = () => {
      rotateY(uniforms[uniforms.length - 1].value, 0.002);
      if (uniforms[0].value > 1) {
        uniforms[0].value = 0;
      }
      uniforms[0].value += step;
    };

    const options = {
      onSetup,
      onRepeat,
      pixelRatio,
    };

    starlings(
      canvas,
      geometry,
      multiplier,
      attributes,
      uniforms,
      vertexShader,
      fragmentShader,
      options,
    );
  };

  const getRandom = value => Math.random() * value - value / 2;

  const rotateY = (matrix, angle) => {
    const sin = Math.sin(angle);
    const cos = Math.cos(angle);
    const clone = JSON.parse(JSON.stringify(matrix));

    matrix[0] = clone[0] * cos - clone[8] * sin;
    matrix[1] = clone[1] * cos - clone[9] * sin;
    matrix[2] = clone[2] * cos - clone[10] * sin;
    matrix[3] = clone[3] * cos - clone[11] * sin;
    matrix[8] = clone[0] * sin + clone[8] * cos;
    matrix[9] = clone[1] * sin + clone[9] * cos;
    matrix[10] = clone[2] * sin + clone[10] * cos;
    matrix[11] = clone[3] * sin + clone[11] * cos;
  };

  const h2r = (p, q, t) => {
    if (t < 0) t += 1;
    if (t > 1) t -= 1;
    if (t < 1 / 6) return p + (q - p) * 6 * t;
    if (t < 1 / 2) return q;
    if (t < 2 / 3) return p + (q - p) * 6 * (2 / 3 - t);
    return p;
  };

  const getHSL = (h, s, l) => {
    h = (h % 1 + 1) % 1;
    s = Math.max(0, Math.min(1, s));
    l = Math.max(0, Math.min(1, l));
    if (s === 0) return [l, l, l];
    const p = l <= 0.5 ? l * (1 + s) : l + s - l * s;
    const q = 2 * l - p;
    return [h2r(q, p, h + 1 / 3), h2r(q, p, h), h2r(q, p, h - 1 / 3)];
  };

  const ratio = window.innerWidth / window.innerHeight;
  const halfWidth = (window.innerWidth * devicePixelRatio) / 2;
  const halfHeight = (window.innerHeight * devicePixelRatio) / 2;

  document.querySelector('.create').addEventListener('click', () => {
    points.length = 0;
    segments.map(segment => segment.map((point) => {
      for (let i = 0; i < 100; i += 1) {
        const x = (((point.x - halfWidth) / halfWidth) * ratio).toFixed(4) * 1;
        const y = (((point.y - halfHeight) / halfHeight)).toFixed(4) * -1;
        points.push({ x, y });
      }
    }));
    input.style.opacity = '0';
    input.style.visibility = 'hidden';
    setTimeout(() => {
      output.style.opacity = '1';
      output.style.visibility = 'visible';
      initialize();
    }, 600);
  });

  document.querySelector('.reset').addEventListener('click', () => {
    input
      .querySelector('canvas')
      .getContext('2d')
      .clearRect(0, 0, window.innerWidth * window.devicePixelRatio, window.innerHeight * window.devicePixelRatio);
    output.style.opacity = '0';
    output.style.visibility = 'hidden';
    setTimeout(() => {
      segments.length = 0;
      points.length = 0;
      input.style.opacity = '1';
      input.style.visibility = 'visible';
    }, 600);
  });
}

Description

This time it's up to you, draw and let the particles take over. Inspired by a project we did just over two years ago.
Term
Wed, 12/06/2017 - 19:43

Related Codes

Pen ID
Pen ID
Pen ID
Square Adv