top of page

HTML/CSS/Javascript

Here is a collection of all the projects and code I wrote using HTML, CSS, and Javascript. I have included here my internship work as well as a class project.

Three.js

This script uses a library called Three.js to create a 3D environment on a website. Pick'd in Columbus asked me to create the website for my internship with the company in the summer of 2021. There are many methods being utilized from Three.js, as well as a physics library system called CANNON.

HTML

<!DOCTYPE html>

<html lang="en">

  <head>

    <meta charset="UTF-8" />

    <meta name="viewport" content="width=device-width, initial-scale=1.0" />

    <title>Pic'd Test</title>

  </head>

  <body>

    <a href="javascript:void(0)" id="openBtn" onclick="openNav()">

      <div></div>

      <div></div>

      <div></div>

    </a>

 

    <div id="mySideNav" class="sideNav">

      <a href="javascript:void(0)" class="closeBtn" onclick="closeNav()">

        <div></div>

        <div></div>

        <div></div

      ></a>

      <div id="container">

        <h1><u>Flowers</u></h1>

        <br />

 

        <h2><i>Roses</i></h2>

        <a class="link white" id="whiteRose">White</a>

        <a class="link red" id="redRose">Red</a>

        <a class="link yellow" id="yellowRose">Yellow</a>

        <a class="link lavender" id="lavenderRose"> Lavender </a>

        <a class="link orange" id="orangeRose">Orange</a>

        <a class="link pink" id="pinkRose">Pink</a>

        <br />

 

        <h2><i>Carnations</i></h2>

        <a class="link white" id="whiteCarnation">White</a>

        <a class="link red" id="redCarnation">Red</a>

        <a class="link yellow" id="yellowCarnation">Yellow</a>

        <a class="link pink" id="pinkCarnation">Pink</a>

        <br />

 

        <h2><i>Lillies</i></h2>

        <a class="link white" id="whiteLilly">White</a>

        <a class="link yellow" id="yellowLilly">Yellow</a>

        <a class="link pink" id="pinkLilly">Pink</a>

        <br />

 

        <h2><i>Daisies</i></h2>

        <a class="link white" id="whiteDaisy">White</a>

        <a class="link red" id="gerberaDaisy">Gerbera</a>

        <a class="link yellow" id="yellowDaisy">Yellow</a>

        <a class="link pink" id="pinkDaisy">Pink</a>

        <br />

 

        <h2><i>Delphinium</i></h2>

        <a class="link white" id="whiteDelphinium">White</a>

        <a class="link blue" id="blueDelphinium">Blue</a>

        <a class="link lavender" id="lavenderDelphinium"> Lavender </a>

        <br />

 

        <h2><i>Sunflower</i></h2>

        <a class="link yellow" id="sunflower">Sunflower</a>

        <br />

 

        <h1><u>Foliage</u></h1>

        <a class="link green" id="largeFoliage">Large</a>

        <a class="link green" id="mediumFoliage">Medium</a>

        <a class="link green" id="smallFoliage">Small</a>

        <br />

        <br />

        <br />

        <br />

      </div>

    </div>

 

    <script>

      function openNav() {

        document.getElementById("mySideNav").style.width = "400px";

        document.getElementById("openBtn").style.display = "none";

      }

 

      function closeNav() {

        document.getElementById("mySideNav").style.width = "0";

        document.getElementById("openBtn").style.display = "block";

      }

    </script>

 

    <canvas class="webgl"></canvas>

  </body>

</html>

Javascript

import "./style.css";

 

import * as THREE from "three";

 

import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js";

import { DRACOLoader } from "three/examples/jsm/loaders/DRACOLoader.js";

 

import * as CANNON from "cannon-es";

 

import { EffectComposer } from "three/examples/jsm/postprocessing/EffectComposer.js";

import { RenderPass } from "three/examples/jsm/postprocessing/RenderPass.js";

import { ShaderPass } from "three/examples/jsm/postprocessing/ShaderPass.js";

import { SMAAPass } from "three/examples/jsm/postprocessing/SMAAPass.js";

import { UnrealBloomPass } from "three/examples/jsm/postprocessing/UnrealBloomPass.js";

 

/**

 * Starting Variables

 */

const objectsToUpdate = [];

const timerQueue = [];

 

/**

 * Canvas

 */

const canvas = document.querySelector("canvas.webgl");

 

/**

 * Scene

 */

const scene = new THREE.Scene();

 

/**

 * Loaders

 */

const dracoLoader = new DRACOLoader();

dracoLoader.setDecoderPath("/draco/");

 

const gltfLoader = new GLTFLoader();

gltfLoader.setDRACOLoader(dracoLoader);

 

/**

 * Update all materials

 */

const updateAllMaterials = () => {

  scene.traverse((child) => {

    if (child instanceof THREE.Mesh) {

      child.castShadow = true;

    }

    if ((child instanceof THREE.Mesh) & (child.name != "Vase")) {

      child.receiveShadow = true;

    }

  });

};

 

/**

 * Sizes

 */

const sizes = {

  width: window.innerWidth,

  height: window.innerHeight,

};

 

window.addEventListener("resize", () => {

  // // Update sizes

  sizes.width = window.innerWidth;

  sizes.height = window.innerHeight;

 

  // Update camera

  camera.aspect = sizes.width / sizes.height;

  camera.updateProjectionMatrix();

 

  // Update renderer

  renderer.setSize(sizes.width, sizes.height);

  renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));

 

  // Update effect composer

  effectComposer.setPixelRatio(Math.min(window.devicePixelRatio, 2));

  effectComposer.setSize(sizes.width, sizes.height);

});

 

/**

 * Camera

 */

 

const camera = new THREE.PerspectiveCamera(

  75,

  sizes.width / sizes.height,

  0.1,

  100

);

camera.position.x = 0;

camera.position.y = 1;

camera.position.z = -3;

camera.rotation.x = Math.PI / 8;

camera.rotation.y = Math.PI;

 

camera.lookAt(new THREE.Vector3(0, 0, 0));

scene.add(camera);

 

// Cursor

const cursor = {

  x: 0,

  y: 0,

};

window.addEventListener("mousemove", (event) => {

  cursor.x = event.clientX / sizes.width - 0.5;

  cursor.y = event.clientY / sizes.height - 0.5;

});

 

/**

 * Physics

 */

// World

const world = new CANNON.World();

world.broadphase = new CANNON.SAPBroadphase(world);

world.allowSleep = true;

world.gravity.set(0, -9.82, 0);

 

// Material

const defaultMaterial = new CANNON.Material("default");

const defaultContactMaterial = new CANNON.ContactMaterial(

  defaultMaterial,

  defaultMaterial,

  {

    friction: 1,

    restitution: 0.1,

  }

);

world.defaultContactMaterial = defaultContactMaterial;

 

/**

 * Physics Models

 */

// Vase

const vaseBottomShape = new CANNON.Plane();

const vaseBottomBody = new CANNON.Body();

vaseBottomBody.mass = 0;

vaseBottomBody.material = defaultMaterial;

vaseBottomBody.quaternion.setFromAxisAngle(

  new CANNON.Vec3(-1, 0, 0),

  Math.PI * 0.5

);

vaseBottomBody.addShape(vaseBottomShape);

 

const vaseWallShapeFront = new CANNON.Box(new CANNON.Vec3(0.7, 0.7, 0.01));

const vaseWallFrontBody = new CANNON.Body();

vaseWallFrontBody.mass = 0;

vaseWallFrontBody.material = defaultMaterial;

vaseWallFrontBody.addShape(vaseWallShapeFront);

 

const vaseWallShapeBack = new CANNON.Box(new CANNON.Vec3(0.7, 0.7, 0.01));

const vaseWallBackBody = new CANNON.Body();

vaseWallBackBody.mass = 0;

vaseWallBackBody.material = defaultMaterial;

vaseWallBackBody.quaternion.setFromAxisAngle(

  new CANNON.Vec3(0, 0, -1),

  Math.PI * 0.5

);

vaseWallBackBody.addShape(vaseWallShapeBack);

 

const vaseWallShapeRight = new CANNON.Box(new CANNON.Vec3(0.7, 0.7, 0.01));

const vaseWallRightBody = new CANNON.Body();

vaseWallRightBody.mass = 0;

vaseWallRightBody.material = defaultMaterial;

vaseWallRightBody.quaternion.setFromAxisAngle(

  new CANNON.Vec3(0, 1, 0),

  Math.PI * 0.5

);

vaseWallRightBody.addShape(vaseWallShapeRight);

 

const vaseWallShapeLeft = new CANNON.Box(new CANNON.Vec3(0.7, 0.7, 0.01));

const vaseWallLeftBody = new CANNON.Body();

vaseWallLeftBody.mass = 0;

vaseWallLeftBody.material = defaultMaterial;

vaseWallLeftBody.quaternion.setFromAxisAngle(

  new CANNON.Vec3(0, -1, 0),

  Math.PI * 0.5

);

vaseWallLeftBody.addShape(vaseWallShapeLeft);

 

vaseBottomBody.position.set(0.05, -0.8, 0);

vaseWallFrontBody.position.set(0.05, 0, -0.18);

vaseWallBackBody.position.set(0.05, 0, 0.18);

vaseWallRightBody.position.set(-0.18, 0, 0);

vaseWallLeftBody.position.set(0.18, 0, 0);

world.addBody(vaseBottomBody);

world.addBody(vaseWallFrontBody);

world.addBody(vaseWallBackBody);

world.addBody(vaseWallRightBody);

world.addBody(vaseWallLeftBody);

 

/**

 *  Blender Models

 */

let mixer = null;

 

// Static

gltfLoader.load("/models/background/background.glb", (gltf) => {

  scene.add(gltf.scene);

});

 

/**

 * Foliage

 */

 

let largeFoliage = new THREE.Mesh();

let mediumFoliage = new THREE.Mesh();

let smallFoliage = new THREE.Mesh();

 

const spawnLargeFoliage = function () {

  gltfLoader.load("/models/background/largeFoliage.glb", (gltf) => {

    largeFoliage = gltf.scene;

    scene.add(largeFoliage);

  });

};

const spawnMediumFoliage = function () {

  gltfLoader.load("/models/background/mediumFoliage.glb", (gltf) => {

    mediumFoliage = gltf.scene;

    scene.add(mediumFoliage);

  });

};

const spawnSmallFoliage = function () {

  gltfLoader.load("/models/background/smallFoliage.glb", (gltf) => {

    smallFoliage = gltf.scene;

    scene.add(smallFoliage);

  });

};

 

const largeFoliageBtn = document.getElementById("largeFoliage");

const mediumFoliageBtn = document.getElementById("mediumFoliage");

const smallFoliageBtn = document.getElementById("smallFoliage");

 

largeFoliageBtn.addEventListener("click", function (event) {

  event.preventDefault();

  spawnLargeFoliage();

  scene.remove(mediumFoliage);

  scene.remove(smallFoliage);

});

mediumFoliageBtn.addEventListener("click", function (event) {

  event.preventDefault();

  spawnMediumFoliage();

  scene.remove(smallFoliage);

  scene.remove(largeFoliage);

});

smallFoliageBtn.addEventListener("click", function (event) {

  event.preventDefault();

  spawnSmallFoliage();

  scene.remove(largeFoliage);

  scene.remove(mediumFoliage);

});

 

spawnMediumFoliage();

 

/**

 * Flowers

 */

const length = 0.75;

 

/**

 * Roses

 */

const createFlower = function (location, positionX, positionY, positionZ) {

  gltfLoader.load(location, (gltf) => {

    let flower = gltf.scene;

    flower.position.set(positionX, positionY, positionZ);

    scene.add(flower);

 

    // Cannon.js body

    const petalShape = new CANNON.Sphere(0.1);

    const stemShape = new CANNON.Cylinder(0.01, 0.01, length + 0.4, 6);

 

    const flowerPetal = new CANNON.Body({

      mass: 10,

      material: defaultMaterial,

    });

    flowerPetal.addShape(petalShape, new CANNON.Vec3(0, 0.2, 0));

    flowerPetal.position.set(positionX, positionY, positionZ);

    world.addBody(flowerPetal);

 

    const flowerStem = new CANNON.Body({

      mass: 1,

      material: defaultMaterial,

    });

    flowerStem.addShape(stemShape, new CANNON.Vec3(0, -0.5 - length / 2, 0));

    flowerStem.position.set(positionX, positionY, positionZ);

    world.addBody(flowerStem);

 

    var flowerConstraint = new CANNON.ConeTwistConstraint(

      flowerPetal,

      flowerStem,

      {

        pivotA: new CANNON.Vec3(0, 0, 0),

        pivotB: new CANNON.Vec3(0, 0, 0),

        axisA: CANNON.Vec3.UNIT_Y,

        axisB: CANNON.Vec3.UNIT_Y,

        angle: Math.PI / 4,

        twistAngle: Math.PI / 4,

      }

    );

    world.addConstraint(flowerConstraint);

 

    // Save in objects to update

    objectsToUpdate.push({

      flowerAndBody: {

        flower: flower,

        body: flowerPetal,

      },

    });

 

    timerQueue.push(

      setTimeout(() => {

        objectsToUpdate.shift();

      }, 5000)

    );

  });

};

 

/**

 * Delphinium

 */

 

// White Delphinium

const createDelphinium = function (location, positionX, positionY, positionZ) {

  gltfLoader.load(location, (gltf) => {

    let delphinium = gltf.scene;

    delphinium.position.set(positionX, positionY, positionZ);

    scene.add(delphinium);

 

    // Cannon.js body

    const stemShape = new CANNON.Cylinder(

      0.04,

      0.04,

      Math.random() + length,

      6

    );

 

    const delphiniumBody = new CANNON.Body({

      mass: 3,

      material: defaultMaterial,

    });

    delphiniumBody.addShape(

      stemShape,

      new CANNON.Vec3(0, -0.5 - length / 2, 0)

    );

 

    delphiniumBody.position.set(positionX, positionY, positionZ);

    world.addBody(delphiniumBody);

 

    // Save in objects to update

    objectsToUpdate.push({

      flowerAndBody: {

        flower: delphinium,

        body: delphiniumBody,

      },

    });

  });

};

 

// Roses

const whiteRoseBtn = document.getElementById("whiteRose");

const redRoseBtn = document.getElementById("redRose");

const yellowRoseBtn = document.getElementById("yellowRose");

const lavenderRoseBtn = document.getElementById("lavenderRose");

const orangeRoseBtn = document.getElementById("orangeRose");

const pinkRoseBtn = document.getElementById("pinkRose");

 

whiteRoseBtn.addEventListener("click", function (event) {

  event.preventDefault();

  createFlower("/models/roses/whiteRose.glb", 0, 0.8, 0);

});

redRoseBtn.addEventListener("click", function (event) {

  event.preventDefault();

  createFlower("/models/roses/redRose.glb", 0, 0.8, 0);

});

yellowRoseBtn.addEventListener("click", function (event) {

  event.preventDefault();

  createFlower("/models/roses/yellowRose.glb", 0, 0.8, 0);

});

lavenderRoseBtn.addEventListener("click", function (event) {

  event.preventDefault();

  createFlower("/models/roses/lavenderRose.glb", 0, 0.8, 0);

});

orangeRoseBtn.addEventListener("click", function (event) {

  event.preventDefault();

  createFlower("/models/roses/orangeRose.glb", 0, 0.8, 0);

});

pinkRoseBtn.addEventListener("click", function (event) {

  event.preventDefault();

  createFlower("/models/roses/pinkRose.glb", 0, 0.8, 0);

});

 

// Carnations

const whiteCarnationBtn = document.getElementById("whiteCarnation");

const redCarnationBtn = document.getElementById("redCarnation");

const yellowCarnationBtn = document.getElementById("yellowCarnation");

const pinkCarnationBtn = document.getElementById("pinkCarnation");

 

whiteCarnationBtn.addEventListener("click", function (event) {

  event.preventDefault();

  createFlower("/models/carnations/whiteCarnation.glb", 0, 0.8, 0);

});

redCarnationBtn.addEventListener("click", function (event) {

  event.preventDefault();

  createFlower("/models/carnations/redCarnation.glb", 0, 0.8, 0);

});

yellowCarnationBtn.addEventListener("click", function (event) {

  event.preventDefault();

  createFlower("/models/carnations/yellowCarnation.glb", 0, 0.8, 0);

});

pinkCarnationBtn.addEventListener("click", function (event) {

  event.preventDefault();

  createFlower("/models/carnations/pinkCarnation.glb", 0, 0.8, 0);

});

 

// Lillies

const whiteLillyBtn = document.getElementById("whiteLilly");

const yellowLillyBtn = document.getElementById("yellowLilly");

const pinkLillyBtn = document.getElementById("pinkLilly");

 

whiteLillyBtn.addEventListener("click", function (event) {

  event.preventDefault();

  createFlower("/models/Lillies/whiteLilly.glb", 0, 0.8, 0);

});

yellowLillyBtn.addEventListener("click", function (event) {

  event.preventDefault();

  createFlower("/models/Lillies/yellowLilly.glb", 0, 0.8, 0);

});

pinkLillyBtn.addEventListener("click", function (event) {

  event.preventDefault();

  createFlower("/models/Lillies/pinkLilly.glb", 0, 0.8, 0);

});

 

// Daisies

const whiteDaisyBtn = document.getElementById("whiteDaisy");

const gerberaDaisyBtn = document.getElementById("gerberaDaisy");

const yellowDaisyBtn = document.getElementById("yellowDaisy");

const pinkDaisyBtn = document.getElementById("pinkDaisy");

 

whiteDaisyBtn.addEventListener("click", function (event) {

  event.preventDefault();

  createFlower("/models/Daisies/whiteDaisy.glb", 0, 0.8, 0);

});

gerberaDaisyBtn.addEventListener("click", function (event) {

  event.preventDefault();

  createFlower("/models/Daisies/gerberaDaisy.glb", 0, 0.8, 0);

});

yellowDaisyBtn.addEventListener("click", function (event) {

  event.preventDefault();

  createFlower("/models/Daisies/yellowDaisy.glb", 0, 0.8, 0);

});

pinkDaisyBtn.addEventListener("click", function (event) {

  event.preventDefault();

  createFlower("/models/Daisies/pinkDaisy.glb", 0, 0.8, 0);

});

 

// Delphinium

const whiteDelphiniumBtn = document.getElementById("whiteDelphinium");

const blueDelphiniumBtn = document.getElementById("blueDelphinium");

const lavenderDelphiniumBtn = document.getElementById("lavenderDelphinium");

 

whiteDelphiniumBtn.addEventListener("click", function (event) {

  event.preventDefault();

  createDelphinium("/models/delphinium/whiteDelphinium.glb", 0, 0.8, 0);

});

blueDelphiniumBtn.addEventListener("click", function (event) {

  event.preventDefault();

  createDelphinium("/models/delphinium/blueDelphinium.glb", 0, 0.8, 0);

});

lavenderDelphiniumBtn.addEventListener("click", function (event) {

  event.preventDefault();

  createDelphinium("/models/delphinium/lavenderDelphinium.glb", 0, 0.8, 0);

});

 

// Sunflower

const sunflowerBtn = document.getElementById("sunflower");

 

sunflowerBtn.addEventListener("click", function (event) {

  event.preventDefault();

  createFlower("/models/sunflower/sunflower.glb", 0, 0.8, 0);

});

 

const clock = new THREE.Clock();

let previousTime = 0;

 

// Physics for Flowers

const physicsTick = () => {

  const elapsedTime = clock.getElapsedTime();

  const deltaTime = elapsedTime - previousTime;

  previousTime = elapsedTime;

 

  // Update Physics World

  world.step(1 / 60, deltaTime, 3);

 

  for (const object of objectsToUpdate) {

    object.flowerAndBody.flower.position.copy(

      object.flowerAndBody.body.position

    );

    object.flowerAndBody.flower.quaternion.copy(

      object.flowerAndBody.body.quaternion

    );

  }

 

  // Call tick again on the next frame

  window.requestAnimationFrame(physicsTick);

};

physicsTick();

 

/**

 * Lights

 */

// Ambient Light

const ambientLight = new THREE.AmbientLight(0xfdfff2, 0.1);

scene.add(ambientLight);

 

// Main Spotlight

const mainSpotLight = new THREE.SpotLight(0xffffbd, 10);

mainSpotLight.position.set(3, 30, -10);

scene.add(mainSpotLight);

 

mainSpotLight.castShadow = true;

mainSpotLight.shadow.mapSize.set(1024 * 4, 1024 * 4);

mainSpotLight.shadow.camera.near = 2;

mainSpotLight.shadow.camera.far = 18;

mainSpotLight.shadow.camera.fov = 1;

mainSpotLight.shadow.normalBias = -0.03;

 

// Top Spotlight

const topSpotLight = new THREE.SpotLight(0xffffbd, 6);

topSpotLight.position.set(0, 7.5, -0.3);

topSpotLight.penumbra = 1;

scene.add(topSpotLight);

 

// Rotation

mainSpotLight.rotation.reorder("YXZ");

topSpotLight.rotation.reorder("YXZ");

 

/**

 * Renderer

 */

const renderer = new THREE.WebGLRenderer({

  canvas: canvas,

});

renderer.antialias = true;

renderer.shadowMap.enabled = true;

renderer.shadowMap.type = THREE.PCFSoftShadowMap;

renderer.physicallyCorrectLights = true;

renderer.setSize(sizes.width, sizes.height);

renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));

renderer.outputEncoding = THREE.sRGBEncoding;

renderer.toneMapping = THREE.ACESFilmicToneMapping;

renderer.toneMappingExposure = 9;

 

/**

 * Post processing

 */

//Render target

let RenderTargetClass = null;

 

if (renderer.getPixelRatio() === 1 && renderer.capabilities.isWebGL2) {

  RenderTargetClass = THREE.WebGLMultisampleRenderTarget;

} else {

  RenderTargetClass = THREE.WebGLRenderTarget;

}

 

//Effect Composer

const effectComposer = new EffectComposer(renderer);

effectComposer.setPixelRatio(Math.min(window.devicePixelRatio, 2));

effectComposer.setSize(sizes.width, sizes.height);

 

//Render Pass

const renderPass = new RenderPass(scene, camera);

effectComposer.addPass(renderPass);

 

//Unreal Bloom Pass

const unrealBloomPass = new UnrealBloomPass();

unrealBloomPass.strength = 0.12;

unrealBloomPass.radius = 0;

unrealBloomPass.threshold = 0.6;

effectComposer.addPass(unrealBloomPass);

 

//Tint pass

const TintShader = {

  uniforms: {

    tDiffuse: { value: null },

    uTint: { value: null },

  },

  vertexShader: `

        varying vec2 vUv;

 

        void main(){

            gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);

       

            vUv = uv;

        }

    `,

  fragmentShader: `

        uniform sampler2D tDiffuse;

        uniform vec3 uTint;

 

        varying vec2 vUv;

 

        void main(){

            vec4 color = texture2D(tDiffuse, vUv);

 

            // color.r += 0.2;

            // color.b += 0.2;

            color.rgb += uTint;

 

            gl_FragColor = color;

        }

    `,

};

const tintPass = new ShaderPass(TintShader);

tintPass.material.uniforms.uTint.value = new THREE.Vector3();

effectComposer.addPass(tintPass);

 

// SMAA Pass

if (renderer.getPixelRatio() === 1 && !renderer.capabilities.isWebGl2) {

  const smaaPass = new SMAAPass();

  effectComposer.addPass(smaaPass);

}

 

/**

 * Animation

 */

// Update Everything

const tick = () => {

  if (mixer) {

    mixer.update(deltaTime);

  }

 

  // Update Materials

  updateAllMaterials();

 

  // Update controls

  // controls.update();

 

  // Update camera to see all around

  camera.position.x = -Math.sin(cursor.x * Math.PI) * 2;

  camera.position.y = Math.cos(cursor.y * Math.PI) * 2;

  camera.position.z = -Math.cos(cursor.x * Math.PI) * 2;

  camera.lookAt(new THREE.Vector3(0, 1, 0));

 

  // Render

  effectComposer.render();

 

  // Call tick again on the next frame

  window.requestAnimationFrame(tick);

};

tick();

Clicker Browser Game

I created as a final project for my college course a clicker game with various levels of collectables. The scripts involved with this project use modules to seperate the code out.

Title.png
Game.png
Burger.png
Restaurant.png
GroceryStore.png
Factory.png
CowFarm.png
BreedingFacility.png
bottom of page