Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

源码阅读 #4392

Draft
wants to merge 23 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
f52d2e4
feat:windows下编译修改
yelikang Aug 19, 2024
e4ed2d4
bug:x6小地图定位不准
yelikang Aug 19, 2024
df812a7
feat:部分源码备注
yelikang Aug 19, 2024
494716f
feat:x6-plugin-history,撤销回退插件原理
yelikang Aug 19, 2024
ff4bf71
feat: Dom公共方法封装(可借鉴)
yelikang Aug 19, 2024
db42367
feat:对象属性mixins
yelikang Aug 19, 2024
70702af
feat:Dom事件注册与Graph本身的事件注册区分开
yelikang Aug 19, 2024
65ddd45
feat: Renderer渲染器渲染原理
yelikang Aug 19, 2024
5ebb94a
feat:调试
yelikang Aug 19, 2024
1f88d3d
feat:鼠标交互,及元素捕捉+事件触发
yelikang Aug 19, 2024
c3b844e
feat:调试
yelikang Aug 20, 2024
624da97
feat:事件处理,构建自定义event
yelikang Aug 20, 2024
48f6c0d
feat: render及queueJob 任务队列
yelikang Aug 20, 2024
17bef50
feat:model中创建Node、Edge模型
yelikang Aug 20, 2024
86376ba
feat:元素捕捉逻辑(当前元素向上递归拥有data-cell-id的父元素的id值)
yelikang Aug 20, 2024
ea2b31b
feat: view层,事件handler,触发对应的CellView(NodeView/EdgeView)的事件监听
yelikang Aug 20, 2024
8b9675e
feat:事件触发,通过store存储之前event中的data数据,下次操作同类型事件能取到相应数据
yelikang Aug 20, 2024
6308950
feat:关于自定义事件event,存储自定义data的部分场景
yelikang Aug 20, 2024
0e97ca4
feat: CellView(NodeView/EdgeView)中包含Cell(Node/Edge)
yelikang Aug 20, 2024
7478b0b
feat: Model中的Collection添加Cell,通过事件告知Scheduler调度器,进行相应的CellView的创建,并通过…
yelikang Aug 20, 2024
b85ca7f
feat:调试
yelikang Aug 20, 2024
dc6ca1a
feat:事件委托,触发流程备注
yelikang Aug 20, 2024
a14c3c5
feat: coord 坐标转换
yelikang Aug 21, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion examples/x6-example-features/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"name": "@antv/x6-example-features",
"version": "2.1.1",
"scripts": {
"start": "export NODE_OPTIONS=--openssl-legacy-provider && umi dev",
"start": "set NODE_OPTIONS=--openssl-legacy-provider && umi dev",
"build": "umi build",
"lint": "eslint 'src/**/*.{js,ts}?(x)' --fix"
},
Expand Down
4 changes: 4 additions & 0 deletions examples/x6-example-features/src/pages/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,10 @@ const dataSource = [
example: 'history',
description: '时光回溯',
},
{
example: 'minimap',
description: '小地图',
},
].map((item, index) => ({ key: index, ...item }))

const columns = [
Expand Down
8 changes: 4 additions & 4 deletions examples/x6-example-features/src/pages/minimap/index.less
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@

.app-minimap {
position: absolute;
bottom: 0;
left: 620px;
width: 200px;
height: 150px;
bottom: 16px;
right: 167px;
width: 400px;
height: 400px;
}

.x6-widget-minimap-viewport {
Expand Down
68 changes: 47 additions & 21 deletions examples/x6-example-features/src/pages/minimap/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as React from 'react'
import { Graph } from '@antv/x6'
import { MiniMap } from '@antv/x6-plugin-minimap'
import { Graph } from '../../../../../packages/x6/src/index'
import { MiniMap } from '../../../../../packages/x6-plugin-minimap/src/index'
import { Scroller } from '@antv/x6-plugin-scroller'
import { Radio } from 'antd'
import { SimpleNodeView } from './simple-view'
Expand All @@ -18,29 +18,27 @@ export default class Example extends React.Component {

componentDidMount() {
this.graph = new Graph({
panning: {
enabled: true,
modifiers: [],
eventTypes: ['leftMouseDown'],
},
mousewheel: {
enabled: true,
},
container: this.container,
width: 600,
height: 320,
width: 1600,
height: 800,
background: {
color: '#F2F7FA',
},
})

this.graph.use(
new Scroller({
pageVisible: true,
pageBreak: false,
pannable: true,
}),
)
this.graph.use(
new MiniMap({
container: this.minimapContainer,
width: 200,
height: 160,
padding: 10,
}),
)
// this.graph.use(
// new Scroller({
// pannable: false,
// }),
// )

this.graph.addNode({
x: 200,
Expand Down Expand Up @@ -78,8 +76,8 @@ export default class Example extends React.Component {

const target = this.graph.addNode({
shape: 'circle',
x: 160,
y: 180,
x: 1160,
y: 2180,
width: 60,
height: 60,
label: 'World',
Expand All @@ -102,6 +100,30 @@ export default class Example extends React.Component {
},
},
})

// this.graph.use(
// new MiniMap({
// container: this.minimapContainer,
// width: 400,
// height: 400,
// padding: 1,
// preserveAspectRatio: false,
// graphOptions: {
// width: 400,
// height: 400,
// },
// }),
// )


this.graph.on('cell:click', ({ e, x, y, cell, view }) => {
console.log('graph cell:click')
})

this.graph.on('node:click',()=>{
console.log('graph node:click')
})

}

onMinimapViewChange = (val: string) => {
Expand Down Expand Up @@ -148,6 +170,9 @@ export default class Example extends React.Component {
refMiniMapContainer = (container: HTMLDivElement) => {
this.minimapContainer = container
}
changeSize = () => {
this.graph.resize(1800, 800)
}

render() {
return (
Expand All @@ -159,6 +184,7 @@ export default class Example extends React.Component {
defaultValue={'detailed'}
optionType="button"
/>
<button onClick={this.changeSize}>Change Size</button>
</div>
<div className="app-content" ref={this.refContainer} />
<div className="app-minimap" ref={this.refMiniMapContainer} />
Expand Down
12 changes: 11 additions & 1 deletion packages/x6-common/src/dom/event/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import './special'
export namespace Core {
let triggered: string | undefined


// Dom的事件注册,与Graph本身的事件注册机制区分开;使用Dom.Event.on进行Dom事件注册
export function on(
elem: Store.EventTarget,
types: string,
Expand Down Expand Up @@ -37,13 +39,14 @@ export namespace Core {
// if (!Util.isValidSelector(elem, selector)) {
// throw new Error('Delegate event with invalid selector.')
// }

// 确保elem进入store,后续dispatch 中Util.getHandlerQueue(elem, event)会用到
const store = Store.ensure(elem)

// Ensure the main handle
let mainHandler = store.handler
if (mainHandler == null) {
mainHandler = store.handler = function (e, ...args: any[]) {
// 事件处理器
return triggered !== e.type ? dispatch(elem, e, ...args) : undefined
}
}
Expand All @@ -61,6 +64,8 @@ export namespace Core {
}

let type = originType
// 事件名称hook,通过事件名转换成其它事件名称;EventHook.register方法注册转换逻辑
// 例如mouseenter 会被转换为mouseover 事件
let hook = EventHook.get(type)

// If selector defined, determine special event type, otherwise given type
Expand Down Expand Up @@ -106,8 +111,10 @@ export namespace Core {
Util.setHandlerId(handleObj.handler, guid)
}


// Add to the element's handler list, delegates in front
if (selector) {
// 有选择器的情况下(理解为具体的cell选择器),将delegateCount+1,代表有多少个具体cell选择器
bag.handlers.splice(bag.delegateCount, 0, handleObj)
bag.delegateCount += 1
} else {
Expand Down Expand Up @@ -209,6 +216,7 @@ export namespace Core {
evt: Event | EventObject | string,
...args: any[]
) {
// 构建自定义的event数据
const event = EventObject.create(evt)
event.delegateTarget = elem as Element

Expand Down Expand Up @@ -240,10 +248,12 @@ export namespace Core {
event.rnamespace == null ||
(handleObj.namespace && event.rnamespace.test(handleObj.namespace))
) {
// 恢复之前的操作数据
event.handleObj = handleObj
event.data = handleObj.data

const hookHandle = EventHook.get(handleObj.originType).handle
// console.log('dispatch 事件触发', handleObj.originType)

const result = hookHandle
? hookHandle(matched.elem as Store.EventTarget, event, ...args)
Expand Down
1 change: 1 addition & 0 deletions packages/x6-common/src/dom/event/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export namespace Store {

export function ensure(target: EventTarget) {
if (!cache.has(target)) {
// 构建以element为key 的events对象
cache.set(target, { events: Object.create(null) })
}
return cache.get(target)!
Expand Down
2 changes: 2 additions & 0 deletions packages/x6-common/src/dom/event/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ export namespace Util {
export namespace Util {
export function getHandlerQueue(elem: Store.EventTarget, event: EventObject) {
const queue = []
// Store中使用WeakMap进行cache缓存,缓存相关数据
const store = Store.get(elem)
const bag = store && store.events && store.events[event.type]
const handlers = (bag && bag.handlers) || []
Expand Down Expand Up @@ -161,6 +162,7 @@ export namespace Util {

// Add the remaining (directly-bound) handlers
if (delegateCount < handlers.length) {
// 截取delegateCount之后的handler,也就是用于具体cell选择器的handler
queue.push({ elem, handlers: handlers.slice(delegateCount) })
}

Expand Down
2 changes: 1 addition & 1 deletion packages/x6-common/src/dom/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
import * as Dom from './main'

// 封装Dom相关的操作方法,可以借鉴
export { Dom }
7 changes: 6 additions & 1 deletion packages/x6-common/src/dom/position.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,11 @@ export function height(elem: Element) {
const rect = elem.getBoundingClientRect()
return rect.height
}

/**
* 计算元素相对于父元素的绝对定位
* @param elem
* @returns
*/
export function position(elem: Element) {
const isFixed = computeStyle(elem, 'position') === 'fixed'
let offsetValue: ReturnType<typeof offset>
Expand All @@ -38,6 +42,7 @@ export function position(elem: Element) {
(offsetParent === doc.body || offsetParent === doc.documentElement) &&
computeStyle(offsetParent, 'position') === 'static'
) {
// 如果 offsetParent 是 body 或 html 并且其定位属性为 static,则继续寻找更高层的定位父元素
offsetParent = offsetParent.parentNode
}
if (offsetParent !== elem && isElement(offsetParent)) {
Expand Down
1 change: 1 addition & 0 deletions packages/x6-common/src/object/mixins.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
/**
* 对象属性混入mixins
* @see https://www.typescriptlang.org/docs/handbook/mixins.html
*/
export function applyMixins(derivedCtor: any, ...baseCtors: any[]) {
Expand Down
1 change: 1 addition & 0 deletions packages/x6-geometry/src/rectangle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -624,6 +624,7 @@ export class Rectangle extends Geometry implements Rectangle.RectangleLike {

/**
* Returns a rectangle that is a union of this rectangle and rectangle `rect`.
* 返回一个矩形区域,该矩形是两个矩形区域的并集(最大区域)。
*/
union(rect: Rectangle.RectangleLike | Rectangle.RectangleData) {
const ref = Rectangle.clone(rect)
Expand Down
3 changes: 3 additions & 0 deletions packages/x6-plugin-history/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,7 @@ export class History
this.model.on('batch:start', this.initBatchCommand, this)
this.model.on('batch:stop', this.storeBatchCommand, this)
if (this.options.eventNames) {
// 监听哪些事件操作需要进入撤销回退队列,统一进入addCommand中处理
this.options.eventNames.forEach((name, index) => {
this.handlers[index] = this.addCommand.bind(this, name)
this.model.on(name, this.handlers[index])
Expand Down Expand Up @@ -525,11 +526,13 @@ export class History
}

protected push(cmd: History.Command, options: KeyValue) {
// 有新的操作进入撤销队列undoStack时,重做队列redoStack清空
this.redoStack = []
if (cmd.batch) {
this.lastBatchIndex = Math.max(this.lastBatchIndex, 0)
this.emit('batch', { cmd, options })
} else {
// 操作进入撤销队列
this.undoStackPush(cmd)
this.consolidateCommands()
this.notify('add', cmd, options)
Expand Down
Loading
Loading