JSFiddle - React, Tailwind, and code Playground
by tfoller
HTML
<canvas id="main_canvas" width="550" height="550"></canvas>
<div id="ui">
<button id="psw">...</button>
</div>
CSS
* {
padding: 0;
margin: 0;
box-sizing: border-box;
}
.noselect {
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
#ctrl_over {
position: absolute;
opacity: 0.5;
bottom: 9px;
right: 5px;
color: #aaa;
font-family: Arial, Helvetica, sans-serif;
font-size: 13px;
}
#ctrl_sw {
border: solid 1px #aaa;
padding: 3px;
margin-left: 10px;
cursor: pointer;
font-size: 11px;
text-transform: uppercase;
}
#canv_wrap {
position:relative;
margin: 0px;
padding: 0px;
display: inline-block;
}
body {
background: #112233;
width: 100vw;
height: 100vh;
}
button {
padding: 3px;
margin-left: 10px;
color: #333;
filter: invert(100%);
cursor: pointer;
}
canvas {
display: block;
border: solid 1px grey;
box-sizing: content-box;
margin: 10px;
}
JavaScript
import * as THREE from 'https://alikim.com/_v1_jsm/three.module.js'
import * as CONTROLS from 'https://alikim.com/_v1_jsm/controls.js'
import { log, slog, get, getHTML } from 'https://alikim.com/_v1_jsm/utils.js'
const html = getHTML();
// 3D
const canvas = get('main_canvas');
const [w, h] = [canvas.width, canvas.height];
const renderer = new THREE.WebGLRenderer({
antialias: true,
canvas: canvas,
});
renderer.setSize(w, h);
const [near, far] = [1, 700];
const mid = -0.5 * (near + far);
const camera = new THREE.PerspectiveCamera(45, w / h, near, far);
const scene = new THREE.Scene();
scene.background = new THREE.Color(0, 0, 0.3);
const generatePoints = (radius, numPoints) => {
const points = [];
for (let i = 0; i < numPoints; i++) {
const angle = (i / numPoints) * Math.PI * 2;
const x = radius * Math.cos(angle);
const y = radius * Math.sin(angle);
const z = 0;
points.push(new THREE.Vector3(x, y, z));
}
return points;
};
const points = generatePoints(50, 20);
const geo = new THREE.BufferGeometry().setFromPoints(points);
const mat = new THREE.MeshBasicMaterial();
const pos_attr = geo.attributes.position;
const vert = pos_attr.array;
const planar = new THREE.LineLoop(geo, mat);
planar.position.z = mid;
scene.add(planar);
const hlp = new THREE.AxesHelper(100);
hlp.position.z = mid;
scene.add(hlp);
function render() { renderer.render(scene, camera) }
function maybeRender() {
for(let i = 0; i < points.length; i++) {
const pnt = points[i].clone().applyQuaternion(camera.quaternion);
const off = i * 3;
vert[off] = pnt.x;
vert[off + 1] = pnt.y;
vert[off + 2] = pnt.z;
}
pos_attr.needsUpdate = true;
render();
}
const createControls = () => {
CONTROLS.create({
cont: canvas,
cam: camera,
type: 'Trackball',
overlay: true,
lookAt: [0, 0, mid],
callback: maybeRender,
sens: {p: 0.005},
});
};
createControls();
render();