UNPKG

mqtnl

Version:

Familiar socket API over MQTT with smart packet prioritization and IoT-friendly features

128 lines (109 loc) 3.38 kB
<!DOCTYPE html> <html> <head> <title>Serial Transmisi Partikel</title> <script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/5.3.0/fabric.min.js"></script> <style> canvas { border: 1px solid #ccc; } button { margin-top: 10px; } label { margin-left: 10px; } </style> </head> <body> <canvas id="canvas" width="1000" height="500"></canvas> <br> <button id="btnTransmit">Transmit</button> <label>Durasi tiap partikel (ms): <input type="number" id="durationInput" value="500" min="100" max="5000"> </label> <script> const canvas = new fabric.Canvas('canvas'); const boxSize = 5; const rows = 15; const cols = 10; const spacing = boxSize + 1; const startX = 20; const startY = 75; const groupYgap = 125; const targetX0 = 800; const colors = ['red', 'orange', 'green']; const particles = []; // Inisiasi semua kotak dan simpan posisi awal colors.forEach((color, gi) => { for (let r = 0; r < rows; r++) { for (let c = 0; c < cols; c++) { const left = startX + c * spacing; const top = startY + gi * groupYgap + r * spacing; const rect = new fabric.Rect({ left, top, width: boxSize, height: boxSize, stroke: "grey", strokeWidth: .5, fill: color, selectable: false }); canvas.add(rect); particles.push({ rect, sx: left, sy: top, r, c, gi }); } } }); // Fisher–Yates shuffle function shuffle(arr) { for (let i = arr.length - 1; i > 0; i--) { const j = Math.floor(Math.random() * (i + 1)); [arr[i], arr[j]] = [arr[j], arr[i]]; } return arr; } document.getElementById('btnTransmit').onclick = () => { const duration = +document.getElementById('durationInput').value; // Reset semua kotak ke posisi awal particles.forEach(p => { p.rect.set({ left: p.sx, top: p.sy }); p.rect.setCoords(); }); canvas.renderAll(); // Susun urutan per grup secara acak const byGroup = [[], [], []]; particles.forEach((p, idx) => byGroup[p.gi].push(idx)); const order = [] .concat(shuffle(byGroup[0])) .concat(shuffle(byGroup[1])) .concat(shuffle(byGroup[2])); // Hitung target untuk setiap kotak order.forEach(idx => { const p = particles[idx]; p.tx = targetX0 + p.c * spacing; p.ty = startY + p.gi * groupYgap + p.r * spacing; }); // Animasi serial satu per satu let ptr = 0; function nextParticle() { if (ptr >= order.length) return; const p = particles[order[ptr++]]; const t0 = performance.now(); function step(now) { const elapsed = now - t0; const t = Math.min(elapsed / duration, 1); const x = p.sx + (p.tx - p.sx) * t; const curve = Math.sin(t * Math.PI) * -100; const y = p.sy + (p.ty - p.sy) * t + curve; p.rect.set({ left: x, top: y }); p.rect.setCoords(); canvas.renderAll(); if (t < 1) { requestAnimationFrame(step); } else { nextParticle(); } } requestAnimationFrame(step); } nextParticle(); }; </script> </body> </html>