Skip to content

Commit

Permalink
bugfix: node pointerupoutside
Browse files Browse the repository at this point in the history
  • Loading branch information
jameslaneconkling committed Oct 12, 2023
1 parent ded6412 commit 607fbb0
Show file tree
Hide file tree
Showing 5 changed files with 83 additions and 78 deletions.
15 changes: 10 additions & 5 deletions src/renderers/webgl/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ export class Renderer {
animateNodeRadius: number | false = defaultOptions.animateNodeRadius
circle: CircleTexture
arrow: ArrowTexture
draggedNode?: NodeRenderer

private doubleClick = false
private doubleClickTimeout?: number
Expand Down Expand Up @@ -242,7 +243,15 @@ export class Renderer {
this.root.addEventListener('pointerdown', this.pointerDown)
this.root.addEventListener('pointermove', this.pointerMove)
this.root.addEventListener('pointerup', this.pointerUp)
this.root.addEventListener('pointerupoutside', this.pointerUp)
this.root.addEventListener('pointerupoutside', (event) => {
if (this.draggedNode) {
const draggedNode = this.draggedNode
draggedNode.pointerUp(event)
draggedNode.pointerLeave(event)
} else {
this.pointerUp(event)
}
})
this.root.addEventListener('pointercancel', this.pointerUp)
this.root.addEventListener('pointerleave', this.pointerLeave)
view.addEventListener!('wheel', this.zoomInteraction.wheel, { passive: false })
Expand Down Expand Up @@ -590,10 +599,6 @@ export class Renderer {
})
}

// TODO - pointerupoutside doesn't work for nodes but does for viewport
// if node is dragging, fire onNodePointerUp on pointer up outside
// TODO - don't fire pointer up if it's handled by a node/edge pointerUp handler
// but still complete drag/decelarate event
private pointerUp = (event: FederatedPointerEvent) => {
if (!this.pointerIsDown) {
return
Expand Down
3 changes: 1 addition & 2 deletions src/renderers/webgl/interaction/edgeHitArea.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ const MIN_LINE_HOVER_RADIUS = 2
export class EdgeHitArea {
mounted = false

private hitArea = new Container()
private container: Container
private edgeRenderer: EdgeRenderer
private hitArea = new Container()

constructor(container: Container, edgeRenderer: EdgeRenderer) {
this.container = container
Expand All @@ -19,7 +19,6 @@ export class EdgeHitArea {
this.hitArea.addEventListener('pointerenter', this.edgeRenderer.pointerEnter)
this.hitArea.addEventListener('pointerdown', this.edgeRenderer.pointerDown)
this.hitArea.addEventListener('pointerup', this.edgeRenderer.pointerUp)
this.hitArea.addEventListener('pointerupoutside', this.edgeRenderer.pointerUp)
this.hitArea.addEventListener('pointercancel', this.edgeRenderer.pointerUp)
this.hitArea.addEventListener('pointerleave', this.edgeRenderer.pointerLeave)
}
Expand Down
3 changes: 1 addition & 2 deletions src/renderers/webgl/interaction/nodeHitArea.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ import { NodeRenderer } from '../node'
export class NodeHitArea {
mounted = false

private hitArea = new Container()
private container: Container
private nodeRenderer: NodeRenderer
private hitArea = new Container()

constructor(container: Container, nodeRenderer: NodeRenderer) {
this.container = container
Expand All @@ -16,7 +16,6 @@ export class NodeHitArea {
this.hitArea.addEventListener('pointerenter', this.nodeRenderer.pointerEnter)
this.hitArea.addEventListener('pointerdown', this.nodeRenderer.pointerDown)
this.hitArea.addEventListener('pointerup', this.nodeRenderer.pointerUp)
this.hitArea.addEventListener('pointerupoutside', this.nodeRenderer.pointerUp)
this.hitArea.addEventListener('pointercancel', this.nodeRenderer.pointerUp)
this.hitArea.addEventListener('pointerleave', this.nodeRenderer.pointerLeave)
}
Expand Down
2 changes: 2 additions & 0 deletions src/renderers/webgl/node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,7 @@ export class NodeRenderer {

if (this.renderer.onNodeDrag) {
event.stopPropagation()
this.renderer.draggedNode = this
this.renderer.container.style.cursor = 'move'
this.nodeMoveXOffset = local.x - (this.node!.x ?? 0)
this.nodeMoveYOffset = local.y - (this.node!.y ?? 0)
Expand Down Expand Up @@ -299,6 +300,7 @@ export class NodeRenderer {
const local = this.renderer.root.toLocal(event.global)

if (this.renderer.onNodeDrag) {
this.renderer.draggedNode = undefined
this.renderer.container.style.cursor = 'auto'
this.renderer.root.removeEventListener('pointermove', this.pointerMove)
this.renderer.zoomInteraction.resume()
Expand Down
138 changes: 69 additions & 69 deletions tests/webgl/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,45 +110,45 @@ const options: Renderer.Options = {
// onViewportDragEnd: (event: Renderer.ViewportDragEvent | Renderer.ViewportDragDecelerateEvent) => {
// console.log('viewport drag end', `x: ${event.dx}, y: ${event.dy}`)
// },
// onViewportPointerUp: (event: Renderer.ViewportPointerEvent) => {
// console.log('viewport pointer up', `x: ${event.x}, y: ${event.y}`)
// },
// onViewportClick: (event: Renderer.ViewportPointerEvent) => {
// console.log('viewport click', `x: ${event.x}, y: ${event.y}`)
// // if (options.x === 0 && options.y === 0 && options.zoom === 1) {
// // options.x = 1000
// // options.y = -1000
// // options.zoom = 0.2
// // } else {
// // options.x = 0
// // options.y = 0
// // options.zoom = 1
// // }
// // renderer.update({ nodes, edges, options })

// // if (options.width === 1400 && options.height === 1000) {
// // options.width = 700
// // options.height = 500
// // } else {
// // options.width = 1400
// // options.height = 1000
// // }
// // renderer.update({ nodes, edges, options })

// // force({ nodes, edges }).then((graph) => {
// // nodes = graph.nodes

// // const { x, y, zoom } = Graph.boundsToViewport(
// // Graph.getSelectionBounds(nodes, 40),
// // { width: options.width, height: options.height }
// // )
// // options.x = x
// // options.y = y
// // options.zoom = zoom

// // renderer.update({ nodes, edges, options: options })
// // })
// },
onViewportPointerUp: (event: Renderer.ViewportPointerEvent) => {
console.log('viewport pointer up', `x: ${event.x}, y: ${event.y}`)
},
onViewportClick: (event: Renderer.ViewportPointerEvent) => {
console.log('viewport click', `x: ${event.x}, y: ${event.y}`)
// if (options.x === 0 && options.y === 0 && options.zoom === 1) {
// options.x = 1000
// options.y = -1000
// options.zoom = 0.2
// } else {
// options.x = 0
// options.y = 0
// options.zoom = 1
// }
// renderer.update({ nodes, edges, options })

// if (options.width === 1400 && options.height === 1000) {
// options.width = 700
// options.height = 500
// } else {
// options.width = 1400
// options.height = 1000
// }
// renderer.update({ nodes, edges, options })

// force({ nodes, edges }).then((graph) => {
// nodes = graph.nodes

// const { x, y, zoom } = Graph.boundsToViewport(
// Graph.getSelectionBounds(nodes, 40),
// { width: options.width, height: options.height }
// )
// options.x = x
// options.y = y
// options.zoom = zoom

// renderer.update({ nodes, edges, options: options })
// })
},
// onViewportDoubleClick: (event: Renderer.ViewportPointerEvent) => {
// console.log('viewport double click', `x: ${event.x}, y: ${event.y}`)
// },
Expand All @@ -162,7 +162,7 @@ const options: Renderer.Options = {
// console.log('viewport pointer leave', `x: ${event.x}, y: ${event.y}`)
// },
onNodePointerEnter: (event: Renderer.NodePointerEvent) => {
console.log('node pointer enter', `x: ${event.x}, y: ${event.y}, id: ${event.target.id}`)
// console.log('node pointer enter', `x: ${event.x}, y: ${event.y}, id: ${event.target.id}`)
nodes = nodes.map((node) => (node.id === event.target.id ? { ...node, label: node.label + ' 北京', style: NODE_HOVER_STYLE } : node))
edges = edges.map((edge) =>
edge.source === event.target.id || edge.target === event.target.id ? { ...edge, style: EDGE_HOVER_STYLE } : edge
Expand All @@ -175,31 +175,31 @@ const options: Renderer.Options = {
// onNodeDragStart: (event: Renderer.NodeDragEvent) => {
// console.log('node drag start', `x: ${event.x}, y: ${event.y}`)
// },
// onNodeDrag: (event: Renderer.NodeDragEvent) => {
// console.log('node drag', `x: ${event.x}, y: ${event.y}`)
// nodes = nodes.map((node) =>
// node.id === event.target.id ? { ...node, x: (node.x ?? 0) + event.dx, y: (node.y ?? 0) + event.dy } : node
// )
// renderer.update({ nodes, edges, options })
// },
onNodeDrag: (event: Renderer.NodeDragEvent) => {
console.log('node drag', `x: ${event.x}, y: ${event.y}`)
nodes = nodes.map((node) =>
node.id === event.target.id ? { ...node, x: (node.x ?? 0) + event.dx, y: (node.y ?? 0) + event.dy } : node
)
renderer.update({ nodes, edges, options })
},
// onNodeDragEnd: (event: Renderer.NodeDragEvent) => {
// console.log('node drag end', `x: ${event.x}, y: ${event.y}`)
// },
// onNodePointerUp: (event: Renderer.NodePointerEvent) => {
// console.log('node pointer up', `x: ${event.x}, y: ${event.y}`)
// },
// onNodeClick: (event: Renderer.NodePointerEvent) => {
// console.log('node pointer click', `x: ${event.x}, y: ${event.y}`)
// // const graph = hierarchy(event.target.id, { nodes, edges, options: { separation: (a, b) => 1, nodeSize: [30, 100] } })
// // nodes = graph.nodes.map((node) => ({ ...node, x: node.y, y: node.x }))
// // edges = graph.edges
// // renderer.update({ nodes, edges, options })
// },
// onNodeDoubleClick: (event: Renderer.NodePointerEvent) => {
// console.log('node pointer double click', `x: ${event.x}, y: ${event.y}`)
// },
onNodePointerUp: (event: Renderer.NodePointerEvent) => {
console.log('node pointer up', `x: ${event.x}, y: ${event.y}`)
},
onNodeClick: (event: Renderer.NodePointerEvent) => {
console.log('node pointer click', `x: ${event.x}, y: ${event.y}`)
// const graph = hierarchy(event.target.id, { nodes, edges, options: { separation: (a, b) => 1, nodeSize: [30, 100] } })
// nodes = graph.nodes.map((node) => ({ ...node, x: node.y, y: node.x }))
// edges = graph.edges
// renderer.update({ nodes, edges, options })
},
onNodeDoubleClick: (event: Renderer.NodePointerEvent) => {
console.log('node pointer double click', `x: ${event.x}, y: ${event.y}`)
},
onNodePointerLeave: (event: Renderer.NodePointerEvent) => {
console.log('node pointer leave', `x: ${event.x}, y: ${event.y}`)
// console.log('node pointer leave', `x: ${event.x}, y: ${event.y}`)
nodes = nodes.map((node) =>
node.id === event.target.id ? { ...node, label: node.label?.slice(0, node.label.length - 3), style: NODE_STYLE } : node
)
Expand All @@ -209,24 +209,24 @@ const options: Renderer.Options = {
renderer.update({ nodes, edges, options })
},
onEdgePointerEnter: (event: Renderer.EdgePointerEvent) => {
console.log('edge pointer enter', `x: ${event.x}, y: ${event.y}`)
// console.log('edge pointer enter', `x: ${event.x}, y: ${event.y}`)
edges = edges.map((edge) => (edge.id === event.target.id ? { ...edge, style: EDGE_HOVER_STYLE } : edge))
renderer.update({ nodes, edges, options })
},
// onEdgePointerDown: (event: Renderer.EdgePointerEvent) => {
// console.log('edge pointer down', `x: ${event.x}, y: ${event.y}`)
// },
// onEdgePointerUp: (event: Renderer.EdgePointerEvent) => {
// console.log('edge pointer up', `x: ${event.x}, y: ${event.y}`)
// },
// onEdgeClick: (event: Renderer.EdgePointerEvent) => {
// console.log('edge pointer click', `x: ${event.x}, y: ${event.y}`)
// },
onEdgePointerUp: (event: Renderer.EdgePointerEvent) => {
console.log('edge pointer up', `x: ${event.x}, y: ${event.y}`)
},
onEdgeClick: (event: Renderer.EdgePointerEvent) => {
console.log('edge pointer click', `x: ${event.x}, y: ${event.y}`)
},
// onEdgeDoubleClick: (event: Renderer.EdgePointerEvent) => {
// console.log('edge pointer double click', `x: ${event.x}, y: ${event.y}`)
// },
onEdgePointerLeave: (event: Renderer.EdgePointerEvent) => {
console.log('edge pointer leave', `x: ${event.x}, y: ${event.y}`)
// console.log('edge pointer leave', `x: ${event.x}, y: ${event.y}`)
edges = edges.map((edge) => ({ ...edge, style: EDGE_STYLE }))
renderer.update({ nodes, edges, options })
}
Expand Down

0 comments on commit 607fbb0

Please sign in to comment.