three实现三维蝴蝶飞舞动画效果代码
代码语言:html
所属分类:三维
代码描述:three实现三维蝴蝶飞舞动画效果代码
下面为部分代码预览,完整代码请点击下载或在bfwstudio webide中打开
<!DOCTYPE html> <html lang="en" > <head> <meta charset="UTF-8"> <style> @import url('https://fonts.googleapis.com/css2?family=Libre+Barcode+39+Text&family=Macondo+Swash+Caps&display=swap'); html, body { min-height: 100%; } body{ overflow: hidden; margin: 0; background: linear-gradient(#face8D 75%, aquamarine); } canvas{ position: absolute; } #butterfly{ position: absolute; font-family: 'Macondo Swash Caps', cursive; font-size: 10vh; width: 100%; text-align: center; bottom: 1vh; color: maroon; } #player{ position: absolute; opacity: 0.1; } #player:hover{ opacity: 1; } .unselectable { -moz-user-select: none; -webkit-user-select: none; -ms-user-select: none; user-select: none; pointer-events: none; } </style> </head> <body > <canvas id="cnv"></canvas> <div id="butterfly" class="unselectable">Schmetterling</div> <script type="text/javascript" src="//repo.bfw.wiki/bfwrepo/js/es-module-shims.1.6.2.js"></script> <script type="importmap"> { "imports": { "three":"//repo.bfw.wiki/bfwrepo/js/module/three/build/150/three.module.js", "three/addons/": "//repo.bfw.wiki/bfwrepo/js/module/three/examples/jsm/" } } </script> <script type="module"> // https://discourse.threejs.org/t/schmetterling-butterfly-no-webgl-depth-sorting/48919 import { Box2, BufferGeometry, BufferAttribute, Color, MathUtils, Object3D, Path, PerspectiveCamera, Scene, Vector2, Vector3, Matrix4 } from "three"; import { OrbitControls } from "three/addons/controls/OrbitControls.js"; console.clear(); class Material { constructor(fill = "gray", stroke = "black", lineWidth = 2, closed = true) { this.fill = fill; this.stroke = stroke; this.lineWidth = lineWidth; this.closed = closed; }} class Drawable extends Object3D { constructor() { super(); this.isDrawable = true; }} class Polygon extends Drawable { constructor(geometry, material) { super(); this.geometry = geometry; this.material = material; this.isPolygon = true; }} class Circle extends Drawable { constructor(radius = 1, material) { super(); this.radius = radius; this.material = material; this.isCircle = true; this.vertices = [new Vector3(), new Vector3(0, 1, 0).setLength(radius)]; }} class CanvasRenderer { constructor(canvas) { this.canvas = canvas; this.context = this.canvas.getContext("2d"); this.halfSize = new Vector3(); this.renderList = []; this._projectScreenMatrix = new Matrix4(); this._vector3 = new Vector3(); } setSize(width, height) { this.canvas.width = width; this.canvas.height = height; this.halfSize.set(width, height, 0).multiplyScalar(0.5); } sort(scene) { this.renderList = []; scene.traverse(child => { if (child.isDrawable) { this._vector3. setFromMatrixPosition(child.matrixWorld). applyMatrix4(this._projectScreenMatrix); this.renderList.push({ object: child, z: this._vector3.z }); } }); this.renderList.sort((a, b) => b.z - a.z); } render(scene, camera) { scene.updateMatrixWorld(); camera.updateMatrixWorld(); this._projectScreenMatrix.multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse); this.sort(scene); let c = this.context; let v3 = this._vector3; let hs = this.halfSize; c.clearRect(0, 0, this.canvas.width, this.canvas.height); for (let i = 0; i < this.renderList.length; i++) { let listObject = this.renderList[i].object; let z = this.renderList[i].z; let g = listObject.geometry; let m = listObject.material; if (listObject.isPolygon) { c.beginPath(); toScreen(listObject, 0, v3, hs); c.moveTo(v3.x, v3.y); for (let j = 1; j < g.attributes.position.count; j++) { toScreen(listObject, j, v3, hs); c.lineTo(v3.x, v3.y); } if (m.closed) { c.closePath(); } if (m.fill) { c.fillStyle = m.fill; c.fill(); } if (m.stroke) { c.lineWidth = m.lineWidth; c.strokeStyle = m.stroke; c.stroke(); } } if (listObject.isCircle) { if (z <= 0) continue; listObject.lookAt(camera.position); listObject.updateMatrixWorld(); vecToScreen(listObject, listObject.vertices[0], v3, hs); let cx = v3.x; let cy = v3.y; vecToScreen(listObject, listObject.vertices[1], v3, hs); let r = Math.hypot(v3.x - cx, v3.y - cy); c.beginPath(); c.arc(cx, cy, r, 0, Math.PI * 2); if (m.fill) { c.fillStyle = m.fill; c.fill(); } if (m.stroke) { c.lineWidth = m.lineWidth; c.strokeStyle = m.stroke; c.stroke(); } } } function vecToScreen(object, v) { v3.copy(v); object.localToWorld(v3); commonCast(v3); } function posToScreen(object) { v3.setFromMatrixPosition(object.matrixWorld); commonCast(v3); } function toScreen(object, vertexID) { v3.fromBufferAttribute(object.geometry.attributes.position, vertexID); object.localToWorld(v3); commonCast(v3); } function commonCast(v3) { v3.project(camera); v3.y *= -1; v3.multiply(hs).add(hs); } }} class Butterfly extends Object3D { constructor() { super(); let holder = new Object3D(); holder.rotation.set(Math.PI * 0.5, Math.PI, 0); this.add(holder); // head and body let mBody = new Material("black", "#303030", 2); let head = new Circle(0.25, mBody); head.position.y = 0.5; holder.add(head); for (let i = 0; i < 7; i++) { let bPart = new Circle(0.25 - i * 0.025, mBody); bPart.position.y = 0.125 - i * 0.25; holder.add(bPart); } // wings this.wingParts = []; for (let sign = 1; sign >= -1; sign -= 2) { let wingHolder = new Object3D(); wingHolder.position.set(0.25 * sign, 0, 0); holder.add(wingHolder); let partTop = makePart(4, 5, 6, 1, sign, 1); let partBottom = makePart(3, 4, 5, 0.5, sign, -1); partTop.userData = { rotStart: Math.PI * 0.5 * -sign, rotAmp: Math.PI / 4 * 3, rotDir: sign, rotShift: 0 }; partBottom.u.........完整代码请登录后点击上方下载按钮下载查看
网友评论0