feat: added scene for task1 in vanilla
This commit is contained in:
parent
46c9ed9a2d
commit
9658508b1d
@ -7,12 +7,80 @@
|
||||
<style>
|
||||
body {
|
||||
margin: 0;
|
||||
background: white;
|
||||
background: #f3f5f8;
|
||||
overflow: hidden;
|
||||
font-family: "Avenir Next", "Segoe UI", sans-serif;
|
||||
}
|
||||
|
||||
#preset-panel {
|
||||
position: fixed;
|
||||
top: 16px;
|
||||
left: 16px;
|
||||
z-index: 10;
|
||||
background: rgba(255, 255, 255, 0.82);
|
||||
border: 1px solid rgba(0, 0, 0, 0.12);
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1);
|
||||
padding: 12px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
backdrop-filter: blur(6px);
|
||||
}
|
||||
|
||||
#preset-panel h2 {
|
||||
margin: 0;
|
||||
font-size: 14px;
|
||||
letter-spacing: 0.03em;
|
||||
color: #1b2530;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.preset-buttons {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.preset-btn {
|
||||
border: 1px solid #cfd8e3;
|
||||
background: #ffffff;
|
||||
color: #203448;
|
||||
border-radius: 8px;
|
||||
padding: 8px 10px;
|
||||
font-size: 13px;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.preset-btn:hover {
|
||||
border-color: #8ea2b8;
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
|
||||
.preset-btn.active {
|
||||
background: #203448;
|
||||
border-color: #203448;
|
||||
color: #f4f8fb;
|
||||
}
|
||||
|
||||
#hint {
|
||||
margin: 0;
|
||||
font-size: 12px;
|
||||
color: #4f647a;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="preset-panel">
|
||||
<h2>Camera Presets</h2>
|
||||
<div class="preset-buttons">
|
||||
<button class="preset-btn" data-preset="front">Front (1)</button>
|
||||
<button class="preset-btn" data-preset="side">Side (2)</button>
|
||||
<button class="preset-btn" data-preset="topAngled">Top Angled (3)</button>
|
||||
</div>
|
||||
</div>
|
||||
<script type="module" src="/main.js"></script>
|
||||
</body>
|
||||
|
||||
|
||||
@ -0,0 +1,99 @@
|
||||
import * as THREE from "three";
|
||||
|
||||
const scene = new THREE.Scene();
|
||||
scene.background = new THREE.Color(0xf3f5f8);
|
||||
|
||||
const camera = new THREE.PerspectiveCamera(
|
||||
55,
|
||||
window.innerWidth / window.innerHeight,
|
||||
0.1,
|
||||
100
|
||||
);
|
||||
|
||||
const renderer = new THREE.WebGLRenderer({ antialias: true });
|
||||
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
|
||||
renderer.setSize(window.innerWidth, window.innerHeight);
|
||||
document.body.appendChild(renderer.domElement);
|
||||
|
||||
const ambientLight = new THREE.AmbientLight(0xffffff, 0.85);
|
||||
scene.add(ambientLight);
|
||||
|
||||
const keyLight = new THREE.DirectionalLight(0xffffff, 1);
|
||||
keyLight.position.set(3, 4, 5);
|
||||
scene.add(keyLight);
|
||||
|
||||
const cube = new THREE.Mesh(
|
||||
new THREE.BoxGeometry(1.6, 1.6, 1.6),
|
||||
new THREE.MeshStandardMaterial({ color: 0x2a9d8f, roughness: 0.45, metalness: 0.1 })
|
||||
);
|
||||
scene.add(cube);
|
||||
|
||||
const target = new THREE.Vector3(0, 0, 0);
|
||||
|
||||
const cameraPresets = {
|
||||
front: new THREE.Vector3(0, 1.2, 6.5),
|
||||
side: new THREE.Vector3(6.5, 1.4, 0),
|
||||
topAngled: new THREE.Vector3(3.8, 5.4, 4.2),
|
||||
};
|
||||
|
||||
let activePreset = "front";
|
||||
let desiredPosition = cameraPresets.front.clone();
|
||||
camera.position.copy(desiredPosition);
|
||||
camera.lookAt(target);
|
||||
|
||||
const presetButtons = Array.from(document.querySelectorAll(".preset-btn"));
|
||||
|
||||
function setActiveButton(presetName) {
|
||||
presetButtons.forEach((button) => {
|
||||
const isActive = button.dataset.preset === presetName;
|
||||
button.classList.toggle("active", isActive);
|
||||
});
|
||||
}
|
||||
|
||||
function switchCameraPreset(presetName) {
|
||||
const nextPreset = cameraPresets[presetName];
|
||||
if (!nextPreset) {
|
||||
return;
|
||||
}
|
||||
|
||||
activePreset = presetName;
|
||||
desiredPosition = nextPreset.clone();
|
||||
setActiveButton(activePreset);
|
||||
}
|
||||
|
||||
presetButtons.forEach((button) => {
|
||||
button.addEventListener("click", () => {
|
||||
const presetName = button.dataset.preset;
|
||||
switchCameraPreset(presetName);
|
||||
});
|
||||
});
|
||||
|
||||
window.addEventListener("keydown", (event) => {
|
||||
if (event.key === "1") {
|
||||
switchCameraPreset("front");
|
||||
}
|
||||
if (event.key === "2") {
|
||||
switchCameraPreset("side");
|
||||
}
|
||||
if (event.key === "3") {
|
||||
switchCameraPreset("topAngled");
|
||||
}
|
||||
});
|
||||
|
||||
setActiveButton(activePreset);
|
||||
|
||||
function animate() {
|
||||
|
||||
camera.position.lerp(desiredPosition, 0.08);
|
||||
camera.lookAt(target);
|
||||
|
||||
renderer.render(scene, camera);
|
||||
}
|
||||
|
||||
renderer.setAnimationLoop(animate);
|
||||
|
||||
window.addEventListener("resize", () => {
|
||||
camera.aspect = window.innerWidth / window.innerHeight;
|
||||
camera.updateProjectionMatrix();
|
||||
renderer.setSize(window.innerWidth, window.innerHeight);
|
||||
});
|
||||
Loading…
x
Reference in New Issue
Block a user