Skip to content

Commit

Permalink
feat: support mousewheel zooming and keyboard shortcuts
Browse files Browse the repository at this point in the history
  • Loading branch information
bubkoo committed May 21, 2020
1 parent 4f7053c commit 4146b04
Show file tree
Hide file tree
Showing 21 changed files with 577 additions and 257 deletions.
63 changes: 63 additions & 0 deletions examples/x6-example-features/src/pages/keyboard/index.tsx
@@ -0,0 +1,63 @@
import React from 'react'
import { Graph } from '@antv/x6'
import '../index.less'

export default class Example extends React.Component {
private container: HTMLDivElement

componentDidMount() {
const graph = new Graph({
container: this.container,
width: 800,
height: 600,
grid: true,
keyboard: {
enabled: true,
global: false,
},
})

graph.keyboard.on('command+shift+k', () => {
console.log(123)
})

graph.addNode({
type: 'rect',
x: 50,
y: 50,
width: 100,
height: 40,
attrs: { label: { text: 'A' } },
})

graph.addNode({
type: 'rect',
x: 250,
y: 50,
width: 100,
height: 40,
attrs: { label: { text: 'B' } },
})

graph.addNode({
type: 'rect',
x: 350,
y: 150,
width: 100,
height: 40,
attrs: { label: { text: 'C' } },
})
}

refContainer = (container: HTMLDivElement) => {
this.container = container
}

render() {
return (
<div className="x6-graph-wrap">
<div ref={this.refContainer} className="x6-graph" />
</div>
)
}
}
15 changes: 7 additions & 8 deletions examples/x6-example-features/src/pages/scroller/index.tsx
Expand Up @@ -34,10 +34,12 @@ export default class Example extends React.Component {
height: 200,
padding: 10,
},
mousewheel: {
enabled: true,
modifiers: ['ctrl', 'meta'],
},
})

console.log(graph)

this.scroller = graph.scroller.widget

const rect = graph.addNode({
Expand Down Expand Up @@ -90,18 +92,15 @@ export default class Example extends React.Component {
}

onZoomOutClick = () => {
this.scroller.zoom(-0.2, { min: 0.2 })
this.scroller.zoom(-0.2)
}

onZoomInClick = () => {
this.scroller.zoom(0.2, { max: 2 })
this.scroller.zoom(0.2)
}

onZoomToFitClick = () => {
this.scroller.zoomToFit({
minScale: 0.2,
maxScale: 2,
})
this.scroller.zoomToFit()
}

render() {
Expand Down
5 changes: 5 additions & 0 deletions examples/x6-example-features/src/pages/shape/basic.tsx
Expand Up @@ -18,6 +18,9 @@ export default class Example extends React.Component {
repeat: 'watermark',
opacity: 0.1,
},
mousewheel: {
enabled: true,
},
})

const rect = graph.addNode({
Expand All @@ -31,6 +34,8 @@ export default class Example extends React.Component {

console.log(rect)

// graph.scale(0.5, 0.5, 20, 20)

graph.addNode({
type: 'basic.circle',
x: 160,
Expand Down
2 changes: 2 additions & 0 deletions packages/x6/package.json
Expand Up @@ -61,6 +61,7 @@
"dependencies": {
"csstype": "^2.6.9",
"jquery": "^3.4.1",
"jquery-mousewheel": "^3.1.13",
"lodash-es": "^4.17.15",
"mousetrap": "^1.6.3",
"utility-types": "^3.10.0"
Expand All @@ -70,6 +71,7 @@
"@babel/preset-env": "^7.9.6",
"@types/jest": "^25.2.1",
"@types/jquery": "^3.3.31",
"@types/jquery-mousewheel": "^3.1.8",
"@types/lodash-es": "^4.17.3",
"@types/node": "^14.0.1",
"@types/sinon": "^9.0.0",
Expand Down
1 change: 1 addition & 0 deletions packages/x6/src/addon/scroller/index.less
Expand Up @@ -6,6 +6,7 @@
position: relative;
box-sizing: border-box;
overflow: scroll;
outline: none;
cursor: move;
cursor: -moz-grabbing;
cursor: -webkit-grabbing;
Expand Down
35 changes: 18 additions & 17 deletions packages/x6/src/addon/scroller/index.ts
Expand Up @@ -626,18 +626,21 @@ export class Scroller extends View {
sy = Math.max(options.min, sy)
}

sx = this.graph.transform.clampScale(sx)
sy = this.graph.transform.clampScale(sy)

if (options.ox == null || options.oy == null) {
cx = center.x
cy = center.y
} else {
const zx = sx / this.sx
const zy = sy / this.sy
cx = options.ox - (options.ox - center.x) / zx
cy = options.oy - (options.oy - center.y) / zy
const fx = sx / this.sx
const fy = sy / this.sy
cx = options.ox - (options.ox - center.x) / fx
cy = options.oy - (options.oy - center.y) / fy
}

this.beforeManipulation()
this.graph.scale(sx, sy)
this.graph.transform.scale(sx, sy)
this.center(cx, cy)
this.afterManipulation()

Expand Down Expand Up @@ -835,18 +838,16 @@ export class Scroller extends View {

clientToLocalPoint(p: Point.PointLike): Point
clientToLocalPoint(x: number, y: number): Point
clientToLocalPoint(x: number | Point.PointLike, y?: number) {
if (typeof x === 'object') {
y = x.y // tslint:disable-line
x = x.x // tslint:disable-line
} else {
y = y as number // tslint:disable-line
}
clientToLocalPoint(a: number | Point.PointLike, b?: number) {
let x = typeof a === 'object' ? a.x : a
let y = typeof a === 'object' ? a.y : (b as number)

const ctm = this.graph.matrix()
const xx = x + (this.container.scrollLeft - this.padding.left - ctm.e)
const yy = y + (this.container.scrollTop - this.padding.top - ctm.f)
return new Point(xx / ctm.a, yy / ctm.d)

x += this.container.scrollLeft - this.padding.left - ctm.e
y += this.container.scrollTop - this.padding.top - ctm.f

return new Point(x / ctm.a, y / ctm.d)
}

localToBackgroundPoint(p: Point.PointLike): Point
Expand Down Expand Up @@ -1085,8 +1086,8 @@ namespace Util {
const top = Math.max(size.height - minHeight, 0)
return { left, top, right: left, bottom: top }
},
minVisibleWidth: 48,
minVisibleHeight: 48,
minVisibleWidth: 50,
minVisibleHeight: 50,
pageVisible: true,
pageBreak: true,
autoResize: true,
Expand Down
4 changes: 2 additions & 2 deletions packages/x6/src/global/util.ts
Expand Up @@ -2,9 +2,9 @@ import { Config } from './config'
import { snapToGrid as snap } from '../geometry/util'

export namespace Util {
export const snapToGrid = snap

export function prefix(suffix: string) {
return `${Config.prefixCls}-${suffix}`
}

export const snapToGrid = snap
}
26 changes: 13 additions & 13 deletions packages/x6/src/graph/coord.ts
Expand Up @@ -50,7 +50,7 @@ export class CoordManager extends Base {
return p.translate(this.getPageOffset())
}

localToPaperRect(
localToGraphRect(
x: number | Rectangle | Rectangle.RectangleLike,
y?: number,
width?: number,
Expand Down Expand Up @@ -79,14 +79,14 @@ export class CoordManager extends Base {
) {
const rect =
typeof x === 'number'
? this.localToPaperRect(x, y!, width!, height!)
: this.localToPaperRect(x)
? this.localToGraphRect(x, y!, width!, height!)
: this.localToGraphRect(x)
return rect.translate(this.getPageOffset())
}

graphToLocalPoint(x: number | Point | Point.PointLike, y?: number) {
const paperPoint = Point.create(x, y)
return Dom.transformPoint(paperPoint, this.graph.matrix().inverse())
const graphPoint = Point.create(x, y)
return Dom.transformPoint(graphPoint, this.graph.matrix().inverse())
}

clientToLocalPoint(x: number | Point | Point.PointLike, y?: number) {
Expand All @@ -96,8 +96,8 @@ export class CoordManager extends Base {

pageToLocalPoint(x: number | Point | Point.PointLike, y?: number) {
const pagePoint = Point.create(x, y)
const paperPoint = pagePoint.diff(this.getPageOffset())
return this.graphToLocalPoint(paperPoint)
const graphPoint = pagePoint.diff(this.getPageOffset())
return this.graphToLocalPoint(graphPoint)
}

graphToLocalRect(
Expand All @@ -106,8 +106,8 @@ export class CoordManager extends Base {
width?: number,
height?: number,
) {
const paperRect = Rectangle.create(x, y, width, height)
return Dom.transformRectangle(paperRect, this.graph.matrix().inverse())
const graphRect = Rectangle.create(x, y, width, height)
return Dom.transformRectangle(graphRect, this.graph.matrix().inverse())
}

clientToLocalRect(
Expand All @@ -126,10 +126,10 @@ export class CoordManager extends Base {
width?: number,
height?: number,
) {
const paperRect = Rectangle.create(x, y, width, height)
const graphRect = Rectangle.create(x, y, width, height)
const pageOffset = this.getPageOffset()
paperRect.x -= pageOffset.x
paperRect.y -= pageOffset.y
return this.graphToLocalRect(paperRect)
graphRect.x -= pageOffset.x
graphRect.y -= pageOffset.y
return this.graphToLocalRect(graphRect)
}
}
6 changes: 5 additions & 1 deletion packages/x6/src/graph/graph.ts
Expand Up @@ -14,6 +14,7 @@ import { DefsManager as Defs } from './defs'
import { GridManager as Grid } from './grid'
import { CoordManager as Coord } from './coord'
import { Keyboard as Shortcut } from './keyboard'
import { MouseWheel as Wheel } from './mousewheel'
import { MiniMapManager as MiniMap } from './minimap'
import { SnaplineManager as Snapline } from './snapline'
import { ScrollerManager as Scroller } from './scroller'
Expand Down Expand Up @@ -42,6 +43,7 @@ export class Graph extends Basecoat<EventArgs> {
public readonly scroller: Scroller
public readonly minimap: MiniMap
public readonly keyboard: Shortcut
public readonly mousewheel: Wheel

public get container() {
return this.view.container
Expand Down Expand Up @@ -70,6 +72,7 @@ export class Graph extends Basecoat<EventArgs> {
this.scroller = this.hook.createScrollerManager()
this.minimap = this.hook.createMiniMapManager()
this.keyboard = this.hook.createKeyboard()
this.mousewheel = this.hook.createMouseWheel()

this.setup()
}
Expand Down Expand Up @@ -259,7 +262,7 @@ export class Graph extends Basecoat<EventArgs> {
width?: number,
height?: number,
) {
return this.coord.localToPaperRect(x, y, width, height)
return this.coord.localToGraphRect(x, y, width, height)
}

localToClientRect(rect: Rectangle.RectangleLike): Rectangle
Expand Down Expand Up @@ -450,6 +453,7 @@ export namespace Graph {
export const View = GraphView
export const Renderer = ViewRenderer
export const Keyboard = Shortcut
export const MouseWheel = Wheel
export const BaseManager = Base
export const DefsManager = Defs
export const GridManager = Grid
Expand Down
7 changes: 7 additions & 0 deletions packages/x6/src/graph/hook.ts
Expand Up @@ -28,6 +28,7 @@ import { BackgroundManager } from './background'
import { HistoryManager } from './history'
import { MiniMapManager } from './minimap'
import { Keyboard } from './keyboard'
import { MouseWheel } from './mousewheel'

namespace Decorator {
export function hook(nilable?: boolean, hookName?: string | null) {
Expand Down Expand Up @@ -269,6 +270,11 @@ export class Hook extends Base implements Hook.IHook {
return new Keyboard({ graph: this.graph, ...this.options.keyboard })
}

@Decorator.hook()
createMouseWheel() {
return new MouseWheel({ graph: this.graph, ...this.options.mousewheel })
}

validateEdge(edge: Edge) {
const options = this.options.connecting

Expand Down Expand Up @@ -448,5 +454,6 @@ export namespace Hook {
createMiniMapManager: CreateManager<MiniMapManager>

createKeyboard: CreateManager<Keyboard>
createMouseWheel: CreateManager<MouseWheel>
}
}
9 changes: 7 additions & 2 deletions packages/x6/src/graph/keyboard.ts
Expand Up @@ -22,7 +22,8 @@ export class Keyboard extends Disposable implements IDisablable {
this.target = document
} else {
this.target = this.container
this.target.setAttribute('tab-index', '-1')
// ensure the container focusable
this.target.setAttribute('tabindex', '-1')
}

this.mousetrap = new Keyboard.Mousetrap(this.target as Element, this)
Expand All @@ -35,12 +36,14 @@ export class Keyboard extends Disposable implements IDisablable {
enable() {
if (this.disabled) {
this.options.enabled = true
this.graph.options.keyboard.enabled = true
}
}

disable() {
if (!this.disabled) {
this.options.enabled = false
this.graph.options.keyboard.enabled = false
}
}

Expand All @@ -57,7 +60,9 @@ export class Keyboard extends Disposable implements IDisablable {
}

private getKeys(keys: string | string[]) {
return (Array.isArray(keys) ? keys : [keys]).map(this.formatkey)
return (Array.isArray(keys) ? keys : [keys]).map((key) =>
this.formatkey(key),
)
}

protected formatkey(key: string) {
Expand Down

0 comments on commit 4146b04

Please sign in to comment.