JSFiddle - React, Tailwind, and code Playground

HTML

<!doctype html>
<html lang="en">

  <head>
    <meta charset="UTF-8" />
    <link rel="stylesheet" href="style.css" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>gsplat.js - PLY Converter</title>
  </head>

  <body>
    <div id="progress-container">
      <dialog open id="progress-dialog">
        <p>
          <label for="progress-indicator">Loading SPLAT file...</label>
        </p>
        <progress max="100" id="progress-indicator"></progress>
      </dialog>
    </div>

    <canvas id="canvas"></canvas>
    <script type="module" src="index.js"></script>
  </body>

</html>

CSS

body,
html {
  margin: 0;
  padding: 0;
  overflow: hidden;
  background-color: #fff;
  font-family: sans-serif;
}

canvas {
  width: 100vw;
  height: 100vh;
}

dialog {
  width: 100%;
  text-align: center;
  max-width: 20em;
  color: white;
  background-color: #000;
  border: none;
  position: relative;
  transform: translate(-50%, -50%);
}

#progress-container {
  position: absolute;
  top: 50%;
  left: 50%;
}

progress {
  width: 100%;
  height: 1em;
  border: none;
  background-color: #fff;
  color: #eee;
}

progress::-webkit-progress-bar {
  background-color: #333;
}

progress::-webkit-progress-value {
  background-color: #eee;
}

progress::-moz-progress-bar {
  background-color: #eee;
}

JavaScript

import * as SPLAT from "https://cdn.jsdelivr.net/npm/gsplat@latest";

const canvas = document.getElementById("canvas");
const progressDialog = document.getElementById("progress-dialog");
const progressIndicator = document.getElementById("progress-indicator");

const renderer = new SPLAT.WebGLRenderer(canvas);
const scene = new SPLAT.Scene();
const camera = new SPLAT.Camera();
const controls = new SPLAT.OrbitControls(camera, canvas);

async function main() {
  // Load and convert ply from url
  const url =
    "https://huggingface.co/datasets/dylanebert/3dgs/resolve/main/bonsai/bonsai-7k-mini.splat";
  await SPLAT.Loader.LoadAsync(url, scene, (progress) => (progressIndicator.value = progress * 100));
  progressDialog.close();
  scene.saveToFile("bonsai-7k-mini.ply", "ply");

  // Render loop
  const frame = () => {
    controls.update();
    renderer.render(scene, camera);

    requestAnimationFrame(frame);
  };

  requestAnimationFrame(frame);
}

main();