Three.js 平滑运动的秒针

文化   2024-11-13 18:00   河南  

使用 Three.js 的 WebGL 小实验。平滑运动的秒针。

实现代码

HTML:

<script type="importmap">  {    "imports": {      "three": "https://unpkg.com/three@0.170.0/build/three.module.js",      "three/addons/": "https://unpkg.com/three@0.170.0/examples/jsm/"    }  }</script>
CSS:
body {  overflow: hidden;  margin:0;}

JAVASCRIPT:

import * as THREE from "three";import { OrbitControls } from "three/addons/controls/OrbitControls.js";

console.clear();

class Dial extends THREE.LineSegments { constructor() { let radii = [6.0, 5.5]; let axis = new THREE.Vector3(0, 0, 1); let positions = [...Array(60)] .map((_, idx, arr) => { let step = (Math.PI * 2) / arr.length; return [...radii].map((radius, rIdx) => { return new THREE.Vector3(0, 1, 0) .setLength(radius - (idx % 5 == 0 && rIdx == 1 ? 0.25 : 0)) .applyAxisAngle(axis, idx * step); }); }) .flat(); super( new THREE.BufferGeometry().setFromPoints(positions), new THREE.LineBasicMaterial({ color: 0x00aaff }) ); }}

class SecondsHand extends THREE.Mesh { constructor() { let shape = new THREE.Shape() .moveTo(5, 0) .lineTo(4.9, 0.05) .absarc(0, 0, 0.25, Math.PI * 0.1, Math.PI * 1.9, false) .lineTo(4.9, -0.05); shape.holes.push(new THREE.Path().absarc(0, 0, 0.1, 0, Math.PI * 2, true)); super( new THREE.ShapeGeometry(shape).rotateZ(Math.PI * 0.5), new THREE.MeshBasicMaterial({ color: "lightblue" }) ); this.angleStep = Math.PI * 2 / 60; this.Easings = { Back: { Out: function(amount) { // https://github.com/tweenjs/tween.js/blob/eb07dd2012862269e652129230a71baa4d3608ae/src/Easing.ts#L189 const s = 1.70158; return amount === 0 ? 0 : --amount * amount * ((s + 1) * amount + s) + 1; } }, Bounce: { Out: function( amount ){ // https://github.com/tweenjs/tween.js/blob/eb07dd2012862269e652129230a71baa4d3608ae/src/Easing.ts#L206 if (amount < 1 / 2.75) { return 7.5625 * amount * amount } else if (amount < 2 / 2.75) { return 7.5625 * (amount -= 1.5 / 2.75) * amount + 0.75 } else if (amount < 2.5 / 2.75) { return 7.5625 * (amount -= 2.25 / 2.75) * amount + 0.9375 } else { return 7.5625 * (amount -= 2.625 / 2.75) * amount + 0.984375 } } }, Elastic: { Out: function (amount) { // https://github.com/tweenjs/tween.js/blob/eb07dd2012862269e652129230a71baa4d3608ae/src/Easing.ts#L155 if (amount === 0) { return 0; } if (amount === 1) { return 1; } return ( Math.pow(2, -10 * amount) * Math.sin((amount - 0.1) * 5 * Math.PI) + 1 ); } } }; }

update(){ let time = new Date(); let seconds = time.getSeconds(); let milliseconds = (time.getMilliseconds() / 1000) ** 16; this.rotation.z = -(seconds + this.Easings.Elastic.Out(milliseconds)) * this.angleStep; }}

let scene = new THREE.Scene();let camera = new THREE.PerspectiveCamera(45, innerWidth / innerHeight, 1, 100);camera.position.set(0, 0, 1).setLength(15);let renderer = new THREE.WebGLRenderer({ antialias: true });renderer.setSize(innerWidth, innerHeight);document.body.appendChild(renderer.domElement);

window.addEventListener("resize", (event) => { camera.aspect = innerWidth / innerHeight; camera.updateProjectionMatrix(); renderer.setSize(innerWidth, innerHeight);});

let controls = new OrbitControls(camera, renderer.domElement);controls.enableDamping = true;

let dial = new Dial();scene.add(dial);

let secondsHand = new SecondsHand();scene.add(secondsHand);

renderer.setAnimationLoop(() => { controls.update(); secondsHand.update(); renderer.render(scene, camera);});



源码:

https://codepen.io/prisoner849/pen/XWvORjj


体验:

https://codepen.io/prisoner849/full/XWvORjj



感谢您的阅读      

在看点赞 好文不断  

初识Threejs
初识 Three.js 的奇妙世界,走进三维空间,与小编一起拥抱前端技术,涉及WebGL、WebGPU、Threejs、Shader、GIS、VR/AR、数字孪生、3D图形学等。
 最新文章