Gozintograph: Unterschied zwischen den Versionen
Keine Bearbeitungszusammenfassung |
Markierung: Zurückgesetzt |
||
| Zeile 46: | Zeile 46: | ||
Die Pfeile zeigen, welche Einzelteile in welches Bauteil eingehen. Die Zahlen an den Pfeilen geben die benötigte Stückzahl an. | Die Pfeile zeigen, welche Einzelteile in welches Bauteil eingehen. Die Zahlen an den Pfeilen geben die benötigte Stückzahl an. | ||
<!-- VARIANTE B – FINAL OPTIMIERT --> | <!-- VARIANTE B – FINAL OPTIMIERT --> <html> <style> .gozinto-wrap { width:95vw; height:50vw; max-width:1100px; max-height:400px; border:0; margin:0; padding:0; } svg { width:100%; height:100%; touch-action:none; user-select:none; background:white; } .node-rect { fill:#3498db; stroke:#1f4e78; stroke-width:2; cursor:grab; } /* Einheitliche Schriftgröße */ .node-text, .count-text { font-family:sans-serif; font-size:14px; fill:#000; pointer-events:none; } .edge-line { stroke:#000; stroke-width:2; fill:none; } .edge-arrow { fill:#000; } .count-circle { fill:#fff; stroke:#000; stroke-width:1.5; } </style> <div class="gozinto-wrap"> <svg id="gozinto_svg_2" viewBox="0 0 1200 450" preserveAspectRatio="xMinYMin meet"> </svg> </div> <script> (function(){ const svg = document.getElementById("gozinto_svg_2"); // leicht reduzierte Abstände const scale = 100; const yOffset = 0; // früher 5 20 → Grafik rückt nach oben const xOffsetGlobal = 120; // gesamte Grafik leicht nach rechts (zentrieren) function svgEl(name, attrs){ const el = document.createElementNS("http://www.w3.org/2000/svg", name); for(const k in (attrs||{})) el.setAttribute(k, attrs[k]); return el; } function getSVGcoords(evt){ const pt = svg.createSVGPoint(); pt.x = evt.clientX; pt.y = evt.clientY; return pt.matrixTransform(svg.getScreenCTM().inverse()); } // ----------- NODE ----------- function createNode(id, cx, cy, w, h, label){ cx += xOffsetGlobal/scale; // gesamte Grafik nach rechts versetzt const g = svgEl("g", {"data-id":id}); const rect = svgEl("rect", { class:"node-rect", x:(cx-w/2)*scale, y:(cy-h/2)*scale + yOffset, width:w*scale, height:h*scale, rx:6, ry:6 }); const text = svgEl("text", { class:"node-text", x:cx*scale, y:cy*scale+yOffset, "text-anchor":"middle", "dominant-baseline":"middle" }); text.textContent = label; g.appendChild(rect); g.appendChild(text); svg.appendChild(g); const node = {id,cx,cy,w,h,rect,text,g}; // Draggen let dragging=false, start={}; rect.addEventListener("pointerdown", e=>{ rect.setPointerCapture(e.pointerId); dragging=true; const p = getSVGcoords(e); start = {px:p.x, py:p.y, cx:node.cx, cy:node.cy}; }); rect.addEventListener("pointermove", e=>{ if(!dragging) return; const p = getSVGcoords(e); node.cx = start.cx + (p.x - start.px)/scale; node.cy = start.cy + (p.y - start.py)/scale; updateNode(node); updateAllEdges(); }); rect.addEventListener("pointerup", e=>{ dragging=false; rect.releasePointerCapture(e.pointerId); }); return node; } function updateNode(n){ n.rect.setAttribute("x",(n.cx-n.w/2)*scale); n.rect.setAttribute("y",(n.cy-n.h/2)*scale+yOffset); n.text.setAttribute("x",n.cx*scale); n.text.setAttribute("y",n.cy*scale+yOffset); } // ------- Geometrie ------- function intersectRectBorder(node, tx, ty){ const cx=node.cx, cy=node.cy, w2=node.w/2, h2=node.h/2; const dx=tx-cx, dy=ty-cy; let pts=[]; if(Math.abs(dx)>1e-9){ let t1=(-w2)/dx; let y1=cy+t1*dy; if(t1>0 && y1>=cy-h2 && y1<=cy+h2) pts.push({x:cx-w2,y:y1,t:t1}); let t2=(w2)/dx; let y2=cy+t2*dy; if(t2>0 && y2>=cy-h2 && y2<=cy+h2) pts.push({x:cx+w2,y:y2,t:t2}); } if(Math.abs(dy)>1e-9){ let t3=(-h2)/dy; let x3=cx+t3*dx; if(t3>0 && x3>=cx-w2 && x3<=cx+w2) pts.push({x:x3,y:cy-h2,t:t3}); let t4=(h2)/dy; let x4=cx+t4*dx; if(t4>0 && x4>=cx-w2 && x4<=cx+w2) pts.push({x:x4,y:cy+h2,t:t4}); } pts.sort((a,b)=>a.t-b.t); return pts[0] || {x:cx,y:cy}; } function pointOnCircle(cx,cy,R,tx,ty){ const dx=tx-cx, dy=ty-cy; const d=Math.sqrt(dx*dx+dy*dy); if(d<1e-9) return {x:cx,y:cy}; return {x:cx+R*dx/d, y:cy+R*dy/d}; } function makeArrowHead(x,y,ux,uy,size){ let px=-uy, py=ux; return M ${x} ${y} L ${x-ux*size+px*size*0.5} ${y-uy*size+py*size*0.5} L ${x-ux*size-px*size*0.5} ${y-uy*size-py*size*0.5} Z; } const edges=[]; function makeConnection(fromNode,toNode,amount,yMid,xOffset){ const g=svgEl("g",{}); const lineA=svgEl("path",{class:"edge-line"}); const lineB=svgEl("path",{class:"edge-line"}); const circle=svgEl("circle",{class:"count-circle"}); const text=svgEl("text",{class:"count-text"}); const arrow=svgEl("path",{class:"edge-arrow"}); text.textContent=amount; g.appendChild(lineA); g.appendChild(lineB); g.appendChild(circle); g.appendChild(text); g.appendChild(arrow); svg.appendChild(g); let e={fromNode,toNode,amount,yMid,xOffset,circle,text,lineA,lineB,arrow}; edges.push(e); updateEdge(e); } function updateEdge(e){ const cx=(e.fromNode.cx+e.toNode.cx)/2+(e.xOffset||0); const cy=e.yMid; const R=0.14; const pF=intersectRectBorder(e.fromNode,cx,cy); const pT=intersectRectBorder(e.toNode,cx,cy); const pCircleIn=pointOnCircle(cx,cy,R,pF.x,pF.y); const pCircleOut=pointOnCircle(cx,cy,R,pT.x,pT.y); const px=p=>[p.x*scale, p.y*scale+yOffset]; const F=px(pF), Ci=px(pCircleIn), Co=px(pCircleOut), T=px(pT); e.lineA.setAttribute("d",M ${F[0]} ${F[1]} L ${Ci[0]} ${Ci[1]}); e.lineB.setAttribute("d",M ${Co[0]} ${Co[1]} L ${T[0]} ${T[1]}); e.circle.setAttribute("cx",cx*scale); e.circle.setAttribute("cy",cy*scale+yOffset); e.circle.setAttribute("r",R*scale); e.text.setAttribute('x', cx*scale-5); e.text.setAttribute('y', cy*scale + yOffset+5); let ux=T[0]-Co[0], uy=T[1]-Co[1]; let L=Math.sqrt(ux*ux+uy*uy); if(L<1e-6) L=1; ux/=L; uy/=L; e.arrow.setAttribute("d",makeArrowHead(T[0],T[1],ux,uy,10)); } function updateAllEdges(){ edges.forEach(updateEdge); } // ------------ Nodes ------------ const nodes={}; // Einzelteile oben nodes.E1=createNode("E1",0,0.5,1.0,0.5,"E1"); nodes.E2=createNode("E2",2.5,0.5,1.0,0.5,"E2"); nodes.E3=createNode("E3",5.0,0.5,1.0,0.5,"E3"); nodes.E4=createNode("E4",7.5,0.5,1.0,0.5,"E4"); // Bauteile darunter nodes.B1=createNode("B1",0.75,4.5,1.0,0.5,"B1"); nodes.B2=createNode("B2",2.5,4.5,1.0,0.5,"B2"); nodes.B3=createNode("B3",5.0,4.5,1.0,0.5,"B3"); nodes.B4=createNode("B4",7.5,4.5,1.0,0.5,"B4"); nodes.B5=createNode("B5",10,4.5,1.0,0.5,"B5"); // ------------ Verbindungen ------------ makeConnection(nodes.E1,nodes.B1,"2",2.2,-0.2); makeConnection(nodes.E2,nodes.B1,"1",2.2, 0.2); makeConnection(nodes.E1,nodes.B2,"2",2.2,-0.2); makeConnection(nodes.E2,nodes.B2,"1",2.2, 0.2); makeConnection(nodes.E1,nodes.B3,"1",2.2,-0.25); makeConnection(nodes.E2,nodes.B3,"1",2.2, 0.0); makeConnection(nodes.E3,nodes.B3,"1",2.2, 0.25); makeConnection(nodes.E1,nodes.B4,"2",2.2,-0.3); makeConnection(nodes.E3,nodes.B4,"1",2.2, 0.0); makeConnection(nodes.E4,nodes.B4,"1",2.2, 0.3); makeConnection(nodes.E1,nodes.B5,"1",2.2,-0.2); makeConnection(nodes.E4,nodes.B5,"2",2.2, 0.2); updateAllEdges(); })(); </script> </html> | ||
<html> | |||
<style> | |||
</style> | |||
<div class="gozinto-wrap"> | |||
<svg id="gozinto_svg_2" viewBox="0 0 1200 450" preserveAspectRatio="xMinYMin meet"> | |||
</svg> | |||
</div> | |||
<script> | |||
(function(){ | |||
})(); | |||
</script> | |||
</html> | |||
Die Gozintomatrix zum oberen Gozintographen kann aus folgender Tabelle abgeleitet werden: | Die Gozintomatrix zum oberen Gozintographen kann aus folgender Tabelle abgeleitet werden: | ||