Website  developer 
stas m photo
and 
animation  enthusiast
stas m photo
with 11 years experience
in the web industry

Technical Stack

import * as THREE from 'three';

import Stats from 'three/addons/libs/stats.module.js';

let container, stats;

let camera, scene, renderer;

let points;

init();
animate();

function init() {

    container = document.getElementById( 'container' );

    //

    camera = new THREE.PerspectiveCamera( 27, window.innerWidth / window.innerHeight, 5, 3500 );
    camera.position.z = 2750;

    scene = new THREE.Scene();
    scene.background = new THREE.Color( 0x050505 );
    scene.fog = new THREE.Fog( 0x050505, 2000, 3500 );

    //

    const particles = 500000;

    const geometry = new THREE.BufferGeometry();

    const positions = [];
    const colors = [];

    const color = new THREE.Color();

    const n = 1000, n2 = n / 2; // particles spread in the cube

    for ( let i = 0; i < particles; i ++ ) {

        // positions

        const x = Math.random() * n - n2;
        const y = Math.random() * n - n2;
        const z = Math.random() * n - n2;

        positions.push( x, y, z );

        // colors

        const vx = ( x / n ) + 0.5;
        const vy = ( y / n ) + 0.5;
        const vz = ( z / n ) + 0.5;

        color.setRGB( vx, vy, vz, THREE.SRGBColorSpace );

        colors.push( color.r, color.g, color.b );

    }

    geometry.setAttribute( 'position', new THREE.Float32BufferAttribute( positions, 3 ) );
    geometry.setAttribute( 'color', new THREE.Float32BufferAttribute( colors, 3 ) );

    geometry.computeBoundingSphere();

    //

    const material = new THREE.PointsMaterial( { size: 15, vertexColors: true } );

    points = new THREE.Points( geometry, material );
    scene.add( points );

    //

    renderer = new THREE.WebGLRenderer();
    renderer.setPixelRatio( window.devicePixelRatio );
    renderer.setSize( window.innerWidth, window.innerHeight );
    renderer.setAnimationLoop( animate );

    container.appendChild( renderer.domElement );

    //

    stats = new Stats();
    container.appendChild( stats.dom );

    //

    window.addEventListener( 'resize', onWindowResize );

}

function onWindowResize() {

    camera.aspect = window.innerWidth / window.innerHeight;
    camera.updateProjectionMatrix();

    renderer.setSize( window.innerWidth, window.innerHeight );

}

//

function animate() {

    const time = Date.now() * 0.001;

    points.rotation.x = time * 0.25;
    points.rotation.y = time * 0.5;

    renderer.render( scene, camera );

    stats.update();

}
MorphSVGPlugin.convertToPath("circle, rect, polygon");

const tl = gsap
  .timeline({
    repeat: -1,
    repeatDelay: 0.5,
    delay: 0.5,
    yoyo: true,
    defaults: { ease: "power2.inOut" }
  })
  .to("#triangle", { morphSVG: "#a" })
  .to("#square", { morphSVG: "#b" })
  .to("#circle", { morphSVG: "#c" });
Heading 1
Heading 2
Heading 3
Heading 4
<div class="h1">Heading 1</div>
<div class="h2">Heading 2</div>
<div class="h3">Heading 3</div>
<div class="h4">Heading 4</div>
<div class="body">Body text with <a href="#">the link (non clickable)</a></div>
.css-showcase {
  height: 100%;
  width: 100%;
  background: #0c0c0c
    radial-gradient(
      80.18% 128.88% at -5.92% 57.57%,
      #0c0c0c 35%,
      #d01cdf 40.5%,
      #2b32ca 60.67%,
      #0c0c0c 65%
    );
  background-size: 850% 150%;
  filter: blur(40px);
  animation: gradientMoves 4s linear infinite reverse;
}

@keyframes gradientMoves {
  0% {
    background-position: 0 50%;
  }

  100% {
    background-position: 60% 50%;
  }
}

const timeElement = document.getElementById("time");
const updateTime = () => {
  const now = new Date();
  const hours = now.getHours().toString().padStart(2, "0");
  const minutes = now.getMinutes().toString().padStart(2, "0");
  const seconds = now.getSeconds().toString().padStart(2, "0");
  const milliseconds = now.getMilliseconds().toString().padStart(3, "0"); // Add milliseconds
  // Get current time zone using Intl API
  const timeZone = Intl.DateTimeFormat().resolvedOptions().timeZone;
  timeElement.textContent = `Current Time: ${hours}:${minutes}:${seconds}:${milliseconds} (${timeZone})`;
};
setInterval(updateTime, 1); 

const fetchDataButton = document.getElementById("fetchDataButton");
fetchDataButton.addEventListener("click", async () => {
  const resultElement = document.getElementById("result");
  resultElement.textContent = "Fetching data...";

  try {
    const response = await fetch(
      "https://jsonplaceholder.typicode.com/todos/1"
    );
    const data = await response.json();
    resultElement.textContent = `Fetched Data: ${JSON.stringify(data)}`;
  } catch (error) {
    resultElement.textContent = "Failed to fetch data!";
  }
});

const storeDataButton = document.getElementById("storeDataButton");
const retrieveDataButton = document.getElementById("retrieveDataButton");

storeDataButton.addEventListener("click", () => {
  localStorage.setItem(
    "myData",
    JSON.stringify({ name: "JavaScript", version: "ES6+" })
  );
  alert("Data stored in local storage!");
});

retrieveDataButton.addEventListener("click", () => {
  const storedData = JSON.parse(localStorage.getItem("myData"));
  if (storedData) {
    alert(
      `Retrieved Data: Name - ${storedData.name}, Version - ${storedData.version}`
    );
  } else {
    alert("No data found in local storage.");
  }
});

const functionalProgrammingButton = document.getElementById(
  "functionalProgrammingButton"
);

functionalProgrammingButton.addEventListener("click", () => {
  const processArray = (arr, fn) => arr.map(fn);

  const numbers = [1, 2, 3, 4, 5];
  const doubledNumbers = processArray(numbers, (num) => num * 2);

  alert(
    `Original Numbers: ${numbers.join(
      ", "
    )}\nDoubled Numbers: ${doubledNumbers.join(", ")}`
  );
});

{{ message }}

Input: {{ userInput }}

Reversed Input: {{ reversedInput }}

Todo List

  • {{ todo.text }}
// Create a Vue instance
new Vue({
  el: "#app", // Connect Vue instance to the #app element
  data: {
    message: "Hello, Vue.js!",
    userInput: "", // Input field bound to v-model
    todos: [
      { id: 1, text: "Learn Vue.js" },
      { id: 2, text: "Build a project" },
      { id: 3, text: "Master components" }
    ],
    newTodo: "" // Input for adding a new todo
  },
  computed: {
    // Computed property to reverse the input text
    reversedInput() {
      return this.userInput.split("").reverse().join("");
    }
  },
  methods: {
    // Method to reverse the message string
    reverseMessage() {
      this.message = this.message.split("").reverse().join("");
    },
    // Method to add a new todo item
    addTodo() {
      if (this.newTodo) {
        this.todos.push({
          id: this.todos.length + 1,
          text: this.newTodo
        });
        this.newTodo = ""; // Clear input after adding
      }
    }
  }
});
139
websites for
๐Ÿ‡ฌ๐Ÿ‡ง Alaistar
๐Ÿ‡ฌ๐Ÿ‡ง Alexander
๐Ÿ‡ฌ๐Ÿ‡ง Lars
๐Ÿ‡ฌ๐Ÿ‡ง Charlie
๐Ÿ‡ฌ๐Ÿ‡ง Mark
๐Ÿ‡บ๐Ÿ‡ธ Sky
๐Ÿ‡ธ๐Ÿ‡ฌ Stephanie
๐Ÿ‡ฉ๐Ÿ‡ฐ Zaedo
๐Ÿ‡ฉ๐Ÿ‡ฐ Sonny
๐Ÿ‡ท๐Ÿ‡บ Demyan
๐Ÿ‡จ๐Ÿ‡ญ Nick
๐Ÿ‡จ๐Ÿ‡ญ Roger
๐Ÿ‡จ๐Ÿ‡ญ Neil
๐Ÿ‡จ๐Ÿ‡ญ Estefano
๐Ÿ‡ฉ๐Ÿ‡ช Scott
๐Ÿ‡ฉ๐Ÿ‡ช Max
๐Ÿ‡ฉ๐Ÿ‡ช Katharina
๐Ÿ‡ฉ๐Ÿ‡ช Sebastian
๐Ÿ‡ฉ๐Ÿ‡ช Sergey
๐Ÿ‡ฆ๐Ÿ‡บ Jesse
๐Ÿ‡ฆ๐Ÿ‡บ Terrie
๐Ÿ‡ฆ๐Ÿ‡บ Lachlan
๐Ÿ‡ฆ๐Ÿ‡บ Linda
๐Ÿ‡ฆ๐Ÿ‡บ Nye
๐Ÿ‡ญ๐Ÿ‡ฐ Charlotte
๐Ÿ‡ฟ๐Ÿ‡ฆ Adrian
๐Ÿ‡ซ๐Ÿ‡ท Guillaume
๐Ÿ‡ธ๐Ÿ‡ช Camilla
๐Ÿ‡ธ๐Ÿ‡ช Yun
๐Ÿ‡ธ๐Ÿ‡ช Fredrik
๐Ÿ‡จ๐Ÿ‡ฆ Carrie
๐Ÿ‡จ๐Ÿ‡ฆ Nabil
๐Ÿ‡จ๐Ÿ‡ฆ Natta
๐Ÿ‡ฆ๐Ÿ‡ช Kal Sami
๐Ÿ‡ฆ๐Ÿ‡ช Amir
๐Ÿ‡ฆ๐Ÿ‡ช Kirstyn
๐Ÿ‡บ๐Ÿ‡ธ Nick & Davis
๐Ÿ‡บ๐Ÿ‡ธ Joe
๐Ÿ‡บ๐Ÿ‡ธ Frederic
๐Ÿ‡บ๐Ÿ‡ธ Dasha
๐Ÿ‡บ๐Ÿ‡ธ Wee
๐Ÿ‡บ๐Ÿ‡ธ Derrick
๐Ÿ‡ช๐Ÿ‡ช Jane
๐Ÿ‡บ๐Ÿ‡ธ Stevens
๐Ÿ‡ช๐Ÿ‡ธ Thao
๐Ÿ‡ง๐Ÿ‡ช Amy
๐Ÿ‡ฎ๐Ÿ‡ช Vladimir
๐Ÿ‡ฎ๐Ÿ‡ฑ Ido
๐Ÿ‡ฎ๐Ÿ‡ฑ Yaada
๐Ÿ‡ฏ๐Ÿ‡ต Sally
๐Ÿ‡ธ๐Ÿ‡ฌ Rupert
๐Ÿ‡จ๐Ÿ‡ฟ Jakub
๐Ÿ‡จ๐Ÿ‡ฟ Masha & Egor
๐Ÿ‡ฐ๐Ÿ‡ท Jisuk

Proficient

and skilled with Webflow, Shopify, andย Squarespace, creating websites for business andย withย designers.