Meta Description" name="description" />

Share this result

Previews are deleted daily. Get a permanent share link sent to your inbox:
Script
<!DOCTYPE html> <html lang="id"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no"> <title>Simulasi 3D Tracking Conveyor Belt</title> <style> *{margin:0;padding:0;box-sizing:border-box} html,body{width:100%;height:100%;overflow:hidden;background:#0d1117;font-family:Arial,Helvetica,sans-serif;color:#e6edf3} #scene{position:fixed;inset:0;display:block;touch-action:none} #title{position:fixed;top:0;left:0;right:0;padding:8px 12px;background:rgba(13,17,23,.85);font-size:14px;font-weight:bold;text-align:center;border-bottom:1px solid #30363d;z-index:5} #hud{position:fixed;z-index:6;background:rgba(22,27,34,.94);border:1px solid #30363d;border-radius:10px;padding:12px;width:300px;top:46px;right:12px} #hud h3{font-size:13px;color:#ff6b6b;margin-bottom:8px} .ctl{margin:9px 0} .ctl label{display:block;font-size:12px;margin-bottom:3px} .ctl .v{float:right;font-weight:bold} .ctl input{width:100%} #t1{color:#ff6b6b}#t2{color:#4dd0e1}#t3{color:#69db7c} .btn{margin:4px 3px 0 0;padding:6px 10px;border:none;border-radius:6px;background:#e63946;color:#fff;font-size:12px;cursor:pointer} .btn.alt{background:#30363d} .btn:active{opacity:.7} #status{margin-top:10px;padding:8px;background:#0d1117;border-radius:6px;font-size:12px;line-height:1.5;border:1px solid #30363d} #hint{margin-top:8px;font-size:11px;color:#8b949e;line-height:1.5} #zoom{position:fixed;left:12px;bottom:12px;z-index:6;display:flex;flex-direction:column;gap:6px} #zoom button{width:40px;height:40px;font-size:20px;border:1px solid #30363d;background:rgba(22,27,34,.94);color:#e6edf3;border-radius:8px;cursor:pointer} #loading{position:fixed;inset:0;display:flex;align-items:center;justify-content:center;background:#0d1117;z-index:20;font-size:14px} @media(max-width:820px){ #hud{top:auto;right:8px;left:8px;bottom:8px;width:auto;max-height:52vh;overflow-y:auto} #zoom{left:8px;bottom:auto;top:52px;flex-direction:row} } </style> </head> <body> <div id="title">⚙️ Simulasi 3D Tracking Conveyor Belt — Muatan Ore</div> <canvas id="scene"></canvas> <div id="zoom"> <button onclick="zoomBy(0.82)">+</button> <button onclick="zoomBy(1.22)">-</button> </div> <div id="hud"> <h3>🔧 Panel Penyetelan</h3> <div class="ctl"><label id="t1">Upper Roller (idler atas) <span class="v" id="vU">0</span></label> <input type="range" id="sU" min="-30" max="30" value="0"></div> <div class="ctl"><label id="t2">Lower Roller (return) <span class="v" id="vL">0</span></label> <input type="range" id="sL" min="-30" max="30" value="0"></div> <div class="ctl"><label id="t3">Tail Pulley <span class="v" id="vT">0</span></label> <input type="range" id="sT" min="-30" max="30" value="0"></div> <button class="btn" onclick="setMiring()">⚠️ Simulasi Belt Miring</button> <button class="btn alt" onclick="resetAll()">🔄 Reset</button> <div id="status">Status: Belt lurus ✅ — ore berjalan normal</div> <div id="hint"> • Geser slider → hanya bagian itu yang bergerak, lalu berhenti<br> • Bagian aktif disorot <b style="color:#ff4d4d">merah</b> + garis bantu <b style="color:#ffd43b">kuning</b><br> • Pinch = zoom · 1 jari = putar · 2 jari = geser </div> </div> <div id="loading">Memuat mesin 3D…</div> <script src=""></script> <script src=""></script> <script> /* ============ SETUP ============ */ const D2R = Math.PI/180, TROUGH = 35*D2R; let scene,camera,renderer,controls,clock; let carryBelt,returnBelt,carryTex,returnTex; let idlerSets=[],returnRollers=[],tailGroup=null; let oreRocks=[],spills=[],arrows=[]; let guides={upper:null,lower:null,tail:null}; const S={ tU:0,tL:0,tT:0, cU:0,cL:0,cT:0, active:null, activeUntil:0 }; const MAT={ roller : new THREE.MeshStandardMaterial({color:0x9aa3ad,metalness:.85,roughness:.35}), hot : new THREE.MeshStandardMaterial({color:0xff3b30,emissive:0x5a0a06,metalness:.5,roughness:.4}), housing: new THREE.MeshStandardMaterial({color:0x30363d,metalness:.6,roughness:.6}), steel : new THREE.MeshStandardMaterial({color:0x4a525c,metalness:.7,roughness:.5}), belt : null, ore:[ new THREE.MeshStandardMaterial({color:0x8b7355,roughness:.95}), new THREE.MeshStandardMaterial({color:0x6b5b3e,roughness:.95}), new THREE.MeshStandardMaterial({color:0xa0926b,roughness:.95}) ] }; function beltTexture(){ const c=document.createElement('canvas');c.width=128;c.height=64; const g=c.getContext('2d'); g.fillStyle='#26262b';g.fillRect(0,0,128,64); g.strokeStyle='#33333a';g.lineWidth=7; for(let i=-64;i<160;i+=30){g.beginPath();g.moveTo(i,0);g.lineTo(i+22,64);g.stroke();} g.fillStyle='#1c1c20';g.fillRect(0,0,128,3);g.fillRect(0,61,128,3); const t=new THREE.CanvasTexture(c); t.wrapS=t.wrapT=THREE.RepeatWrapping; return t; } function label(text,color){ const c=document.createElement('canvas');c.width=256;c.height=64; const g=c.getContext('2d'); g.fillStyle='rgba(13,17,23,.75)';g.fillRect(0,0,256,64); g.font='bold 26px Arial';g.fillStyle=color;g.textAlign='center'; g.fillText(text,128,42); const sp=new THREE.Sprite(new THREE.SpriteMaterial({map:new THREE.CanvasTexture(c),transparent:true,depthTest:false})); sp.scale.set(3.6,0.9,1); return sp; } /* ============ BUILD ============ */ function init(){ scene=new THREE.Scene(); scene.background=new THREE.Color(0x0d1117); scene.fog=new THREE.Fog(0x0d1117,40,90); camera=new THREE.PerspectiveCamera(45,innerWidth/innerHeight,0.1,300); camera.position.set(16,11,17); renderer=new THREE.WebGLRenderer({canvas:document.getElementById('scene'),antialias:true}); renderer.setPixelRatio(Math.min(devicePixelRatio,2)); renderer.setSize(innerWidth,innerHeight); renderer.shadowMap.enabled=true; controls=new THREE.OrbitControls(camera,renderer.domElement); controls.target.set(0,1.4,0); controls.enableDamping=true;controls.dampingFactor=.08; controls.minDistance=6;controls.maxDistance=60; controls.maxPolarAngle=Math.PI/2.05; scene.add(new THREE.HemisphereLight(0xbfd4ff,0x20242b,0.75)); const dl=new THREE.DirectionalLight(0xffffff,1.0); dl.position.set(14,20,12);dl.castShadow=true; dl.shadow.mapSize.set(1024,1024); dl.shadow.camera.left=-22;dl.shadow.camera.right=22; dl.shadow.camera.top=22;dl.shadow.camera.bottom=-22; scene.add(dl); scene.add(new THREE.DirectionalLight(0x5b7fff,0.25).translateX(-15)); const ground=new THREE.Mesh(new THREE.PlaneGeometry(120,80), new THREE.MeshStandardMaterial({color:0x1a1f26,roughness:1})); ground.rotation.x=-Math.PI/2;ground.position.y=-1.2;ground.receiveShadow=true; scene.add(ground); const grid=new THREE.GridHelper(120,60,0x30363d,0x21262d); grid.position.y=-1.19;scene.add(grid); buildFrame(); buildPulleys(); buildIdlers(); buildReturnRollers(); buildBelts(); buildOre(); buildArrows(); buildLabels(); clock=new THREE.Clock(); document.getElementById('loading').style.display='none'; addEventListener('resize',onResize); animate(); } function buildFrame(){ const g=new THREE.Group(); [-1.95,1.95].forEach(z=>{ const beam=new THREE.Mesh(new THREE.BoxGeometry(27,0.3,0.22),MAT.steel); beam.position.set(0,1.15,z);beam.castShadow=true;g.add(beam); const beam2=new THREE.Mesh(new THREE.BoxGeometry(27,0.18,0.18),MAT.steel); beam2.position.set(0,-0.05,z);g.add(beam2); }); [-11,-5.5,0,5.5,11].forEach(x=>{ [-1.95,1.95].forEach(z=>{ const leg=new THREE.Mesh(new THREE.BoxGeometry(0.22,2.5,0.22),MAT.steel); leg.position.set(x,-0.05,z);leg.castShadow=true;g.add(leg); const lo=new THREE.Mesh(new THREE.BoxGeometry(0.2,1.15,0.2),MAT.steel); lo.position.set(x,-0.75,z*1.35);g.add(lo); }); const cross=new THREE.Mesh(new THREE.BoxGeometry(0.16,0.16,4.3),MAT.steel); cross.position.set(x,-0.05,0);g.add(cross); }); scene.add(g); } function pulley(radius,len){ const g=new THREE.Group(); const drum=new THREE.Mesh(new THREE.CylinderGeometry(radius,radius,len,28),MAT.roller); drum.rotation.x=Math.PI/2;drum.castShadow=true;g.add(drum); [-1,1].forEach(s=>{ const h=new THREE.Mesh(new THREE.BoxGeometry(radius*1.5,radius*1.9,0.42),MAT.housing); h.position.z=s*(len/2+0.28);g.add(h); const b=new THREE.Mesh(new THREE.CylinderGeometry(radius*0.34,radius*0.34,0.5,16),MAT.roller); b.rotation.x=Math.PI/2;b.position.z=s*(len/2+0.3);g.add(b); [[-1,-1],[1,-1],[-1,1],[1,1]].forEach(p=>{ const bolt=new THREE.Mesh(new THREE.CylinderGeometry(0.07,0.07,0.1,8), new THREE.MeshStandardMaterial({color:0xffd43b,metalness:.6,roughness:.4})); bolt.rotation.x=Math.PI/2; bolt.position.set(p[0]*radius*0.6,p[1]*radius*0.75,s*(len/2+0.5)); g.add(bolt); }); }); return g; } function buildPulleys(){ tailGroup=new THREE.Group(); tailGroup.position.set(-13,1.32,0); const p=pulley(0.72,3.3); tailGroup.add(p); tailGroup.userData.meshes=p.children.filter(c=>c.material===MAT.roller); guides.tail=makeGuide(0xffd43b,4.6); guides.tail.position.y=0.95; tailGroup.add(guides.tail); scene.add(tailGroup); const head=pulley(0.72,3.3); head.position.set(13,1.32,0); scene.add(head); const motor=new THREE.Mesh(new THREE.BoxGeometry(1.5,1.1,1.1),MAT.housing); motor.position.set(14.4,0.5,1.9);motor.castShadow=true;scene.add(motor); } function makeGuide(color,len){ const geo=new THREE.BufferGeometry().setFromPoints([ new THREE.Vector3(0,0,-len/2),new THREE.Vector3(0,0,len/2)]); const line=new THREE.Line(geo,new THREE.LineBasicMaterial({color,linewidth:2,transparent:true,opacity:.95})); line.visible=false; return line; } function buildIdlers(){ [-9.5,-5,0,5,9.5].forEach((x,i)=>{ const root=new THREE.Group();root.position.x=x; const pivot=new THREE.Group();root.add(pivot); const meshes=[]; const c=new THREE.Mesh(new THREE.CylinderGeometry(0.28,0.28,1.5,20),MAT.roller); c.rotation.x=Math.PI/2;c.position.y=1.72;c.castShadow=true; pivot.add(c);meshes.push(c); [-1,1].forEach(s=>{ const w=new THREE.Mesh(new THREE.CylinderGeometry(0.26,0.26,1.0,20),MAT.roller); w.rotation.x=Math.PI/2 - s*TROUGH; w.position.set(0, 1.72+0.5*Math.sin(TROUGH), s*(0.75+0.5*Math.cos(TROUGH))); w.castShadow=true;pivot.add(w);meshes.push(w); const br=new THREE.Mesh(new THREE.BoxGeometry(0.18,0.9,0.18),MAT.housing); br.position.set(0,1.4,s*1.75);pivot.add(br); }); const base=new THREE.Mesh(new THREE.BoxGeometry(0.2,0.16,4),MAT.housing); base.position.y=1.18;root.add(base); if(i===2){ guides.upper=makeGuide(0xffd43b,5.2); guides.upper.position.y=2.25; pivot.add(guides.upper); } root.userData={pivot,meshes}; idlerSets.push(root);scene.add(root); }); } function buildReturnRollers(){ [-8,-2.5,3,8.5].forEach((x,i)=>{ const root=new THREE.Group();root.position.x=x; const pivot=new THREE.Group();root.add(pivot); const r=new THREE.Mesh(new THREE.CylinderGeometry(0.26,0.26,3.3,20),MAT.roller); r.rotation.x=Math.PI/2;r.position.y=0.36;r.castShadow=true; pivot.add(r); if(i===1){ guides.lower=makeGuide(0xffd43b,5.0); guides.lower.position.y=0.7; pivot.add(guides.lower); } root.userData={pivot,meshes:[r]}; returnRollers.push(root);scene.add(root); }); } function buildBelts(){ carryTex=beltTexture();carryTex.repeat.set(14,1); returnTex=beltTexture();returnTex.repeat.set(14,1); const mC=new THREE.MeshStandardMaterial({map:carryTex,roughness:.85,metalness:.05,side:THREE.DoubleSide}); const mR=new THREE.MeshStandardMaterial({map:returnTex,roughness:.85,metalness:.05,side:THREE.DoubleSide}); carryBelt=new THREE.Group(); const mid=new THREE.Mesh(new THREE.PlaneGeometry(26,1.5),mC); mid.rotation.x=-Math.PI/2;mid.position.y=2.01;mid.receiveShadow=true; carryBelt.add(mid); [-1,1].forEach(s=>{ const w=new THREE.Mesh(new THREE.PlaneGeometry(26,1.0),mC); w.rotation.x=-Math.PI/2; w.rotation.y=0; w.rotation.z=0; w.geometry.rotateX(0); w.rotation.set(-Math.PI/2 + s*TROUGH*0, 0, 0); // tilt wing belt to match wing rollers w.rotation.x=-Math.PI/2; w.rotation.order='ZYX'; w.rotation.z=0; w.position.set(0, 2.01+0.5*Math.sin(TROUGH), s*(0.75+0.5*Math.cos(TROUGH))); w.rotateOnAxis(new THREE.Vector3(1,0,0), -s*TROUGH); w.receiveShadow=true; carryBelt.add(w); }); scene.add(carryBelt); returnBelt=new THREE.Group(); const rb=new THREE.Mesh(new THREE.PlaneGeometry(26,3.2),mR); rb.rotation.x=-Math.PI/2;rb.position.y=0.63;rb.receiveShadow=true; returnBelt.add(rb); scene.add(returnBelt); } function buildOre(){ const geos=[ new THREE.DodecahedronGeometry(0.22,0), new THREE.DodecahedronGeometry(0.17,0), new THREE.IcosahedronGeometry(0.2,0) ]; for(let i=0;i<190;i++){ const m=new THREE.Mesh(geos[i%3],MAT.ore[i%3]); const t=Math.random(); m.userData.z=(Math.random()-0.5)*1.5; m.userData.y=2.12+Math.random()*0.42*(1-Math.abs(m.userData.z)/0.9); m.position.set(-13+t*26, m.userData.y, m.userData.z); m.scale.setScalar(0.7+Math.random()*0.7); m.rotation.set(Math.random()*3,Math.random()*3,Math.random()*3); m.castShadow=true; oreRocks.push(m);scene.add(m); } for(let i=0;i<70;i++){ const m=new THREE.Mesh(geos[i%3],MAT.ore[i%3]); m.scale.setScalar(0.55);m.visible=false; m.userData.vy=0;m.userData.side=1; spills.push(m);scene.add(m); } } function buildArrows(){ const geo=new THREE.ConeGeometry(0.22,0.6,10); const mat=new THREE.MeshStandardMaterial({color:0x39d353,emissive:0x0f5c22,transparent:true,opacity:.9}); for(let s of [-1,1]){ for(let i=0;i<6;i++){ const a=new THREE.Mesh(geo,mat.clone()); a.rotation.z=-Math.PI/2; a.position.set(-11+i*4.4, 1.45, s*2.55); a.userData.phase=i*0.35; arrows.push(a);scene.add(a); } const bar=new THREE.Mesh(new THREE.BoxGeometry(24,0.06,0.06), new THREE.MeshStandardMaterial({color:0x1f7a35})); bar.position.set(-0.2,1.45,s*2.55);scene.add(bar); const sp=label('➡ ARAH BELT','#39d353'); sp.position.set(0,2.9,s*2.9);scene.add(sp); } } function buildLabels(){ const L=[ ['TAIL PULLEY','#69db7c',-13,0.2], ['HEAD PULLEY','#8b949e',13,0.2], ['UPPER ROLLER','#ff6b6b',0,3.35], ['LOWER ROLLER','#4dd0e1',-2.5,-0.35] ]; L.forEach(([t,c,x,y])=>{const s=label(t,c);s.position.set(x,y===0.2?0.15:y,0); if(t==='LOWER ROLLER'){s.position.set(-2.5,-0.4,2.6);} if(t==='UPPER ROLLER'){s.position.set(0,3.4,0);} if(t==='TAIL PULLEY'){s.position.set(-13,2.9,0);} if(t==='HEAD PULLEY'){s.position.set(13,2.9,0);} scene.add(s);}); } /* ============ INTERAKSI ============ */ const eU=document.getElementById('sU'),eL=document.getElementById('sL'),eT=document.getElementById('sT'); function touch(part){S.active=part;S.activeUntil=performance.now()+2600;} eU.addEventListener('input',()=>{S.tU=+eU.value;touch('upper');}); eL.addEventListener('input',()=>{S.tL=+eL.value;touch('lower');}); eT.addEventListener('input',()=>{S.tT=+eT.value;touch('tail');}); function resetAll(){eU.value=0;eL.value=0;eT.value=0;S.tU=S.tL=S.tT=0;touch('upper');} function setMiring(){eU.value=-18;eL.value=12;eT.value=22;S.tU=-18;S.tL=12;S.tT=22;touch('tail');} function zoomBy(f){ const d=camera.position.clone().sub(controls.target); const len=THREE.MathUtils.clamp(d.length()*f,controls.minDistance,controls.maxDistance); camera.position.copy(controls.target.clone().add(d.setLength(len))); } function onResize(){ camera.aspect=innerWidth/innerHeight;camera.updateProjectionMatrix(); renderer.setSize(innerWidth,innerHeight); } /* ============ LOOP ============ */ function animate(){ requestAnimationFrame(animate); const dt=Math.min(clock.getDelta(),0.05), now=performance.now(); // --- bagian mekanis: HANYA bergerak saat nilai berubah (lerp lalu berhenti) --- const k=1-Math.pow(0.001,dt); S.cU+=(S.tU-S.cU)*k; S.cL+=(S.tL-S.cL)*k; S.cT+=(S.tT-S.cT)*k; if(Math.abs(S.tU-S.cU)<0.01)S.cU=S.tU; if(Math.abs(S.tL-S.cL)<0.01)S.cL=S.tL; if(Math.abs(S.tT-S.cT)<0.01)S.cT=S.tT; idlerSets.forEach((r,i)=>{ r.userData.pivot.rotation.y = S.cU*D2R*0.5*(i===2?1:0.45); }); returnRollers.forEach((r,i)=>{ r.userData.pivot.rotation.y = S.cL*D2R*0.5*(i===1?1:0.45); }); tailGroup.position.z = S.cT*0.022; tailGroup.rotation.y = S.cT*D2R*0.35; // --- highlight bagian aktif --- const on = now < S.activeUntil; const pulse = 0.5+0.5*Math.sin(now*0.012); const setMat=(list,hot)=>list.forEach(m=>m.material = hot?MAT.hot:MAT.roller); setMat(idlerSets[2].userData.meshes, on&&S.active==='upper'); idlerSets.forEach((r,i)=>{ if(i!==2) setMat(r.userData.meshes,false); }); returnRollers.forEach((r,i)=> setMat(r.userData.meshes, on&&S.active==='lower'&&i===1)); setMat(tailGroup.userData.meshes, on&&S.active==='tail'); guides.upper.visible = on&&S.active==='upper'; guides.lower.visible = on&&S.active==='lower'; guides.tail.visible = on&&S.active==='tail'; [guides.upper,guides.lower,guides.tail].forEach(g=>{if(g&&g.visible)g.material.opacity=0.35+0.65*pulse;}); // --- belt: JALAN TERUS --- carryTex.offset.x -= dt*0.55; returnTex.offset.x += dt*0.55; // --- tracking belt (mengikuti hasil penyetelan) --- const carryOff = (S.cT*0.5 + S.cU*0.42)/30*1.25; const retOff = (S.cT*0.3 + S.cL*0.55)/30*1.25; carryBelt.position.z += (carryOff-carryBelt.position.z)*k; returnBelt.position.z += (retOff-returnBelt.position.z)*k; carryBelt.rotation.y = -S.cU*D2R*0.05; // --- muatan ore: JALAN TERUS --- const spd = 4.2*dt; oreRocks.forEach(m=>{ m.position.x += spd; if(m.position.x>13.2) m.position.x=-13.2; m.position.z = m.userData.z + carryBelt.position.z; m.position.y = m.userData.y; m.rotation.z -= spd*0.9; }); // --- ceceran ore saat belt sangat miring --- const mis=Math.abs(S.cU)+Math.abs(S.cL)+Math.abs(S.cT); const side=Math.sign(carryBelt.position.z)||1; spills.forEach(p=>{ if(!p.visible){ if(mis>34 && Math.random()<0.05){ p.visible=true;p.userData.vy=0; p.position.set(-12+Math.random()*24, 2.0, side*(1.45+carryBelt.position.z)); } return; } p.userData.vy-=13*dt; p.position.y+=p.userData.vy*dt; p.position.z+=side*1.3*dt; p.position.x+=spd*0.6; p.rotation.x+=dt*4;p.rotation.y+=dt*3; if(p.position.y<-1.05){p.visible=false;} }); // --- panah arah --- arrows.forEach(a=>{a.material.opacity=0.35+0.6*(0.5+0.5*Math.sin(now*0.005-a.userData.phase*3));}); // --- status --- document.getElementById('vU').textContent=S.tU; document.getElementById('vL').textContent=S.tL; document.getElementById('vT').textContent=S.tT; const st=document.getElementById('status'); const dir = carryBelt.position.z>0.06?'↗ belt geser KANAN':carryBelt.position.z<-0.06?'↙ belt geser KIRI':'● belt di TENGAH'; if(mis<5) st.innerHTML='Status: Belt lurus ✅ — ore berjalan normal<br><span style="color:#8b949e">'+dir+'</span>'; else if(mis<25) st.innerHTML='Status: Belt sedikit miring ⚠️ — perlu penyetelan<br><span style="color:#ffd43b">'+dir+'</span>'; else st.innerHTML='Status: Belt sangat miring ❌ — segera koreksi!<br><span style="color:#ff6b6b">'+dir+' · ore mulai tumpah</span>'; controls.update(); renderer.render(scene,camera); } init(); </script> </body> </html>
Landing Page
This ad does not have a landing page available
Network Timeline
Performance Summary

1

Requests

1

Domains

20KB

Transfer Size

20KB

Content Size

95.0ms

Dom Content Loaded

208.0ms

First Paint

96.0ms

Load Time
Domain Breakdown
Transfer Size (bytes)
Loading...
Content Size (bytes)
Loading...
Header Size (bytes)
Loading...
Requests
Loading...
Timings (ms)
Loading...
Total Time
Loading...
Content Breakdown
Transfer Size (bytes)
Loading...
Content Size (bytes)
Loading...
Header Size (bytes)
Loading...
Requests
Loading...