Skip to content

Commit

Permalink
fix: 🐛 optimize contextmenu tools (#1391)
Browse files Browse the repository at this point in the history
  • Loading branch information
NewByVector authored Oct 1, 2021
1 parent b111fce commit 4d0b1e8
Show file tree
Hide file tree
Showing 4 changed files with 156 additions and 127 deletions.
82 changes: 49 additions & 33 deletions examples/x6-example-features/src/pages/tools/contextmenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,14 @@ class ContextMenuTool extends ToolsView.ToolItem<
ContextMenuToolOptions
> {
private knob: HTMLDivElement
private timer: number

render() {
super.render()
this.knob = ToolsView.createElement('div', false) as HTMLDivElement
this.knob.style.position = 'absolute'
this.container.appendChild(this.knob)
this.updatePosition(this.options)
setTimeout(() => {
this.toggleContextMenu(true)
})
if (!this.knob) {
this.knob = ToolsView.createElement('div', false) as HTMLDivElement
this.knob.style.position = 'absolute'
this.container.appendChild(this.knob)
}
return this
}

Expand All @@ -41,9 +39,10 @@ class ContextMenuTool extends ToolsView.ToolItem<
}
}

private updatePosition(pos?: { x: number; y: number }) {
private updatePosition(e?: MouseEvent) {
const style = this.knob.style
if (pos) {
if (e) {
const pos = this.graph.clientToGraph(e.clientX, e.clientY)
style.left = `${pos.x}px`
style.top = `${pos.y}px`
} else {
Expand All @@ -52,15 +51,30 @@ class ContextMenuTool extends ToolsView.ToolItem<
}
}

private onMouseDown = (e: MouseEvent) => {
setTimeout(() => {
private onMouseDown = () => {
this.timer = window.setTimeout(() => {
this.updatePosition()
this.toggleContextMenu(false)
if (this.options.onHide) {
this.options.onHide.call(this)
}
}, 200)
}

private onContextMenu({ e }: { e: MouseEvent }) {
if (this.timer) {
clearTimeout(this.timer)
this.timer = 0
}
this.updatePosition(e)
this.toggleContextMenu(true)
}

delegateEvents() {
this.cellView.on('cell:contextmenu', this.onContextMenu, this)
return super.delegateEvents()
}

protected onRemove() {
this.cellView.off('cell:contextmenu', this.onContextMenu, this)
}
}

ContextMenuTool.config({
Expand All @@ -69,10 +83,7 @@ ContextMenuTool.config({
})

export interface ContextMenuToolOptions extends ToolsView.ToolItem.Options {
x: number
y: number
menu?: Menu | (() => Menu)
onHide?: (this: ContextMenuTool) => void
menu: React.ReactElement
}

Graph.registerEdgeTool('contextmenu', ContextMenuTool, true)
Expand All @@ -87,7 +98,7 @@ const menu = (
3rd menu item
</a>
</Menu.Item>
<Menu.Item key="4" danger="true">
<Menu.Item key="4" danger>
a danger item
</Menu.Item>
</Menu>
Expand Down Expand Up @@ -121,6 +132,14 @@ export default class Example extends React.Component {
strokeWidth: 1,
},
},
tools: [
{
name: 'contextmenu',
args: {
menu,
},
},
],
})

const target = graph.addNode({
Expand All @@ -135,6 +154,14 @@ export default class Example extends React.Component {
strokeWidth: 1,
},
},
tools: [
{
name: 'contextmenu',
args: {
menu,
},
},
],
})

graph.addEdge({
Expand All @@ -146,26 +173,15 @@ export default class Example extends React.Component {
strokeWidth: 1,
},
},
})

graph.on('cell:contextmenu', ({ cell, e }) => {
const p = graph.clientToGraph(e.clientX, e.clientY)
cell.addTools([
tools: [
{
name: 'contextmenu',
args: {
menu,
x: p.x,
y: p.y,
onHide() {
this.cell.removeTools()
},
},
},
])
],
})

graph.zoomTo(0.8)
}

refContainer = (container: HTMLDivElement) => {
Expand Down
109 changes: 54 additions & 55 deletions examples/x6-example-features/src/pages/tools/tooltip.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,34 +5,53 @@ import { Graph, ToolsView, EdgeView } from '@antv/x6'
import '../index.less'

class TooltipTool extends ToolsView.ToolItem<EdgeView, TooltipToolOptions> {
private delay = 100
private timer: number
private knob: HTMLDivElement
private tooltipVisible: boolean

render() {
super.render()
this.knob = ToolsView.createElement('div', false) as HTMLDivElement
this.knob.style.position = 'absolute'
this.container.appendChild(this.knob)
this.updatePosition()
document.addEventListener('mousemove', this.onMouseMove)

if (!this.knob) {
this.knob = ToolsView.createElement('div', false) as HTMLDivElement
this.knob.style.position = 'absolute'
this.container.appendChild(this.knob)
}
return this
}

private toggleTooltip(visible: boolean) {
ReactDom.unmountComponentAtNode(this.knob)

if (visible) {
ReactDom.render(
<Tooltip title={this.options.tooltip} visible={true}>
<Tooltip
title={this.options.tooltip}
visible={true}
destroyTooltipOnHide
>
<div />
</Tooltip>,
this.knob,
)
}
this.tooltipVisible = visible
}

private onMosueEnter({ e }: { e: MouseEvent }) {
this.updatePosition(e)
this.toggleTooltip(true)
}

private onMouseLeave() {
this.updatePosition()
this.toggleTooltip(false)
}

private onMouseMove() {
this.updatePosition()
this.toggleTooltip(false)
}

delegateEvents() {
this.cellView.on('cell:mouseenter', this.onMosueEnter, this)
this.cellView.on('cell:mouseleave', this.onMouseLeave, this)
this.cellView.on('cell:mousemove', this.onMouseMove, this)
return super.delegateEvents()
}

private updatePosition(e?: MouseEvent) {
Expand All @@ -49,31 +68,10 @@ class TooltipTool extends ToolsView.ToolItem<EdgeView, TooltipToolOptions> {
}
}

private onMouseLeave() {
this.updatePosition()
window.clearTimeout(this.timer)
window.setTimeout(() => this.toggleTooltip(false), this.delay)
document.removeEventListener('mousemove', this.onMouseMove)
}

private onMouseMove = (e: MouseEvent) => {
window.clearTimeout(this.timer)
this.updatePosition(e)
this.timer = window.setTimeout(() => {
if (this.tooltipVisible) {
this.toggleTooltip(false)
}
this.toggleTooltip(true)
}, this.delay)
}

delegateEvents() {
this.cellView.on('cell:mouseleave', this.onMouseLeave, this)
return super.delegateEvents()
}

protected onRemove() {
this.cellView.off('cell:mouseenter', this.onMosueEnter, this)
this.cellView.off('cell:mouseleave', this.onMouseLeave, this)
this.cellView.off('cell:mousemove', this.onMouseMove, this)
}
}

Expand All @@ -86,8 +84,8 @@ export interface TooltipToolOptions extends ToolsView.ToolItem.Options {
tooltip?: string
}

Graph.registerNodeTool('tooltip', TooltipTool, true)
Graph.registerEdgeTool('tooltip', TooltipTool, true)
Graph.registerNodeTool('tooltip', TooltipTool, true)

export default class Example extends React.Component {
private container: HTMLDivElement
Expand All @@ -114,6 +112,14 @@ export default class Example extends React.Component {
strokeWidth: 1,
},
},
tools: [
{
name: 'tooltip',
args: {
tooltip: 'tooltip content',
},
},
],
})

const target = graph.addNode({
Expand All @@ -128,6 +134,14 @@ export default class Example extends React.Component {
strokeWidth: 1,
},
},
tools: [
{
name: 'tooltip',
args: {
tooltip: 'tooltip content',
},
},
],
})

graph.addEdge({
Expand All @@ -137,31 +151,16 @@ export default class Example extends React.Component {
line: {
stroke: '#a0a0a0',
strokeWidth: 1,
targetMarker: {
name: 'classic',
size: 7,
},
},
},
})

graph.on('cell:mouseenter', ({ cell }) => {
cell.addTools([
tools: [
{
name: 'tooltip',
args: {
tooltip: cell.isNode()
? cell === source
? 'source tooltip'
: 'target tooltip '
: 'edge tooltip',
tooltip: 'tooltip content',
},
},
])
})

graph.on('cell:mouseleave', ({ cell }) => {
cell.removeTools()
],
})
}

Expand Down
Loading

0 comments on commit 4d0b1e8

Please sign in to comment.