- 目的:three.js加载svg, 选中改变模型颜色。
- 技术:vue3,threeJs。
- 代码:
<template>
<div id="my-three"></div>
</template>
<script setup>
import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
import { SVGLoader } from "three/examples/jsm/loaders/SVGLoader";
import { onMounted } from "vue";
var scene, camera, renderer;
function init() {
scene = new THREE.Scene();
scene.background = new THREE.Color("#F7F7F7");
const width = window.innerWidth,
height = window.innerHeight;
camera = new THREE.PerspectiveCamera(45, width / height, 1, 3000);
camera.position.set(500, 150, 600);
camera.lookAt(0, 0, 0);
const ambient = new THREE.AmbientLight(0xffffff, 0.4);
const light = new THREE.PointLight(0xffffff, 1);
scene.add(ambient);
light.position.set(200, 300, 400);
scene.add(light);
var gridHelper = new THREE.GridHelper(600, 50, 0xb3b3b3, 0xcccccc);
gridHelper.position.y = -50;
scene.add(gridHelper);
setTitleGroup();
renderer = new THREE.WebGLRenderer();
renderer.setSize(width, height);
renderer.render(scene, camera);
document.getElementById("my-three")?.appendChild(renderer.domElement);
const controls = new OrbitControls(camera, renderer.domElement);
controls.addEventListener("change", () => {
render();
});
}
const titleGroup = new THREE.Group();
titleGroup.scale.y = -1;
titleGroup.position.y = 35;
function setTitleGroup() {
const loader = new SVGLoader();
loader.load(
"https://lf3-cdn-tos.bytescm.com/obj/static/xitu_juejin_web/e08da34488b114bd4c665ba2fa520a31.svg",
(data) => {
const paths = data.paths;
for (let i = 0; i < paths.length; i++) {
const path = paths[i];
const material = new THREE.MeshLambertMaterial({
color: path.color,
side: THREE.DoubleSide,
depthWrite: false,
});
const shapes = path.toShapes(true);
for (let j = 0; j < shapes.length; j++) {
const shape = shapes[j];
var extrudeSettings = {
steps: 1,
depth: 5,
bevelEnabled: false,
};
const geometry = new THREE.ExtrudeGeometry(shape, extrudeSettings);
const mesh = new THREE.Mesh(geometry, material);
titleGroup.add(mesh);
}
}
setCenter(titleGroup);
scene.add(titleGroup);
render();
},
function (xhr) {
console.log((xhr.loaded / xhr.total) * 100 + "% loaded");
},
function (error) {
console.log("An error happened", error);
}
);
}
function setCenter(group) {
const box = new THREE.Box3();
box.expandByObject(group);
const mdlen = box.max.x - box.min.x;
const mdwid = box.max.z - box.min.z;
const mdhei = box.max.y - box.min.y;
const x1 = box.min.x + mdlen / 2;
const y1 = box.min.y + mdhei / 2;
const z1 = box.min.z + mdwid / 2;
group.position.set(-x1, -y1, -z1);
}
var raycaster = new THREE.Raycaster();
var mouse = new THREE.Vector2();
var intersects, selectedObj;
document.addEventListener("mousedown", onDocumentMouseDown, false);
function onDocumentMouseDown(event) {
event.preventDefault();
mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
raycaster.setFromCamera(mouse, camera);
intersects = raycaster.intersectObjects(titleGroup.children);
if (intersects.length > 0) {
if (selectedObj != intersects[0].object) {
document.body.style.cursor = "pointer";
if (selectedObj)
selectedObj.material.color.setHex(selectedObj.currentHex);
selectedObj = intersects[0].object;
selectedObj.currentHex = selectedObj.material.color.getHex();
selectedObj.material.color.set(0xff0000);
}
} else {
document.body.style.cursor = "auto";
if (selectedObj) selectedObj.material.color.set(selectedObj.currentHex);
selectedObj = null;
}
render();
}
function render() {
renderer.render(scene, camera);
}
onMounted(() => {
init();
});
</script>
- 效果:

