mirror of
http://10.0.2.1:3031/sauer/bfa-dryer-design.git
synced 2026-06-30 11:36:42 +10:00
Fix fan/agitator animations, add proper SVG graphics
- Fan: 4 curved blades spinning from center, centered rotation - Agitator: 3 flat paddles with hub, slower spin, distinct look - Both now rotate properly around their center (translate+rotate) - Default equipment: shaker=vibrate, mill=vibrate, brush=glow, discharge=flow, temp probes=pulse - Saved layouts preserved (only default.json changed) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
1d26f78592
commit
0975d031a3
@ -107,7 +107,7 @@ body{font-family:'Segoe UI',system-ui,sans-serif;background:var(--bg);color:var(
|
|||||||
.schematic .anim-overlay.active{opacity:1}
|
.schematic .anim-overlay.active{opacity:1}
|
||||||
|
|
||||||
/* Animations */
|
/* Animations */
|
||||||
@keyframes spin{100%{transform-origin:center;transform:rotate(360deg)}}
|
@keyframes spin{0%{transform:rotate(0deg)}100%{transform:rotate(360deg)}}
|
||||||
@keyframes pulse-glow{0%,100%{opacity:0.4}50%{opacity:1}}
|
@keyframes pulse-glow{0%,100%{opacity:0.4}50%{opacity:1}}
|
||||||
@keyframes scroll-belt{100%{stroke-dashoffset:-20}}
|
@keyframes scroll-belt{100%{stroke-dashoffset:-20}}
|
||||||
@keyframes fall-particles{0%{opacity:1;transform:translateY(0)}100%{opacity:0;transform:translateY(30px)}}
|
@keyframes fall-particles{0%{opacity:1;transform:translateY(0)}100%{opacity:0;transform:translateY(30px)}}
|
||||||
@ -622,10 +622,10 @@ const defaultEquipment = [
|
|||||||
{id:'eq_agit1', label:'A1', shape:'circle', x:440, y:170, r:12, anim:'agitator', link:'motor_3'},
|
{id:'eq_agit1', label:'A1', shape:'circle', x:440, y:170, r:12, anim:'agitator', link:'motor_3'},
|
||||||
{id:'eq_agit2', label:'A2', shape:'circle', x:510, y:170, r:12, anim:'agitator', link:'motor_4'},
|
{id:'eq_agit2', label:'A2', shape:'circle', x:510, y:170, r:12, anim:'agitator', link:'motor_4'},
|
||||||
{id:'eq_spinner', label:'Spin', shape:'circle', x:475, y:155, r:14, anim:'fan', link:'motor_2'},
|
{id:'eq_spinner', label:'Spin', shape:'circle', x:475, y:155, r:14, anim:'fan', link:'motor_2'},
|
||||||
{id:'eq_discharge',label:'Discharge', shape:'rect', x:580, y:160, w:80, h:60, anim:null, link:null},
|
{id:'eq_discharge',label:'Discharge', shape:'rect', x:580, y:160, w:80, h:60, anim:'flow', link:'output_0'},
|
||||||
{id:'eq_mill', label:'Mill', shape:'rect', x:580, y:250, w:70, h:50, anim:null, link:'output_4'},
|
{id:'eq_mill', label:'Mill', shape:'rect', x:580, y:250, w:70, h:50, anim:'vibrate', link:'output_4'},
|
||||||
{id:'eq_shaker', label:'Shaker Sep.',shape:'rect', x:670, y:250, w:90, h:50, anim:null, link:'output_5'},
|
{id:'eq_shaker', label:'Shaker Sep.',shape:'rect', x:670, y:250, w:90, h:50, anim:'vibrate', link:'output_5'},
|
||||||
{id:'eq_brush', label:'Brush', shape:'rect', x:670, y:160, w:60, h:40, anim:null, link:'output_1'},
|
{id:'eq_brush', label:'Brush', shape:'rect', x:670, y:160, w:60, h:40, anim:'glow', link:'output_1'},
|
||||||
{id:'eq_in', label:'IN \u25B6', shape:'label', x:60, y:148, anim:null, link:null, color:'#4a5670'},
|
{id:'eq_in', label:'IN \u25B6', shape:'label', x:60, y:148, anim:null, link:null, color:'#4a5670'},
|
||||||
{id:'eq_out', label:'\u25B6 OUT', shape:'label', x:740, y:320, anim:null, link:null, color:'#4a5670'},
|
{id:'eq_out', label:'\u25B6 OUT', shape:'label', x:740, y:320, anim:null, link:null, color:'#4a5670'},
|
||||||
{id:'eq_t_heat', label:'T1', shape:'circle', x:230, y:180, r:10, anim:'pulse', link:'temp_0', color:'#ff4444'},
|
{id:'eq_t_heat', label:'T1', shape:'circle', x:230, y:180, r:10, anim:'pulse', link:'temp_0', color:'#ff4444'},
|
||||||
@ -851,9 +851,54 @@ function renderSchematic() {
|
|||||||
if (eq.anim === 'burner') {
|
if (eq.anim === 'burner') {
|
||||||
g.appendChild(mkSvgEl('circle', {'class':'anim-overlay burner-glow', id:'sim-'+eq.id,
|
g.appendChild(mkSvgEl('circle', {'class':'anim-overlay burner-glow', id:'sim-'+eq.id,
|
||||||
cx:eq.x, cy:eq.y, r:r+4, fill:'none', stroke:col||'var(--amber)', 'stroke-width':'4'}));
|
cx:eq.x, cy:eq.y, r:r+4, fill:'none', stroke:col||'var(--amber)', 'stroke-width':'4'}));
|
||||||
} else if (eq.anim === 'fan' || eq.anim === 'agitator') {
|
} else if (eq.anim === 'fan') {
|
||||||
const ag = mkSvgEl('g', {'class':`anim-overlay ${eq.anim==='fan'?'fan-anim':'agitator-anim'}`, id:'sim-'+eq.id, 'transform-origin':`${eq.x} ${eq.y}`});
|
// Fan: 4 curved blades spinning inside the circle
|
||||||
ag.innerHTML = `<line x1="${eq.x}" y1="${eq.y-r}" x2="${eq.x}" y2="${eq.y+r}" stroke="${col||'var(--blue)'}" stroke-width="2"/><line x1="${eq.x-r}" y1="${eq.y}" x2="${eq.x+r}" y2="${eq.y}" stroke="${col||'var(--blue)'}" stroke-width="2"/>`;
|
const ag = mkSvgEl('g', {'class':'anim-overlay', id:'sim-'+eq.id});
|
||||||
|
const inner = mkSvgEl('g', {'class':'fan-anim', style:`transform-origin:0 0`});
|
||||||
|
const fc = col||'var(--blue)';
|
||||||
|
const b = r * 0.8;
|
||||||
|
// 4 fan blades as arcs
|
||||||
|
for (let i = 0; i < 4; i++) {
|
||||||
|
const a = (i * 90) * Math.PI / 180;
|
||||||
|
const x1 = Math.cos(a) * b * 0.2, y1 = Math.sin(a) * b * 0.2;
|
||||||
|
const x2 = Math.cos(a) * b, y2 = Math.sin(a) * b;
|
||||||
|
const cx1 = Math.cos(a + 0.6) * b * 0.6, cy1 = Math.sin(a + 0.6) * b * 0.6;
|
||||||
|
inner.appendChild(mkSvgEl('path', {
|
||||||
|
d: `M ${x1} ${y1} Q ${cx1} ${cy1} ${x2} ${y2}`,
|
||||||
|
fill:'none', stroke:fc, 'stroke-width':'3', 'stroke-linecap':'round'
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
// Center dot
|
||||||
|
inner.appendChild(mkSvgEl('circle', {cx:0, cy:0, r:r*0.15, fill:fc}));
|
||||||
|
ag.setAttribute('transform', `translate(${eq.x},${eq.y})`);
|
||||||
|
ag.appendChild(inner);
|
||||||
|
g.appendChild(ag);
|
||||||
|
} else if (eq.anim === 'agitator') {
|
||||||
|
// Agitator: 3 flat paddles spinning slower
|
||||||
|
const ag = mkSvgEl('g', {'class':'anim-overlay', id:'sim-'+eq.id});
|
||||||
|
const inner = mkSvgEl('g', {'class':'agitator-anim', style:`transform-origin:0 0`});
|
||||||
|
const ac = col||'var(--amber)';
|
||||||
|
const pr = r * 0.75;
|
||||||
|
// 3 rectangular paddles
|
||||||
|
for (let i = 0; i < 3; i++) {
|
||||||
|
const a = (i * 120) * Math.PI / 180;
|
||||||
|
const x1 = Math.cos(a) * pr, y1 = Math.sin(a) * pr;
|
||||||
|
// Paddle: thick line from center to edge
|
||||||
|
inner.appendChild(mkSvgEl('line', {
|
||||||
|
x1: 0, y1: 0, x2: x1, y2: y1,
|
||||||
|
stroke:ac, 'stroke-width':'4', 'stroke-linecap':'round'
|
||||||
|
}));
|
||||||
|
// Paddle head: small rect at end
|
||||||
|
inner.appendChild(mkSvgEl('rect', {
|
||||||
|
x: x1 - 3, y: y1 - 5, width: 6, height: 10,
|
||||||
|
fill:ac, rx:'2',
|
||||||
|
transform: `rotate(${i*120} ${x1} ${y1})`
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
// Center hub
|
||||||
|
inner.appendChild(mkSvgEl('circle', {cx:0, cy:0, r:r*0.2, fill:ac, stroke:ac, 'stroke-width':'1'}));
|
||||||
|
ag.setAttribute('transform', `translate(${eq.x},${eq.y})`);
|
||||||
|
ag.appendChild(inner);
|
||||||
g.appendChild(ag);
|
g.appendChild(ag);
|
||||||
} else if (eq.anim === 'pulse') {
|
} else if (eq.anim === 'pulse') {
|
||||||
g.appendChild(mkSvgEl('circle', {'class':'anim-overlay pulse-anim', id:'sim-'+eq.id,
|
g.appendChild(mkSvgEl('circle', {'class':'anim-overlay pulse-anim', id:'sim-'+eq.id,
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user