Confetti

from codepen https://codepen.io/wakana-k

by Angelica

HTML

<!--
confetti
Copyright (c) 2023 by Wakana Y.K. (https://codepen.io/wakana-k/pen/gOqqWdY)

Luxurious version : https://codepen.io/wakana-k/pen/mdvoQaV
-->
<!-- using three.js -->
<h1>ANGELICA'S SITE</h1>
<script async src="https://ga.jspm.io/npm:[email protected]/dist/es-module-shims.js" crossorigin="anonymous"></script>
<script type="importmap">
  {
    "imports": {      
      "three": "https://unpkg.com/[email protected]/build/three.module.js",
      "three/addons/": "https://unpkg.com/[email protected]/examples/jsm/"
    }
  }
</script>

CSS

@import url("https://fonts.googleapis.com/css2?family=Asap&display=swap");
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}
html,
body {
  background: radial-gradient(
    circle farthest-corner,
    #bdbdbd,
    #404040 100%
  );
  overscroll-behavior-x: none;
  overscroll-behavior-y: none;
}
body {
  font-family: "Asap", sans-serif;
  position: relative;
  width: 100vw;
  min-height: 100vh;
  text-align: center;
  overflow-x: hidden;
  color: white;
  display: flex;
  align-items: center;
  justify-content: center;
}
h1 {
  font-size: max(35px, 7vw);
  text-shadow: 1px 1px black;
  mix-blend-mode: overlay;
  z-index: 1;
}
canvas {
  -moz-user-select: none;
  -webkit-user-select: none;
  -ms-user-select: none;
  user-select: none;
  position: fixed;
  width: 100vw;
  height: 100vh;
  top: 0;
  left: 0;
  z-index: 0;
}

JavaScript

/*!
confetti
Copyright (c) 2023 by Wakana Y.K. (https://codepen.io/wakana-k/pen/gOqqWdY)

Luxurious version : https://codepen.io/wakana-k/pen/mdvoQaV
*/
"use strict";
import * as THREE from "three";
import { OrbitControls } from "three/addons/controls/OrbitControls.js";

console.clear();

(function () {
  const worldRadius = 5;
  const confettiSize = 0.07;
  const confettiNum = 3000;
  const rotateRange_x = Math.PI / 30;
  const rotateRange_y = Math.PI / 50;
  const speed_y = 0.01;
  const speed_x = 0.003;
  const speed_z = 0.005;

  let camera, scene, renderer, controls;
  let confettiMesh;
  const dummy = new THREE.Object3D();
  const matrix = new THREE.Matrix4();
  const color = new THREE.Color();

  init();

  function init() {
    //
    camera = new THREE.PerspectiveCamera(
      35,
      window.innerWidth / window.innerHeight,
      1,
      worldRadius * 3
    );
    camera.position.z = worldRadius * Math.sqrt(2);
    //camera.position.set(-1, 1.5, 2);
    //camera.lookAt(0, 0.5, 0);

    scene = new THREE.Scene();
    //scene.background = new THREE.Color(0x666666);

    /////////////////////////////////
    // Confetti
    /////////////////////////////////
    // choose random color
    function getRandomColor() {
      let saturation = 100;
      let lightness = 50;
      const colors = [
        "#fa8085",
        "#fd9d7c",
        "#fbd97d",
        "#a3d963",
        "#2ec7d6",
        "#9c70cc",
        "#fd7ab0"
      ];
      return colors[Math.floor(Math.random() * colors.length)];
      //return color.setHex(0xffffff * Math.random());
    }
    //
    const confettiGeometry = new THREE.PlaneGeometry(
      confettiSize / 2,
      confettiSize
    );
    const confettiMaterial = new THREE.MeshBasicMaterial({
      color: 0xffffff,
      side: THREE.DoubleSide
    });
    confettiMesh = new THREE.InstancedMesh(
      confettiGeometry,
      confettiMaterial,
      confettiNum
    );

    // set random position and rotation
    for (let i = 0; i...