토론

회전하는 3D 와이어프레임 큐브

Wikiprompt, 무료 프롬프트 백과사전에서

Alex Prompter

2025년 8월 15일

회전하는 3D 와이어프레임 큐브 Canvas 2D만 사용하여 WebGL 없이 원근감 있게 회전하는 3D 와이어프레임 큐브를 생성하는 프롬프트.

관련 미디어

프롬프트 내용저장

🌐
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>3D wireframe cube · canvas 2d</title> <style> body { background: #0b0e14; margin: 0; min-height: 100vh; display: flex; align-items: center; justify-content: center; } .container { background: #1a1f2a; padding: 1.5rem; border-radius: 1.5rem; box-shadow: 0 20px 40px rgba(0,0,0,0.6); } canvas { display: block; width: 480px; height: 480px; border-radius: 0.8rem; background: #10141c; box-shadow: inset 0 0 30px rgba(0,0,0,0.5); } .info { text-align: center; margin-top: 0.8rem; font-family: 'Segoe UI', Roboto, system-ui, sans-serif; color: #a8b3c0; font-size: 0.9rem; letter-spacing: 0.5px; } .info span { color: #6fc3df; font-weight: 500; } </style> </head> <body> <div class="container"> <canvas id="cubeCanvas" width="480" height="480"></canvas> <div class="info">wireframe cube · <span>canvas 2d</span> · slow rotation</div> </div> <script> (function() { const canvas = document.getElementById('cubeCanvas'); const ctx = canvas.getContext('2d'); // ---------- fixed perspective parameters ---------- const W = canvas.width; const H = canvas.height; const CX = W / 2; const CY = H / 2; // camera distance (perspective strength) const VIEW_DIST = 4.2; // larger = flatter, smaller = more perspective const SCALE = 1.9; // base scale factor (fits cube nicely) // ---------- cube vertices (unit cube centered at origin) ---------- // 8 vertices: x,y,z in [-1, 1] const VERTICES = [ [-1, -1, -1], // 0 [ 1, -1, -1], // 1 [ 1, 1, -1], // 2 [-1, 1, -1], // 3 [-1, -1, 1], // 4 [ 1, -1, 1], // 5 [ 1, 1, 1], // 6 [-1, 1, 1] // 7 ]; // ---------- edges (12 lines) ---------- const EDGES = [ [0, 1], [1, 2], [2, 3], [3, 0], // back face [4, 5], [5, 6], [6, 7], [7, 4], // front face [0, 4], [1, 5], [2, 6], [3, 7] // connecting edges ]; // ---------- rotation state (slow) ---------- let angleX = 0.0; let angleY = 0.0; const ROT_SPEED_X = 0.0022; // radians per frame (slow) const ROT_SPEED_Y = 0.0017; // ---------- projection: rotate -> perspective -> screen ---------- function project(vertex, rotX, rotY) { // 1. rotate around Y axis const x0 = vertex[0]; const y0 = vertex[1]; const z0 = vertex[2]; const cosY = Math.cos(rotY); const sinY = Math.sin(rotY); const x1 = x0 * cosY + z0 * sinY; const z1 = -x0 * sinY + z0 * cosY; const y1 = y0; // unchanged by Y rotation // 2. rotate around X axis const cosX = Math.cos(rotX); const sinX = Math.sin(rotX); const y2 = y1 * cosX - z1 * sinX; const z2 = y1 * sinX + z1 * cosX; const x2 = x1; // unchanged by X rotation // 3. perspective projection (z is depth) // camera looks along +Z? we want classic: z goes into screen. // we use perspective factor = VIEW_DIST / (VIEW_DIST + z2) // but we want cube to be visible: use z2 in range [-sqrt(3), sqrt(3)] // we shift to make it comfortable: add 3.0 to depth so it's always positive. const depth = VIEW_DIST + z2 * 0.9; // z2 in [-1.73, 1.73] -> depth in [2.5, 5.8] const perspective = VIEW_DIST / depth; // 4. scale and center const screenX = CX + x2 * SCALE * perspective * 100; // 100 = pixel factor const screenY = CY - y2 * SCALE * perspective * 100; // minus because y goes down return { x: screenX, y: screenY }; } // ---------- render frame ---------- function draw() { ctx.clearRect(0, 0, W, H); // subtle grid (optional, for depth perception) ctx.strokeStyle = '#2a3342'; ctx.lineWidth = 0.6; for (let i = -4; i <= 4; i++) { const offset = i * 30; ctx.beginPath(); ctx.moveTo(CX + offset, 0); ctx.lineTo(CX + offset, H); ctx.strokeStyle = '#202a38'; ctx.stroke(); ctx.beginPath(); ctx.moveTo(0, CY + offset); ctx.lineTo(W, CY + offset); ctx.strokeStyle = '#202a38'; ctx.stroke(); } // project all vertices const projected = VERTICES.map(v => project(v, angleX, angleY)); // draw edges (lines) with subtle glow effect ctx.lineWidth = 2.0; ctx.lineJoin = 'round'; ctx.lineCap = 'round'; // first pass: darker underlay for glow ctx.strokeStyle = '#3d4f66'; ctx.lineWidth = 3.5; for (const [i, j] of EDGES) { const p1 = projected[i]; const p2 = projected[j]; ctx.beginPath(); ctx.moveTo(p1.x, p1.y); ctx.lineTo(p2.x, p2.y); ctx.stroke(); } // second pass: bright core lines ctx.strokeStyle = '#b8d8f0'; ctx.lineWidth = 1.6; for (const [i, j] of EDGES) { const p1 = projected[i]; const p2 = projected[j]; ctx.beginPath(); ctx.moveTo(p1.x, p1.y); ctx.lineTo(p2.x, p2.y); ctx.stroke(); } // draw vertices as small dots (helps spatial orientation) ctx.fillStyle = '#e0f0ff'; ctx.shadowColor = '#7fc4ff'; ctx.shadowBlur = 6; for (const p of projected) { ctx.beginPath(); ctx.arc(p.x, p.y, 3.2, 0, 2 * Math.PI); ctx.fill(); } ctx.shadowBlur = 0; // reset for next frame // update rotation (slow) angleX += ROT_SPEED_X; angleY += ROT_SPEED_Y; requestAnimationFrame(draw); } // start animation draw(); })(); </script> </body> </html>

전체 프롬프트를 보려면 로그인하세요

Continue with:

By logging in, you agree to our Terms of Use and Privacy Policy

사용법

이 프롬프트는 coding와 함께 사용하도록 설계되었습니다. 위의 프롬프트 내용을 복사하여 원하는 AI 도구에 붙여넣으세요.

최상의 결과를 얻으려면 자리 표시자(대괄호 또는 대문자로 표시)를 특정 요구 사항으로 사용자 지정할 수 있습니다.

참고 자료

분류:coding| twitter| html| css

토론