graflow: wireType straight

This commit is contained in:
STEINNI
2026-03-01 13:27:00 +00:00
parent 9bc55b74d6
commit 070be08dee

View File

@@ -85,10 +85,11 @@ class BZgraflow extends Buildoz{
this.mainContainer.append(this.nodesContainer) this.mainContainer.append(this.nodesContainer)
this.append(this.hostContainer) this.append(this.hostContainer)
this.loadFlow(flowUrl).then(() => { this.loadFlow(flowUrl).then(() => {
if(this.hasAttribute('editable')){ if((this.getBZAttribute('edit')=='move') || (this.getBZAttribute('edit')=='full')){
this.dnd = new MovingNodes(this) this.dnd = new MovingNodes(this)
this.dnd.enableMovingNodes('.bzgf-node') } this.dnd.enableMovingNodes('.bzgf-node')
}) // Let it load async }
})
} }
error(msg, err){ error(msg, err){
@@ -393,7 +394,7 @@ class BZgraflow extends Buildoz{
addWire(link){ addWire(link){
const [idNode1, idPort1] = link.from const [idNode1, idPort1] = link.from
const [idNode2, idPort2] = link.to const [idNode2, idPort2] = link.to
const path = this.bezierNodes(idNode1, idPort1, idNode2, idPort2, this.getBZAttribute('tension')) const path = this.linkNodes(idNode1, idPort1, idNode2, idPort2)
const id = `${idNode1}_${idNode2}` const id = `${idNode1}_${idNode2}`
this.stagedWires[id] = document.createElementNS('http://www.w3.org/2000/svg', 'path') this.stagedWires[id] = document.createElementNS('http://www.w3.org/2000/svg', 'path')
this.stagedWires[id].setAttribute('d', path) this.stagedWires[id].setAttribute('d', path)
@@ -458,8 +459,9 @@ class BZgraflow extends Buildoz{
return({ x: x - r.left, y: y - r.top }) return({ x: x - r.left, y: y - r.top })
} }
bezierNodes(idNode1, idPort1, idNode2, idPort2, tension=60) { linkNodes(idNode1, idPort1, idNode2, idPort2) {
tension = parseInt(tension) const tension = parseInt(this.getBZAttribute('tension')) || 60
const wireType = this.getBZAttribute('wiretype') || 'bezier'
const node1 = this.stagedNodes[idNode1] const node1 = this.stagedNodes[idNode1]
const port1 = node1.ports[idPort1] const port1 = node1.ports[idPort1]
const node2 = this.stagedNodes[idNode2] const node2 = this.stagedNodes[idNode2]
@@ -477,7 +479,6 @@ class BZgraflow extends Buildoz{
const x2 = Math.floor(p2.x) const x2 = Math.floor(p2.x)
const y2 = Math.floor(p2.y) const y2 = Math.floor(p2.y)
const loop = (idNode1==idNode2) && (idPort1==idPort2) const loop = (idNode1==idNode2) && (idPort1==idPort2)
const dist = Math.abs(x2 - x1) + Math.abs(y2 - y1)
let c1x = Math.floor(x1 + (this.dirVect[port1.direction].x * tension)) let c1x = Math.floor(x1 + (this.dirVect[port1.direction].x * tension))
let c1y = Math.floor(y1 + (this.dirVect[port1.direction].y * tension)) let c1y = Math.floor(y1 + (this.dirVect[port1.direction].y * tension))
@@ -493,41 +494,68 @@ class BZgraflow extends Buildoz{
c2y -= 1*tension c2y -= 1*tension
} }
} }
if(wireType === 'bezier') {
return(`M ${x1} ${y1} C ${c1x} ${c1y}, ${c2x} ${c2y}, ${x2} ${y2}`) return(`M ${x1} ${y1} C ${c1x} ${c1y}, ${c2x} ${c2y}, ${x2} ${y2}`)
} }
if(wireType === 'straight') {
console.log('straight')
// Straight segments through the same control points
return(`M ${x1} ${y1} L ${c1x} ${c1y} L ${c2x} ${c2y} L ${x2} ${y2}`)
}
return('')
//return(`M ${x1} ${y1} C ${c1x} ${c1y}, ${c2x} ${c2y}, ${x2} ${y2}`)
}
bezierInterNodes(idNode1, idPort1, idNode2, idPort2, interNodes, orientation='horizontal', tension=60) { linkInterNodes(idNode1, idPort1, idNode2, idPort2, interNodes, orientation='horizontal') {
tension = parseInt(tension) const tension = parseInt(this.getBZAttribute('tension')) || 60
const wireType = this.getBZAttribute('wiretype') || 'bezier'
const node1 = this.stagedNodes[idNode1] const node1 = this.stagedNodes[idNode1]
let port1 = node1.ports[idPort1] const port1 = node1.ports[idPort1]
const node2 = this.stagedNodes[idNode2]
const makeCubicBezier = (x1, y1, x2, y2, orientation1, orientation2) => { const port2 = node2.ports[idPort2]
const dist = Math.abs(x2 - x1) + Math.abs(y2 - y1) if(!node1 || !node2 || !port1 || !port2) {
console.warn('Link on bad node / port ', idNode1, idPort1, idNode2, idPort2)
return('')
}
const makeSegment = (x1, y1, x2, y2, orientation1, orientation2) => {
let c1x, c1y, c2x, c2y let c1x, c1y, c2x, c2y
if(orientation1=='horizontal'){ if(orientation1=='horizontal') {
c1x = Math.floor(x1 + tension) c1x = Math.floor(x1 + tension)
c1y = y1 c1y = y1
} else { } else {
c1x = x1 c1x = x1
c1y = Math.floor(y1 + tension) c1y = Math.floor(y1 + tension)
} }
if(orientation2=='horizontal'){ if(orientation2=='horizontal') {
c2x = Math.floor(x2 - tension) c2x = Math.floor(x2 - tension)
c2y = y2 c2y = y2
} else { } else {
c2x = x2 c2x = x2
c2y = Math.floor(y2 - tension) c2y = Math.floor(y2 - tension)
} }
if(wireType === 'bezier') {
return(`C ${c1x} ${c1y}, ${c2x} ${c2y}, ${x2} ${y2}`) return(`C ${c1x} ${c1y}, ${c2x} ${c2y}, ${x2} ${y2}`)
} }
const directPath = this.bezierNodes(idNode1, idPort1, idNode2, idPort2, tension) if(wireType === 'straight') {
const startPath = directPath.substring(0,directPath.indexOf('C')) return(`L ${c1x} ${c1y} L ${c2x} ${c2y} L ${x2} ${y2}`)
const endPath = directPath.substring(directPath.lastIndexOf(',')+1).trim() }
let path = startPath return(`C ${c1x} ${c1y}, ${c2x} ${c2y}, ${x2} ${y2}`)
let [ , x1, y1] = startPath.split(' ') }
x1 = parseFloat(x1)
y1 = parseFloat(y1) // Start/end points in SVG coords (works for both bezier and line)
const bb1 = port1.el.getBoundingClientRect()
const bb2 = port2.el.getBoundingClientRect()
const sp = this.clientToSvg(bb1.x + (bb1.width/2), bb1.y + (bb1.height/2))
const ep = this.clientToSvg(bb2.x + (bb2.width/2), bb2.y + (bb2.height/2))
let x1 = Math.floor(sp.x)
let y1 = Math.floor(sp.y)
const xEnd = Math.floor(ep.x)
const yEnd = Math.floor(ep.y)
let path = `M ${x1} ${y1} `
let firstPort = port1
for(const interNode of interNodes){ for(const interNode of interNodes){
const bb = this.stagedNodes[interNode].getBoundingClientRect() const bb = this.stagedNodes[interNode].getBoundingClientRect()
// Entry/exit points on the placeholder box, converted to SVG coords (handles CSS transforms) // Entry/exit points on the placeholder box, converted to SVG coords (handles CSS transforms)
@@ -544,11 +572,11 @@ class BZgraflow extends Buildoz{
let x2 = Math.floor(entry.x) let x2 = Math.floor(entry.x)
let y2 = Math.floor(entry.y) let y2 = Math.floor(entry.y)
if(port1){ if(firstPort){
path += makeCubicBezier(x1, y1, x2, y2, ['w','e'].includes(port1.direction) ? 'horizontal' : 'vertical', orientation) path += makeSegment(x1, y1, x2, y2, ['w','e'].includes(firstPort.direction) ? 'horizontal' : 'vertical', orientation)
port1 = false firstPort = null
} else { } else {
path += makeCubicBezier(x1, y1, x2, y2, orientation, orientation) path += makeSegment(x1, y1, x2, y2, orientation, orientation)
} }
const x3 = Math.floor(exit.x) const x3 = Math.floor(exit.x)
@@ -558,10 +586,7 @@ class BZgraflow extends Buildoz{
x1 = x3 x1 = x3
y1 = y3 y1 = y3
} }
let [x2, y2] = endPath.split(' ') path += ' ' + makeSegment(x1, y1, xEnd, yEnd, orientation, orientation)
x2 = parseFloat(x2)
y2 = parseFloat(y2)
path += ' '+makeCubicBezier(x1, y1, x2, y2, orientation, orientation)
return(path) return(path)
} }
@@ -574,12 +599,7 @@ class BZgraflow extends Buildoz{
// Cleanup placeholders from previous autoPlace() runs. // Cleanup placeholders from previous autoPlace() runs.
// Each run creates new longLinkPlaceHolder_* IDs; without cleanup they accumulate in the DOM. // Each run creates new longLinkPlaceHolder_* IDs; without cleanup they accumulate in the DOM.
for(const nid of Object.keys(this.stagedNodes || {})){ this.clearFakeNodes()
if(!nid.startsWith('longLinkPlaceHolder_')) continue
const el = this.stagedNodes[nid]
if(el?.parentNode) el.parentNode.removeChild(el)
delete this.stagedNodes[nid]
}
// Loops create infinite recursion in dfs for getting parents & adjacency lists: Remove them ! // Loops create infinite recursion in dfs for getting parents & adjacency lists: Remove them !
let linksWithoutBackEdges let linksWithoutBackEdges
@@ -724,6 +744,15 @@ class BZgraflow extends Buildoz{
} }
} }
clearFakeNodes(){
for(const nid of Object.keys(this.stagedNodes || {})){
if(!nid.startsWith('longLinkPlaceHolder_')) continue
const el = this.stagedNodes[nid]
if(el?.parentNode) el.parentNode.removeChild(el)
delete this.stagedNodes[nid]
}
}
getMaxWidth(layer){ getMaxWidth(layer){
return(layer.filter(nid => return(layer.filter(nid =>
!nid.startsWith('longLinkPlaceHolder_')) !nid.startsWith('longLinkPlaceHolder_'))
@@ -849,7 +878,7 @@ class BZgraflow extends Buildoz{
const y = y0 + (desty - y0) * k const y = y0 + (desty - y0) * k
el.style.left = `${x}px` el.style.left = `${x}px`
el.style.top = `${y}px` el.style.top = `${y}px`
this.updateWires(nid, orientation) this.updateWires(nid, orientation, true)
if(p < 1) requestAnimationFrame(frame.bind(this)) if(p < 1) requestAnimationFrame(frame.bind(this))
else{ else{
@@ -863,7 +892,7 @@ class BZgraflow extends Buildoz{
requestAnimationFrame(frame.bind(this)) requestAnimationFrame(frame.bind(this))
} }
updateWires(nid, orientation){ updateWires(nid, orientation, LondLinkfix = false){
const wires = Object.keys(this.stagedWires) const wires = Object.keys(this.stagedWires)
.filter(id => (id.startsWith(nid+'_')||id.endsWith('_'+nid))) .filter(id => (id.startsWith(nid+'_')||id.endsWith('_'+nid)))
.map(id => this.stagedWires[id]) .map(id => this.stagedWires[id])
@@ -873,11 +902,11 @@ class BZgraflow extends Buildoz{
if(!lnk) continue if(!lnk) continue
if(!this.flow?.longLinks) this.flow.longLinks = [] if(!this.flow?.longLinks) this.flow.longLinks = []
const longLink = this.flow.longLinks.find(item => (item.link.from[0] == lnk.from[0] && item.link.from[1] == lnk.from[1] && item.link.to[0] == lnk.to[0] && item.link.to[1] == lnk.to[1])) const longLink = this.flow.longLinks.find(item => (item.link.from[0] == lnk.from[0] && item.link.from[1] == lnk.from[1] && item.link.to[0] == lnk.to[0] && item.link.to[1] == lnk.to[1]))
if(longLink) { if(longLink && LondLinkfix) {
const path = this.bezierInterNodes(nid1, lnk.from[1], nid2, lnk.to[1], longLink.interNodes, orientation, this.getBZAttribute('tension')) const path = this.linkInterNodes(nid1, lnk.from[1], nid2, lnk.to[1], longLink.interNodes, orientation)
wire.setAttribute('d', path) wire.setAttribute('d', path)
} else { } else {
const path = this.bezierNodes(nid1, lnk.from[1], nid2, lnk.to[1], this.getBZAttribute('tension')) const path = this.linkNodes(nid1, lnk.from[1], nid2, lnk.to[1])
wire.setAttribute('d', path) wire.setAttribute('d', path)
} }
} }
@@ -1051,6 +1080,7 @@ class MovingNodes{
} }
pointerDown(e){ pointerDown(e){
this.graflow.clearFakeNodes()
const node = (e.target.classList.contains(this.itemSelector)) ? e.target : e.target.closest(this.itemSelector) const node = (e.target.classList.contains(this.itemSelector)) ? e.target : e.target.closest(this.itemSelector)
const handle = (node.classList.contains(this.handleSelector)) ? node : node.querySelector(this.handleSelector) const handle = (node.classList.contains(this.handleSelector)) ? node : node.querySelector(this.handleSelector)
@@ -1081,7 +1111,7 @@ class MovingNodes{
const y = e.clientY - startY + offsetY const y = e.clientY - startY + offsetY
node.style.left = `${x}px` node.style.left = `${x}px`
node.style.top = `${y}px` node.style.top = `${y}px`
this.graflow.updateWires(node.dataset.id, this.graflow.currentOrientation) this.graflow.updateWires(node.dataset.id, this.graflow.currentOrientation, false)
} }
pointerUp(e){ pointerUp(e){