Liveweave: Generative AI Web Editor & HTML/CSS/JS Playground
Initializing
Liveweave
Web
expand_more
home
Home
Palette
Color Explorer
arrow_outward
Polyline
Graphics Editor
arrow_outward
frame_source
Python Playground
arrow_outward
build
Tools
expand_more
restart_alt
Load "Hello Weaver!"
post_add
Generate Lorem ipsum...
code
Format HTML
code_blocks
Format CSS
data_object
Format JavaScript
library_add
Library
expand_more
A
Algolia JS
Animate CSS
Apex Charts JS
B
Bulma CSS
Bootstrap
C
Chart JS
Chartist
Create JS
D
D3
Dojo
F
Foundation
Fullpage JS
G
Granim JS
Google Charts
H
Halfmoon
J
jQuery
M
Materialize
Moment JS
Masonry JS
Milligram CSS
P
Pure CSS
Primer CSS
Popper JS
Pattern CSS
Picnic CSS
R
React JS
Raphael JS
Raisin CSS
S
Semantic UI
Skeleton CSS
Spectre CSS
Tachyons CSS
T
Tailwind
Three JS
U
UI Kit
Vis JS
W
Water CSS
download
Download
expand_more
developer_mode
Download as HTML
folder_zip
Download as .ZIP
cloud_upload
Fork
account_circle
Login
settings
Settings
expand_more
Editor font
14
px
A
A
Night mode
Line number
Mini map
Word wrap
sync_alt
Reset Settings
smart_display
Run
left_panel_close
AI Assistant
dashboard
All
HTML
CSS
JS
visibility
Preview
bolt
Live Preview
terminal
JS Console
<!DOCTYPE html> <html> <head> <title>Interactive 3D villa</title> </head> <body> <!-- Start your code here --> <div id="villa-app"> <div id="scene3d"></div> <div class="top-ui"> <div class="brand"> <span class="eyebrow">ARCHITECTURAL VISUALIZATION / 001</span> <h1>CASA <em>VERDE</em></h1> <p>A modern retreat in nature.</p> </div> <div class="scene-status"> <span class="live-dot"></span> REAL-TIME 3D </div> </div> <div class="bottom-ui"> <div class="control-panel"> <div class="panel-label">ENVIRONMENT</div> <div class="button-row"> <button id="dayBtn" class="active">☀ Day</button> <button id="nightBtn">☾ Night</button> </div> <div class="separator"></div> <div class="button-row"> <button id="orbitBtn">Auto Orbit</button> <button id="resetBtn">Reset View</button> </div> </div> <div class="scene-info"> <span>01 / MODERN VILLA</span> <span>DRAG TO ROTATE · SCROLL TO ZOOM</span> </div> </div> <div id="loading">BUILDING 3D ENVIRONMENT...</div> </div> <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/0.152.2/three.min.js"></script> <!-- End your code here --> </body> </html>
@import url('https://fonts.googleapis.com/css2?family=DM+Mono:wght@400;500&family=Manrope:wght@400;500;600;700;800&display=swap'); * { box-sizing: border-box; } html, body { margin: 0; width: 100%; height: 100%; overflow: hidden; } body { font-family: 'Manrope', sans-serif; background: #dce5e4; color: #263b36; } #villa-app { position: relative; width: 100%; height: 100vh; min-height: 450px; overflow: hidden; background: #dce5e4; } #scene3d { position: absolute; inset: 0; } #scene3d canvas { display: block; width: 100%; height: 100%; cursor: grab; touch-action: none; } #scene3d canvas:active { cursor: grabbing; } .top-ui { position: absolute; z-index: 5; top: 0; left: 0; right: 0; padding: 30px 38px; display: flex; justify-content: space-between; align-items: flex-start; pointer-events: none; } .eyebrow, .scene-status, .panel-label, .scene-info, #loading { font-family: 'DM Mono', monospace; font-size: 9px; letter-spacing: 1.5px; } .eyebrow { color: #688078; } .brand h1 { font-size: clamp(27px, 3vw, 43px); letter-spacing: -2px; line-height: 1; margin: 12px 0 8px; font-weight: 800; } .brand h1 em { font-weight: 500; font-style: normal; color: #719486; } .brand p { margin: 0; font-size: 12px; color: #71857d; } .scene-status { display: flex; align-items: center; gap: 9px; background: rgba(255,255,255,.65); padding: 12px 15px; border-radius: 30px; backdrop-filter: blur(12px); } .live-dot { width: 7px; height: 7px; border-radius: 50%; background: #4e9470; box-shadow: 0 0 0 4px rgba(78,148,112,.12); } .bottom-ui { position: absolute; z-index: 5; left: 38px; right: 38px; bottom: 27px; display: flex; align-items: flex-end; justify-content: space-between; pointer-events: none; gap: 20px; } .control-panel { width: 285px; padding: 18px; background: rgba(255,255,255,.84); border: 1px solid rgba(255,255,255,.85); border-radius: 15px; box-shadow: 0 12px 40px rgba(30,50,45,.1); backdrop-filter: blur(18px); pointer-events: auto; } .panel-label { color: #82938a; margin-bottom: 13px; } .button-row { display: flex; gap: 7px; } .button-row button { flex: 1; min-width: 0; padding: 11px 9px; border: 1px solid #dce3de; border-radius: 8px; background: #f6f8f5; color: #53665d; font-family: inherit; font-size: 11px; font-weight: 700; cursor: pointer; transition: .2s ease; } .button-row button:hover { background: #e9eee9; transform: translateY(-1px); } .button-row button.active { background: #2d4a3e; color: white; border-color: #2d4a3e; } .separator { height: 1px; background: #e1e7e2; margin: 14px 0; } .scene-info { text-align: right; color: #536f66; line-height: 2; text-shadow: 0 1px 8px rgba(255,255,255,.8); } .scene-info span { display: block; } #loading { position: absolute; z-index: 10; inset: 0; display: grid; place-items: center; background: #dce5e4; color: #526b61; } @media(max-width: 650px) { .top-ui { padding: 20px; } .scene-status { display: none; } .bottom-ui { left: 15px; right: 15px; bottom: 15px; justify-content: center; } .control-panel { width: min(100%, 350px); } .scene-info { display: none; } }
(function () { const container = document.getElementById("scene3d"); const loading = document.getElementById("loading"); if (!window.THREE) { loading.textContent = "THREE.JS COULD NOT LOAD. CHECK CDN ACCESS."; return; } const T = THREE; const scene = new T.Scene(); scene.background = new T.Color(0xdce8ec); scene.fog = new T.Fog(0xdce8ec, 45, 105); const camera = new T.PerspectiveCamera(42, 1, .1, 200); const renderer = new T.WebGLRenderer({ antialias: true, alpha: false }); renderer.setPixelRatio(Math.min(devicePixelRatio, 2)); renderer.shadowMap.enabled = true; renderer.shadowMap.type = T.PCFSoftShadowMap; renderer.outputColorSpace = T.SRGBColorSpace; renderer.toneMapping = T.ACESFilmicToneMapping; renderer.toneMappingExposure = 1.15; container.appendChild(renderer.domElement); // MATERIALS function mat(color, roughness = .8, metalness = 0) { return new T.MeshStandardMaterial({ color, roughness, metalness }); } const concrete = mat(0xd8d6cd, .88); const white = mat(0xf0eee5, .75); const dark = mat(0x343d3b, .38, .45); const wood = mat(0x997452, .78); const woodLight = mat(0xb38b62, .8); const grass = mat(0x78966d, 1); const stone = mat(0xb6b5a9, 1); const road = mat(0x8e9189, 1); const soil = mat(0x675947, 1); const foliage = [ mat(0x4e7650), mat(0x648b5b), mat(0x789c68), mat(0x3d6848) ]; const glass = new T.MeshPhysicalMaterial({ color: 0x8fb5bb, metalness: .1, roughness: .08, transparent: true, opacity: .32, depthWrite: false, side: T.DoubleSide }); const waterMat = new T.MeshPhysicalMaterial({ color: 0x3babb5, metalness: .15, roughness: .17, transparent: true, opacity: .82, side: T.DoubleSide }); // HELPERS function box(w, h, d, material, x, y, z, parent = scene) { const mesh = new T.Mesh( new T.BoxGeometry(w, h, d), material ); mesh.position.set(x, y, z); mesh.castShadow = true; mesh.receiveShadow = true; parent.add(mesh); return mesh; } function cylinder(rt, rb, h, material, x, y, z, sides = 16) { const mesh = new T.Mesh( new T.CylinderGeometry(rt, rb, h, sides), material ); mesh.position.set(x, y, z); mesh.castShadow = true; mesh.receiveShadow = true; scene.add(mesh); return mesh; } function sphere(r, material, x, y, z, detail = 12) { const mesh = new T.Mesh( new T.SphereGeometry(r, detail, 9), material ); mesh.position.set(x, y, z); mesh.castShadow = true; mesh.receiveShadow = true; scene.add(mesh); return mesh; } function plane(w, h, material, x, y, z) { const mesh = new T.Mesh( new T.PlaneGeometry(w, h), material ); mesh.rotation.x = -Math.PI / 2; mesh.position.set(x, y, z); mesh.receiveShadow = true; scene.add(mesh); return mesh; } // LIGHTING const hemi = new T.HemisphereLight(0xe8f3ff, 0x71816d, 2); scene.add(hemi); const sun = new T.DirectionalLight(0xffefda, 3.2); sun.position.set(-14, 24, 12); sun.castShadow = true; sun.shadow.mapSize.set(2048, 2048); sun.shadow.camera.left = -28; sun.shadow.camera.right = 28; sun.shadow.camera.top = 28; sun.shadow.camera.bottom = -28; sun.shadow.normalBias = .025; scene.add(sun); // LANDSCAPE plane(200, 200, mat(0x839d76), 0, -.12, 0); box(34, .35, 29, soil, 0, -.2, 0); box(33.5, .13, 28.5, grass, 0, .02, 0); // Main building platform box(16.5, .35, 11.5, concrete, -2, .2, -2); // Ground floor architectural mass box(12.8, 3.6, 8.5, white, -2.3, 2.1, -2.4); // Dark facade recess box(11.7, 3.0, .16, dark, -2.3, 2.05, 1.94); // Large glazing across ground floor for (let i = 0; i < 5; i++) { const x = -7.25 + i * 2.45; box(2.34, 2.72, .045, glass, x, 2.05, 2.05); box(.055, 2.85, .10, dark, x + 1.2, 2.05, 2.09); } box(12.7, .12, .28, dark, -2.3, 3.5, 2.12); box(12.7, .12, .28, dark, -2.3, .6, 2.12); // Upper floor, offset to create a cantilever box(12.2, 3.0, 7.4, concrete, -1.1, 5.5, -2.9); // Upper dark recessed facade box(10.6, 2.42, .13, dark, -1.1, 5.5, .86); // Upper glazing for (let i = 0; i < 4; i++) { const x = -5.1 + i * 2.65; box(2.52, 2.28, .045, glass, x, 5.5, .97); box(.055, 2.4, .1, dark, x + 1.31, 5.5, 1); } // Upper-level side windows for (let i = 0; i < 3; i++) { box(.045, 1.8, 1.25, glass, 5.05, 5.5, -5 + i * 1.8); } // Roof slab box(13, .38, 8.2, white, -1.1, 7.17, -2.9); // Roof parapet box(13, .65, .18, concrete, -1.1, 7.65, -7); box(.18, .65, 8.2, concrete, -7.55, 7.65, -2.9); box(.18, .65, 8.2, concrete, 5.35, 7.65, -2.9); // Architectural wood slats for (let i = 0; i < 12; i++) { box(.09, 2.7, .19, wood, 4.65 + i * .105, 5.55, 1.04); } // Side wood accent wall box(.2, 2.8, 4.5, wood, -8.75, 2.1, -2.5); for (let i = 0; i < 16; i++) { box(.05, 2.8, .055, woodLight, -8.62, 2.1, -4.6 + i * .27); } // Front canopy box(7.8, .22, 3.1, dark, -3.4, 3.9, 3.4); for (const x of [-6.9, -.2]) { box(.13, 3.6, .13, dark, x, 1.95, 4.8); } // Rooftop terrace glass railing for (let i = 0; i < 8; i++) { box(1.5, .75, .045, glass, -6.55 + i * 1.55, 7.73, 1.12); } // INTERIOR DETAILS const warmLight = new T.MeshStandardMaterial({ color: 0xffd4a0, emissive: 0xffb45a, emissiveIntensity: .3 }); // Visible internal floors and walls box(11.6, .1, 7.7, woodLight, -2.3, .52, -2.4); box(11.3, .08, 6.9, woodLight, -1.1, 4.02, -2.9); // Ground-floor sofa box(3.2, .5, 1.2, mat(0xd4c8b6), -3.8, 1.03, -1.3); box(3.2, .75, .25, mat(0xc8baa5), -3.8, 1.45, -1.85); // Coffee table box(1.7, .12, 1, wood, -3.8, 1.1, .3); for (const x of [-4.5, -3.1]) { for (const z of [-.05, .65]) { box(.08, .5, .08, dark, x, .8, z); } } // Interior pendant lamps for (const x of [-4, 0, 3]) { cylinder(.04, .04, .9, dark, x, 2.85, -1.2); sphere(.19, warmLight, x, 2.35, -1.2); } // POOL AND DECK box(13.2, .22, 7.2, stone, 4.2, .12, 7.8); // Pool basin box(10.5, .17, 5.6, mat(0x387d87), 4.2, .22, 7.8); const pool = plane(10.25, 5.35, waterMat, 4.2, .315, 7.8); // Pool perimeter box(10.7, .12, .25, white, 4.2, .37, 4.98); box(10.7, .12, .25, white, 4.2, .37, 10.62); box(.25, .12, 5.7, white, -1.1, .37, 7.8); box(.25, .12, 5.7, white, 9.5, .37, 7.8); // Pool steps for (let i = 0; i < 3; i++) { box(1.8, .06, .38, white, -1 + i * .15, .34 - i * .035, 5.65 + i * .4); } // LOUNGERS function lounger(x, z) { const frame = box(.95, .13, 2.2, wood, x, .42, z); box(.84, .12, 1.2, mat(0xe2dfd2), x, .53, z + .4); const back = box(.84, .12, 1.05, mat(0xe2dfd2), x, .86, z - .55); back.rotation.x = -.65; for (const dx of [-.38, .38]) { box(.07, .35, .07, dark, x + dx, .23, z + .7); box(.07, .35, .07, dark, x + dx, .23, z - .7); } } lounger(11.3, 5.8); lounger(13, 5.8); // OUTDOOR DINING cylinder(1.1, 1.1, .12, woodLight, -6.3, .85, 6.8); cylinder(.08, .08, .65, dark, -6.3, .48, 6.8); for (let i = 0; i < 4; i++) { const a = i * Math.PI / 2; const x = -6.3 + Math.cos(a) * 1.7; const z = 6.8 + Math.sin(a) * 1.7; const seat = box(.65, .12, .65, wood, x, .55, z); seat.rotation.y = -a; for (const dx of [-.22, .22]) { box(.055, .43, .055, dark, x + dx, .29, z); } } // GARDEN PATH for (let i = 0; i < 7; i++) { box(1.6, .07, .9, stone, -9.8, .13, 1 + i * 1.15); } // TREES function tree(x, z, size = 1) { const height = 2.5 * size; cylinder(.15 * size, .23 * size, height, wood, x, height / 2, z); const crown = new T.Group(); scene.add(crown); const layers = [ [0, 0, 0, 1.3], [-.65, -.25, .15, .9], [.7, -.1, .1, 1], [0, .7, -.3, 1], [.1, -.4, .65, .85] ]; layers.forEach((v, i) => { sphere(v[3] * size, foliage[i % foliage.length], x + v[0] * size, height + .6 * size + v[1] * size, z + v[2] * size, 10); }); } tree(-13, -8, 1.3); tree(-13.5, 5, 1); tree(13, -8, 1.4); tree(15, 2, .85); tree(12, 12, .8); tree(-12, 11, 1.1); // SHRUBS let seed = 42; function random() { seed = (seed * 1664525 + 1013904223) >>> 0; return seed / 4294967296; } for (let i = 0; i < 65; i++) { const x = (random() - .5) * 31; const z = (random() - .5) * 26; // Avoid the house and swimming pool. if (x > -10 && x < 11 && z > -8 && z < 12) continue; const r = .18 + random() * .32; sphere(r, foliage[i % foliage.length], x, r * .7, z, 8); } // DECORATIVE PLANTERS function planter(x, z) { cylinder(.46, .36, .7, concrete, x, .42, z); cylinder(.13, .13, .55, wood, x, 1.0, z); for (let i = 0; i < 6; i++) { const a = i * Math.PI / 3; sphere(.35, foliage[i % 4], x + Math.cos(a) * .22, 1.25 + (i % 2) * .2, z + Math.sin(a) * .22, 8); } } planter(-7.5, 4.7); planter(-.2, 4.8); planter(7.2, -6.4); // GARDEN LIGHTS const gardenLights = []; const lampGlow = new T.MeshStandardMaterial({ color: 0xffe3a9, emissive: 0xffb85b, emissiveIntensity: .2 }); function gardenLamp(x, z) { cylinder(.07, .09, .65, dark, x, .4, z); sphere(.13, lampGlow, x, .77, z, 12); const light = new T.PointLight(0xffbc77, 0, 5); light.position.set(x, .9, z); scene.add(light); gardenLights.push(light); } for (let i = 0; i < 6; i++) { gardenLamp(-8.6, 1 + i * 1.35); } gardenLamp(10.5, 4.3); gardenLamp(10.5, 11.2); // CAMERA CONTROLS const target = new T.Vector3(0, 2.1, 0); let azimuth = .75; let elevation = .42; let distance = 32; let dragging = false; let lastX = 0; let lastY = 0; let autoOrbit = false; let night = false; const canvas = renderer.domElement; function updateCamera() { camera.position.set( target.x + distance * Math.cos(elevation) * Math.sin(azimuth), target.y + distance * Math.sin(elevation), target.z + distance * Math.cos(elevation) * Math.cos(azimuth) ); camera.lookAt(target); } canvas.addEventListener("pointerdown", e => { dragging = true; autoOrbit = false; document.getElementById("orbitBtn") .classList.remove("active"); lastX = e.clientX; lastY = e.clientY; canvas.setPointerCapture(e.pointerId); }); canvas.addEventListener("pointermove", e => { if (!dragging) return; azimuth -= (e.clientX - lastX) * .006; elevation += (e.clientY - lastY) * .005; elevation = T.MathUtils.clamp(elevation, .12, 1.3); lastX = e.clientX; lastY = e.clientY; }); canvas.addEventListener("pointerup", () => { dragging = false; }); canvas.addEventListener("pointercancel", () => { dragging = false; }); canvas.addEventListener("wheel", e => { e.preventDefault(); distance = T.MathUtils.clamp( distance + e.deltaY * .025, 15, 65 ); }, { passive: false }); // BUTTONS const dayBtn = document.getElementById("dayBtn"); const nightBtn = document.getElementById("nightBtn"); const orbitBtn = document.getElementById("orbitBtn"); function setNight(value) { night = value; dayBtn.classList.toggle("active", !night); nightBtn.classList.toggle("active", night); scene.background.set(night ? 0x182633 : 0xdce8ec); scene.fog.color.set(night ? 0x182633 : 0xdce8ec); hemi.intensity = night ? .55 : 2; sun.intensity = night ? .18 : 3.2; renderer.toneMappingExposure = night ? .85 : 1.15; gardenLights.forEach(light => { light.intensity = night ? 3 : 0; }); warmLight.emissiveIntensity = night ? 2.5 : .3; lampGlow.emissiveIntensity = night ? 2 : .2; } dayBtn.addEventListener("click", () => setNight(false)); nightBtn.addEventListener("click", () => setNight(true)); orbitBtn.addEventListener("click", () => { autoOrbit = !autoOrbit; orbitBtn.classList.toggle("active", autoOrbit); }); document.getElementById("resetBtn") .addEventListener("click", () => { azimuth = .75; elevation = .42; distance = 32; autoOrbit = false; orbitBtn.classList.remove("active"); }); // RESPONSIVE RENDERING function resize() { const w = container.clientWidth; const h = container.clientHeight; if (!w || !h) return; camera.aspect = w / h; camera.updateProjectionMatrix(); renderer.setSize(w, h); } window.addEventListener("resize", resize); resize(); updateCamera(); // ANIMATION const clock = new T.Clock(); let time = 0; function animate() { requestAnimationFrame(animate); const delta = Math.min(clock.getDelta(), .05); time += delta; if (autoOrbit && !dragging) { azimuth += delta * .12; } // Gentle water shimmer waterMat.roughness = .13 + Math.sin(time * 1.8) * .035; pool.position.y = .315 + Math.sin(time * 1.3) * .009; updateCamera(); renderer.render(scene, camera); } animate(); loading.style.display = "none"; })();
terminal
JavaScript Console
Preview
Clear
close
›
Run