Compare commits

..

1 Commits

Author SHA1 Message Date
8e2616dfe1 feat: init vite 2022-12-19 22:21:22 +08:00
113 changed files with 18822 additions and 9017 deletions
.github/workflows
CONTRIBUTORSCONTRIBUTORS.svgLICENSEREADME.md
examples
package.json
packages
pnpm-lock.yaml
scripts
sites

@ -15,8 +15,7 @@ jobs:
steps:
- name:  Checkout
uses: actions/checkout@v3
with:
persist-credentials: false
- name: 🎉 Setup nodejs
uses: actions/setup-node@v3
with:

@ -20,7 +20,9 @@ jobs:
👋 @{{ author }}
Thanks for opening your first issue here! If you're reporting a 🐞 bug, please make sure you include steps to reproduce it.
To help make it easier for us to investigate your issue, please follow the [contributing guidelines](https://github.com/antvis/X6/blob/master/CONTRIBUTING.md).
We get a lot of issues on this repo, so please be patient and we will get back to you as soon as we can.
FIRST_PR: |

@ -1,23 +1,21 @@
BARM <284942955@qq.com>
Candy <563378816@qq.com>
Chaoqi ZHANG <prncoprs@163.com>
Clifford Fajardo <cliffordfajardo@users.noreply.github.com>
Chaoqi <HAN>
Clifford <ajard>
DaiGang <42136433+daigang666@users.noreply.github.com>
Dong <48054715+halodong@users.noreply.github.com>
Draco <Draco.coder@gmail.com>
Eve-Sama <17764594863@163.com>
Eve-Sama <948832626@qq.com>
Gossypol <31892817+gossypol@users.noreply.github.com>
HQidea <HQidea@users.noreply.github.com>
ImgBotApp <ImgBotHelp@gmail.com>
Indomi <indomi126@gmail.com>
James Tsang <wtzeng1@gmail.com>
Jógvan Olsen <jogvanolsen@hotmail.com>
Ken Geis <geis.ken@gmail.com>
Kent Wood <minzojian@hotmail.com>
James <san>
Jógvan <lse>
Ken <ei>
Limbo <49612796+JUST-Limbo@users.noreply.github.com>
Lixu <37231473+wflixu@users.noreply.github.com>
Lloyd Zhou <lloydzhou@users.noreply.github.com>
Lloyd <ho>
Lyn <47809781+lyn-boyu@users.noreply.github.com>
MOMO <329053928@qq.com>
Mingfei <az8641683@163.com>
@ -27,22 +25,17 @@ NewByVector <NewByVector@users.noreply.github.com>
Olive.Wang <olivewind.wang@gmail.com>
Opportunity <opportunity@live.in>
Questions <chip@twostewards.com>
RuiLin Dong <48054715+halodong@users.noreply.github.com>
RuiLin <on>
SSC <273702440@qq.com>
Samuel Bodin <1637651+bodinsamuel@users.noreply.github.com>
Simon He <57086651+Simon-He95@users.noreply.github.com>
Simon <>
Sindori <441933726@qq.com>
Struggle <1178825961@qq.com>
Struggle Roue <47975400+struggleRoue@users.noreply.github.com>
Susan <527971893@qq.com>
Thomas Zeugner <tomsoftware@gmx.de>
Tony Wu <93302820+tonywu6@users.noreply.github.com>
Thomas <eugne>
Tony <>
Utopia <greatauk11@gmail.com>
XLZY <1017866168@qq.com>
Xia Wenqi <xiawenqi90@gmail.com>
Xingjian Zhang <44231913+THUzxj@users.noreply.github.com>
Zhenyu Hou <skyking_H@hotmail.com>
_XiaoTian <istianlei@qq.com>
Xingjian <han>
Zhenyu <o>
arthur657834 <kingkom7834@126.com>
boyu.zlj <boyu.zlj@antgroup.com>
breezefaith <nyzhangzc@qq.com>
@ -58,8 +51,6 @@ kelin.zrh <34393362+AricZhu@users.noreply.github.com>
kingshuaishuai <ken.wang@mrs.ai>
kio <1421104933@qq.com>
lijing666 <lijing241@yeah.net>
linkun <33945539+linkun-wang@users.noreply.github.com>
linkun <linkun0922@163.com>
lopn <lopnxrp@126.com>
luchunwei <luchunwei@gmail.com>
luzhuang <364439895@qq.com>
@ -69,20 +60,17 @@ newbyvector <vectorse@126.com>
niexq <1879633916@qq.com>
niexq <niexq@firstgrid.cn>
njshuisheng <34205271+njshuisheng@users.noreply.github.com>
nobugforever <84232410+mengYu-Jin@users.noreply.github.com>
pengxingjian.pxj <pengxingjian.pxj@alibaba-inc.com>
pfdgithub <pfdgithub@users.noreply.github.com>
qingchi <qinky94@163.com>
qu <33251372+Qujh97@users.noreply.github.com>
sallen450 <qinghua10199@gmail.com>
semantic-release-bot <semantic-release-bot@martynus.net>
siaikin <abc1310054026@outlook.com>
vector <vectorse@126.com>
wenbei <38773084+wb-wenbei@users.noreply.github.com>
wgf <34190465+evelope@users.noreply.github.com>
wind X <35559153+XueMeijing@users.noreply.github.com>
wind <>
wjqsummer <52412389+wjqsummer@users.noreply.github.com>
wseven7677 <caoyu_92@126.com>
wtzeng1 <wtzeng1@gmail.com>
x6-bot <x6-bot@users.noreply.github.com>
xrkffgg <xrkffgg@gmail.com>
@ -91,12 +79,10 @@ zdc1111 <39116292+zdc1111@users.noreply.github.com>
€alix <qq287649920@gmail.com>
九思⚡⚡⚡ <2228429150@qq.com>
何腾飞 <avrin.live.cn@outlook.com>
依枫 <deng25st@163.com>
偏右 <afc163@gmail.com>
小耀 <jinyue.gjy@antfin.com>
崖 <bubkoo.wy@gmail.com>
崖崖崖 <bubkoo.wy@gmail.com>
张子睿 <411489774@qq.com>
文瑀 <wenyu.jqq@antfin.com>
映月 <38279397+orientMoon@users.noreply.github.com>
杨凌 <89915256@qq.com>

File diff suppressed because one or more lines are too long

Before

(image error) Size: 14 MiB

After

(image error) Size: 12 MiB

@ -1,6 +1,6 @@
MIT License
Copyright (c) 2021-2023 Alipay.inc
Copyright (c) 2021-2022 Alipay.inc
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

@ -6,17 +6,18 @@
<p align="center"><strong>提供简单易用的节点定制能力和开箱即用的交互组件方便我们快速搭建流程图、DAG 图、ER 图等图应用</strong></p>
<p align="center">
<a href="https://github.com/antvis/X6/actions/workflows/ci.yml"><img alt="build" src="https://img.shields.io/github/actions/workflow/status/antvis/x6/ci.yml?branch=master&style=for-the-badge&logo=github"></a>
<!-- <a href="https://app.codecov.io/gh/antvis/X6"><img alt="coverage" src="https://img.shields.io/codecov/c/gh/antvis/x6?logo=codecov&style=for-the-badge&token=15CO54WYUV"></a> -->
<a href="https://www.npmjs.com/package/@antv/x6"><img alt="NPM Package" src="https://img.shields.io/npm/v/@antv/x6.svg?logo=npm&style=for-the-badge"></a>
<a href="https://www.npmjs.com/package/@antv/x6"><img alt="NPM Downloads" src="https://img.shields.io/npm/dm/@antv/x6?logo=npm&style=for-the-badge"></a>
<a href="https://github.com/antvis/X6/actions/workflows/ci.yml"><img alt="build" src="https://img.shields.io/github/actions/workflow/status/antvis/x6/ci.yml?branch=master&logo=github&style=flat-square"></a>
<!-- <a href="https://app.codecov.io/gh/antvis/X6"><img alt="coverage" src="https://img.shields.io/codecov/c/gh/antvis/x6?logo=codecov&style=flat-square&token=15CO54WYUV"></a> -->
<a href="https://lgtm.com/projects/g/antvis/x6/context:javascript"><img alt="Language grade: JavaScript" src="https://img.shields.io/lgtm/grade/javascript/g/antvis/x6.svg?logo=lgtm&style=flat-square"></a>
<a href="https://www.npmjs.com/package/@antv/x6"><img alt="NPM Package" src="https://img.shields.io/npm/v/@antv/x6.svg?style=flat-square"></a>
<a href="https://www.npmjs.com/package/@antv/x6"><img alt="NPM Downloads" src="https://img.shields.io/npm/dm/@antv/x6?logo=npm&style=flat-square"></a>
</p>
<p align="center">
<a href="/LICENSE"><img src="https://img.shields.io/github/license/antvis/x6?style=for-the-badge" alt="MIT License"></a>
<a href="https://www.typescriptlang.org"><img alt="Language" src="https://img.shields.io/badge/language-TypeScript-blue.svg?style=for-the-badge"></a>
<a href="https://github.com/antvis/x6/pulls"><img alt="PRs Welcome" src="https://img.shields.io/badge/PRs-Welcome-brightgreen.svg?style=for-the-badge"></a>
<a href="https://x6.antv.antgroup.com"><img alt="website" src="https://img.shields.io/static/v1?label=&labelColor=505050&message=website&color=0076D6&style=for-the-badge&logo=google-chrome&logoColor=f5f5f5"></a>
<a href="/LICENSE"><img src="https://img.shields.io/github/license/antvis/x6?style=flat-square" alt="MIT License"></a>
<a href="https://www.typescriptlang.org"><img alt="Language" src="https://img.shields.io/badge/language-TypeScript-blue.svg?style=flat-square"></a>
<a href="https://github.com/antvis/x6/pulls"><img alt="PRs Welcome" src="https://img.shields.io/badge/PRs-Welcome-brightgreen.svg?style=flat-square"></a>
<a href="https://x6.antv.antgroup.com"><img alt="website" src="https://img.shields.io/static/v1?label=&labelColor=505050&message=website&color=0076D6&style=flat-square&logo=google-chrome&logoColor=0076D6"></a>
</p>
## 特性

24
examples/vite-example/.gitignore vendored Normal file

@ -0,0 +1,24 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
node_modules
dist
dist-ssr
*.local
# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?

@ -0,0 +1,13 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/antv.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>s</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/index.tsx"></script>
</body>
</html>

@ -0,0 +1,30 @@
{
"name": "@antv/vite-project",
"private": true,
"version": "2.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "tsc && vite build",
"prebuild": "rimraf dist",
"preview": "vite preview"
},
"dependencies": {
"lodash-es": "^4.17.15",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-helmet": "^6.0.0",
"react-router": "^6.5.0",
"react-router-dom": "^6.5.0"
},
"devDependencies": {
"@types/lodash-es": "^4.17.4",
"@types/react": "^18.0.26",
"@types/react-dom": "^18.0.9",
"@types/react-helmet": "^6.0.0",
"@vitejs/plugin-react-swc": "^3.0.0",
"less": "^4.1.1",
"typescript": "^4.9.3",
"vite": "^4.0.0"
}
}

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="28"><defs><linearGradient id="a" x1=".004%" x2="100.131%" y1="49.993%" y2="49.993%"><stop offset="0%" stop-color="#6500FF"/><stop offset="16%" stop-color="#6A09FF"/><stop offset="43%" stop-color="#7623FF"/><stop offset="77%" stop-color="#8A4CFF"/><stop offset="99%" stop-color="#996BFF"/></linearGradient><linearGradient id="b" x1="50.004%" x2="50.004%" y1="100.012%" y2="0%"><stop offset="0%" stop-color="#6500FF"/><stop offset="16%" stop-color="#6909FF"/><stop offset="43%" stop-color="#7523FF"/><stop offset="77%" stop-color="#894CFF"/><stop offset="99%" stop-color="#976BFF"/></linearGradient><linearGradient id="c" x1="49.854%" x2="49.854%" y1="100.255%" y2="0%"><stop offset="0%" stop-color="#FF6E06"/><stop offset="28%" stop-color="#FF770C"/><stop offset="75%" stop-color="#FF911C"/><stop offset="100%" stop-color="#FFA126"/></linearGradient><linearGradient id="d" x1="57351%" x2="57351%" y1="59860%" y2="35023%"><stop offset="0%" stop-color="#FF6E06"/><stop offset="28%" stop-color="#FF770C"/><stop offset="75%" stop-color="#FF911C"/><stop offset="100%" stop-color="#FFA126"/></linearGradient></defs><g fill="none" fill-rule="nonzero"><path fill="url(#a)" d="M1.955.004c-.029 0-.057 0-.088.002a1.41 1.41 0 0 0-.197.017A2.312 2.312 0 0 0 1.4.08a3.479 3.479 0 0 0-.179.061 3.768 3.768 0 0 0-.075.032l-.029.013-.057.028-.031.016L.98.257.95.275.91.298.883.317.825.355.79.381l-.03.022L.728.43.7.453C.68.468.662.483.645.5L.621.521.588.553l-.02.02A1.898 1.898 0 0 0 .46.691L.446.709.414.75A2.707 2.707 0 0 0 .348.84L.337.857.308.9l-.01.017L.29.931l3.784 2.214.801.855a.406.406 0 0 1-.019-.42.446.446 0 0 1 .37-.227H18.12c.045.003.09.005.137.005.961-.014 1.734-.758 1.737-1.674.002-.916-.765-1.664-1.726-1.683L1.955.004Z" transform="translate(.006)"/><path fill="url(#b)" d="m22.737 11.315-6.392 11.01a.438.438 0 0 1-.74.025l-4.063-6.995a1.724 1.724 0 0 0-.117-.23L4.667 3.459a2.32 2.32 0 0 1-.005-2.248A2.345 2.345 0 0 1 6.57.005L1.981.001A1.899 1.899 0 0 0 .908.294l-.1.068a2.405 2.405 0 0 0-.15.12A1.7 1.7 0 0 0 .462.69a1.797 1.797 0 0 0-.17.243 1.767 1.767 0 0 0-.028 1.9l.166.289 13.874 23.895a1.882 1.882 0 0 0 .793.776l.108.05a2.537 2.537 0 0 0 .18.069 2.14 2.14 0 0 0 .28.066 2.148 2.148 0 0 0 .19.02l.106.002c.04 0 .063 0 .086-.002a1.206 1.206 0 0 0 .19-.016 2.065 2.065 0 0 0 .27-.06 1.927 1.927 0 0 0 .168-.06l.089-.038.07-.036c.058-.03.073-.04.088-.048a2.596 2.596 0 0 0 .207-.142 1.851 1.851 0 0 0 .464-.537l.376-.64.081-.14 7.68-13.225a1.716 1.716 0 0 0 .047-1.75 1.74 1.74 0 0 0-3.039.01Z" transform="translate(.006)"/><path fill="url(#c)" d="M30.137 0h-6.459c-.935.018-1.684.847-1.684 1.863s.75 1.845 1.684 1.864c.046 0 .09-.003.134-.006h2.925c.214.032.374.23.374.465a.501.501 0 0 1-.025.157l-1.542 2.9c-.454.904-.147 2.036.685 2.53.832.492 1.874.159 2.328-.745l3.19-6c.029-.055.056-.111.08-.17l.003-.007c.015-.036.03-.072.043-.11l.002-.005.017-.052.008-.027c.008-.024.015-.048.021-.073l.012-.042.01-.04a2.826 2.826 0 0 0 .033-.191 2.31 2.31 0 0 0 .01-.077v-.011l.005-.09v-.022l.003-.091c0-1.115-.83-2.019-1.857-2.02Z" transform="translate(.006)"/><path fill="url(#d)" d="M19.881 7.41a.84.84 0 0 0-.725-.41h-6.325a.84.84 0 0 0-.725.41.804.804 0 0 0 0 .82l3.163 5.36a.84.84 0 0 0 .725.41.84.84 0 0 0 .725-.41l3.162-5.36a.804.804 0 0 0 0-.82Z" transform="translate(.006)"/></g></svg>

After

(image error) Size: 3.3 KiB

@ -0,0 +1,72 @@
:root {
color: rgb(255 255 255 / 87%);
font-weight: 400;
font-size: 16px;
font-family: Inter, Avenir, Helvetica, Arial, sans-serif;
line-height: 24px;
background-color: #242424;
color-scheme: light dark;
font-synthesis: none;
text-rendering: optimizelegibility;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-size-adjust: 100%;
}
a {
color: #646cff;
font-weight: 500;
text-decoration: inherit;
}
a:hover {
color: #535bf2;
}
body {
margin: 0;
}
html,
body,
#root {
height: 100%;
}
button {
padding: 0.6em 1.2em;
font-weight: 500;
font-size: 1em;
font-family: inherit;
background-color: #1a1a1a;
border: 1px solid transparent;
border-radius: 8px;
cursor: pointer;
transition: border-color 0.25s;
}
button:hover {
border-color: #646cff;
}
button:focus,
button:focus-visible {
outline: 4px auto -webkit-focus-ring-color;
}
@media (prefers-color-scheme: light) {
:root {
color: #213547;
background-color: #fff;
}
a:hover {
color: #747bff;
}
button {
background-color: #f9f9f9;
}
}

@ -0,0 +1,14 @@
import React from 'react'
import ReactDOM from 'react-dom/client'
import { createBrowserRouter, RouterProvider } from 'react-router-dom'
import { getRoutes } from './routes'
import './index.less'
const routes = getRoutes()
const router = createBrowserRouter(routes)
ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
<React.StrictMode>
<RouterProvider router={router} />
</React.StrictMode>,
)

@ -0,0 +1,43 @@
.wrap {
position: relative;
display: flex;
flex-direction: row;
height: 100%;
}
.nav {
display: flex;
flex-direction: column;
width: 220px;
padding: 0 16px;
border-right: 1px solid #e9e9e9;
section {
flex: 1;
overflow-x: hidden;
overflow-y: auto;
> ul {
margin: 0;
padding: 0;
}
ul {
padding-left: 16px;
li {
line-height: 1.6;
list-style: none;
}
}
}
}
.content {
flex: 1;
box-sizing: border-box;
padding: 24px;
overflow-x: hidden;
overflow-y: auto;
background: #fff;
}

@ -0,0 +1,57 @@
import React from 'react'
import { RouteObject } from 'react-router'
import { Outlet, NavLink } from 'react-router-dom'
import style from './_layout.module.less'
function renderLink(route: RouteObject, parentPath: string) {
let children = route.children
let indexRoute: RouteObject | null = null
if (children) {
children = children.slice()
const idx = children.findIndex((r) => r.index)
if (idx >= 0) {
indexRoute = children[idx]
children.splice(idx, 1)
}
}
const routeName = route.path
const routePath = `${parentPath}/${routeName}`
const element = indexRoute ? indexRoute.element : route.element
return (
<React.Fragment key={routePath}>
<li>
{element ? (
<NavLink
to={routePath}
className={({ isActive }) => (isActive ? 'active' : undefined)}
>
{routeName}
</NavLink>
) : (
routeName
)}
</li>
{children && <li>{renderLinks(children, routePath)}</li>}
</React.Fragment>
)
}
function renderLinks(routes: RouteObject[], parentPath = '') {
return <ul>{routes.map((route) => renderLink(route, parentPath))}</ul>
}
export default function Layout(props: { routes: RouteObject[] }) {
return (
<div className={style.wrap}>
<div className={style.nav}>
<h2>Examples</h2>
<section>{renderLinks(props.routes)}</section>
</div>
<div className={style.content}>
<Outlet />
</div>
</div>
)
}

@ -0,0 +1,5 @@
import React from 'react'
export default function transition() {
return <div>transition</div>
}

@ -0,0 +1,5 @@
import React from 'react'
export default function transition() {
return <div>auto-size</div>
}

@ -0,0 +1,87 @@
import React from 'react'
import { set } from 'lodash-es'
import { RouteObject } from 'react-router'
import { Helmet } from 'react-helmet'
function parseRouteConfig() {
const modules = import.meta.glob(`/src/pages/**/*.tsx`)
const config: Record<string, any> = {}
Object.keys(modules).forEach((filePath) => {
const routeParts = filePath
.replace(/^\/src\/pages\//, '') // 去除 /src/pages
.replace(/.tsx$/, '') // 去除文件名后缀
.replace(/\[([\w-]+)]/, ':$1') // 转换动态路由 [foo].tsx => :foo
.split('/')
set(config, routeParts, modules[filePath])
})
return config
}
function wrapSuspense(
mod: () => Promise<{
default: React.ComponentType<{ routes?: RouteObject[] }>
}>,
routes?: RouteObject[],
title?: string,
) {
if (!mod) {
return undefined
}
const Component = React.lazy(mod)
// 结合 Suspense ,这里可以自定义 loading 组件
return (
<React.Suspense fallback={null}>
{title && (
<Helmet>
<title>{title}</title>
</Helmet>
)}
{title ? <Component /> : <Component routes={routes} />}
</React.Suspense>
)
}
function wrapLayout(
routePath: string,
routeConfig: Record<string, any>,
): RouteObject {
const { _layout, ...rest } = routeConfig
const routes = routeConfigToRoute(rest, routePath)
return {
path: routePath,
element: wrapSuspense(_layout, routes),
children: routes,
}
}
function routeConfigToRoute(
config: Record<string, any>,
parentPath: string,
): RouteObject[] {
return Object.entries(config).map(([routePath, child]) => {
// () => import() 语法判断
if (typeof child === 'function') {
// 等于 index 则映射为当前根路由
const isIndex = routePath === 'index'
return {
index: isIndex,
path: isIndex ? undefined : routePath,
// 转换为组件
element: wrapSuspense(
child,
undefined,
isIndex ? parentPath : `${parentPath}/${routePath}`,
),
}
}
// 否则为目录,则查找下一层级
return wrapLayout(routePath, child)
})
}
export function getRoutes(): RouteObject[] {
const routeConfig = parseRouteConfig()
return [wrapLayout('/', routeConfig)]
}

@ -0,0 +1 @@
/// <reference types="vite/client" />

@ -0,0 +1,21 @@
{
"compilerOptions": {
"target": "ESNext",
"useDefineForClassFields": true,
"lib": ["DOM", "DOM.Iterable", "ESNext"],
"allowJs": false,
"skipLibCheck": true,
"esModuleInterop": false,
"allowSyntheticDefaultImports": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"module": "ESNext",
"moduleResolution": "Node",
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "react-jsx"
},
"include": ["src"],
"references": [{ "path": "./tsconfig.node.json" }]
}

@ -0,0 +1,9 @@
{
"compilerOptions": {
"composite": true,
"module": "ESNext",
"moduleResolution": "Node",
"allowSyntheticDefaultImports": true
},
"include": ["vite.config.ts"]
}

@ -0,0 +1,7 @@
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react-swc'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [react()],
})

@ -1,24 +1,3 @@
## @antv/x6-example-features [2.1.1](https://github.com/antvis/X6/compare/@antv/x6-example-features@2.1.0...@antv/x6-example-features@2.1.1) (2023-02-18)
### Bug Fixes
* mindmap demo duplicate node id, close [#3256](https://github.com/antvis/X6/issues/3256) ([#3257](https://github.com/antvis/X6/issues/3257)) ([c510756](https://github.com/antvis/X6/commit/c510756fe4e96c8e7471c2fb558e6019ec69b057))
# @antv/x6-example-features [2.1.0](https://github.com/antvis/X6/compare/@antv/x6-example-features@2.0.3...@antv/x6-example-features@2.1.0) (2023-02-17)
### Features
* history add max stack size ([#3253](https://github.com/antvis/X6/issues/3253)) ([fba5310](https://github.com/antvis/X6/commit/fba531064ad8027c451a81b60d5efd7f7314a0fa))
## @antv/x6-example-features [2.0.2](https://github.com/antvis/X6/compare/@antv/x6-example-features@2.0.1...@antv/x6-example-features@2.0.2) (2023-01-17)
### Bug Fixes
* **mindmap demo:** can not find target id when create edge ([#3144](https://github.com/antvis/X6/issues/3144)) ([bfc8d7f](https://github.com/antvis/X6/commit/bfc8d7f17ac900f70b696c1fa7a3f3f3a389103f))
## @antv/x6-example-features [2.0.1](https://github.com/antvis/X6/compare/@antv/x6-example-features@2.0.0...@antv/x6-example-features@2.0.1) (2022-12-16)

@ -1,7 +1,7 @@
{
"private": true,
"name": "@antv/x6-example-features",
"version": "2.1.1",
"version": "2.0.1",
"scripts": {
"start": "umi dev",
"build": "umi build",

@ -212,15 +212,12 @@ export default class Example extends React.Component {
return 'right'
},
})
const cells: Cell[] = []
const traverse = (hierarchyItem: HierarchyResult) => {
if (hierarchyItem) {
const { data, children } = hierarchyItem
// 检查当前遍历的节点已经存在还是需要新添加?
if (graph.hasCell(data.id)) {
const node = graph.getCellById(data.id)
node.prop('position', { x: hierarchyItem.x, y: hierarchyItem.y })
} else {
const node = graph.addNode({
cells.push(
graph.createNode({
id: data.id,
shape: data.type === 'topic-child' ? 'topic-child' : 'topic',
x: hierarchyItem.x,
@ -229,18 +226,13 @@ export default class Example extends React.Component {
height: data.height,
label: data.label,
type: data.type,
})
}
}),
)
if (children) {
children.forEach((item: HierarchyResult) => {
const { id, data } = item
// 先遍历子节点里面包含创建逻辑如果画布没有开启async的时候创建边会提示找不到target节点
traverse(item)
const eid = `${hierarchyItem.id}-->${id}`
// 检查当前边是否已经存在
if (!graph.hasCell(eid)) {
graph.addEdge({
id: eid,
cells.push(
graph.createEdge({
shape: 'mindmap-edge',
source: {
cell: hierarchyItem.id,
@ -265,13 +257,15 @@ export default class Example extends React.Component {
name: 'left',
},
},
})
}
}),
)
traverse(item)
})
}
}
}
traverse(result)
graph.resetCells(cells)
graph.centerContent()
}
@ -309,14 +303,9 @@ export default class Example extends React.Component {
if (dataItem) {
let item: MindMapData | null = null
const length = dataItem.children ? dataItem.children.length : 0
let nid = `${id}-${length + 1}`
if (graph.hasCell(nid)) {
// 如果通过length + 1拼接出来的节点id在画布中存在了就在id后面加上随机数
nid = nid + Math.random()
}
if (type === 'topic') {
item = {
id: nid,
id: `${id}-${length + 1}`,
type: 'topic-branch',
label: `分支主题${length + 1}`,
width: 100,
@ -324,7 +313,7 @@ export default class Example extends React.Component {
}
} else if (type === 'topic-branch') {
item = {
id: nid,
id: `${id}-${length + 1}`,
type: 'topic-child',
label: `子主题${length + 1}`,
width: 60,
@ -345,16 +334,10 @@ export default class Example extends React.Component {
const removeNode = (id: string) => {
const res = findItem(data, id)
const parentItem = res?.parent
const nodeItem = res?.node
if (parentItem && parentItem.children) {
const { children } = parentItem
const dataItem = res?.parent
if (dataItem && dataItem.children) {
const { children } = dataItem
const index = children.findIndex((item) => item.id === id)
// 删除的时候先删节点以及可能存在的子节点再调用render对data数据进行遍历
if (nodeItem && nodeItem.children) {
nodeItem.children.forEach((item) => graph.removeCell(item.id))
}
graph.removeCell(id)
return children.splice(index, 1)
}
return null

@ -1,104 +0,0 @@
import React from 'react'
import { Graph } from '@antv/x6'
import { Keyboard } from '@antv/x6-plugin-keyboard'
import { Selection } from '@antv/x6-plugin-selection'
import { History } from '@antv/x6-plugin-history'
import '../index.less'
export default class Example extends React.Component<
{},
{ graph: Graph | undefined }
> {
private container: HTMLDivElement
componentDidMount() {
const graph = new Graph({
container: this.container,
width: 800,
height: 600,
grid: true,
})
this.setState({ graph })
const selection = new Selection({ enabled: true })
const keyboard = new Keyboard({ enabled: true })
const history = new History({ enabled: true, stackSize: 5 })
graph.use(selection)
graph.use(keyboard)
graph.use(history)
graph.addNode({
x: 50,
y: 50,
width: 100,
height: 40,
attrs: { label: { text: 'A' } },
})
graph.addNode({
x: 250,
y: 50,
width: 100,
height: 40,
attrs: { label: { text: 'B' } },
})
graph.addNode({
x: 350,
y: 150,
width: 100,
height: 40,
attrs: { label: { text: 'C' } },
})
keyboard.bindKey('backspace', () => {
graph.removeCells(selection.getSelectedCells())
})
keyboard.bindKey('command+z', () => {
this.undo()
})
keyboard.bindKey('command+shift+z', () => {
this.redo()
})
}
refContainer = (container: HTMLDivElement) => {
this.container = container
}
enablePlugins = () => {
const { graph } = this.state
graph?.enablePlugins('keyboard')
}
disablePlugins = () => {
const { graph } = this.state
graph?.disablePlugins('keyboard')
}
undo = () => {
const { graph } = this.state
const history = graph?.getPlugin('history') as History
history?.undo()
}
redo = () => {
const { graph } = this.state
const history = graph?.getPlugin('history') as History
history?.redo()
}
render() {
return (
<div className="x6-graph-wrap">
<div ref={this.refContainer} className="x6-graph" />
<button onClick={this.enablePlugins}>enable</button>
<button onClick={this.disablePlugins}>disable</button>
<button onClick={this.undo}>undo</button>
<button onClick={this.redo}>redo</button>
</div>
)
}
}

@ -179,10 +179,6 @@ const dataSource = [
example: 'animation/transition',
description: '动画',
},
{
example: 'history',
description: '时光回溯',
},
].map((item, index) => ({ key: index, ...item }))
const columns = [

@ -4,10 +4,7 @@ import { Keyboard } from '@antv/x6-plugin-keyboard'
import { Selection } from '@antv/x6-plugin-selection'
import '../index.less'
export default class Example extends React.Component<
{},
{ graph: Graph | undefined }
> {
export default class Example extends React.Component {
private container: HTMLDivElement
componentDidMount() {
@ -18,8 +15,6 @@ export default class Example extends React.Component<
grid: true,
})
this.setState({ graph })
const selection = new Selection({ enabled: true })
const keyboard = new Keyboard({ enabled: true })
graph.use(selection)
@ -58,22 +53,10 @@ export default class Example extends React.Component<
this.container = container
}
enablePlugins = () => {
const { graph } = this.state
graph.enablePlugins('keyboard')
}
disablePlugins = () => {
const { graph } = this.state
graph.disablePlugins('keyboard')
}
render() {
return (
<div className="x6-graph-wrap">
<div ref={this.refContainer} className="x6-graph" />
<button onClick={this.enablePlugins}>enable</button>
<button onClick={this.disablePlugins}>disable</button>
</div>
)
}

@ -2,7 +2,7 @@
"name": "x6",
"private": true,
"scripts": {
"preinstall": "npx only-allow pnpm",
"preinstall": "node ./scripts/preinstall",
"lint:ts": "eslint '**/src/**/*.{js,ts}?(x)' --cache --fix",
"lint:style": "stylelint '**/src/**/*.less' --customSyntax postcss-less --cache --fix",
"lint": "run-s lint:ts lint:style",
@ -51,7 +51,7 @@
"prettier --write --ignore-unknown"
],
"*.less": [
"stylelint --syntax less --fix"
"stylelint --custom-syntax postcss-less --fix"
],
"*.js": [
"prettier --write"
@ -137,7 +137,6 @@
"lodash": "^4.17.21",
"npm-run-all": "^4.1.5",
"postcss": "^8.4.20",
"postcss-less": "^6.0.0",
"prettier": "^2.8.0",
"pretty-quick": "^3.1.1",
"rimraf": "^3.0.2",
@ -162,6 +161,7 @@
"typescript": "^4.9.3"
},
"devDependencies": {
"@rollup/plugin-terser": "^0.2.0"
"@rollup/plugin-terser": "^0.2.0",
"postcss-less": "^6.0.0"
}
}

@ -1,31 +1,3 @@
## @antv/x6-common [2.0.8](https://github.com/antvis/x6/compare/@antv/x6-common@2.0.7...@antv/x6-common@2.0.8) (2023-02-18)
### Bug Fixes
* fix typo for dom event handlers ([#3255](https://github.com/antvis/x6/issues/3255)) ([9b4fa86](https://github.com/antvis/x6/commit/9b4fa86daa587fe8818f3615bc1e40738a0f2319))
## @antv/x6-common [2.0.6](https://github.com/antvis/x6/compare/@antv/x6-common@2.0.5...@antv/x6-common@2.0.6) (2023-01-31)
### Bug Fixes
* fix index error for priorityQueue ([#3179](https://github.com/antvis/x6/issues/3179)) ([d64150b](https://github.com/antvis/x6/commit/d64150bfadf10fe21f44734a0267261260b8c53b))
## @antv/x6-common [2.0.5](https://github.com/antvis/x6/compare/@antv/x6-common@2.0.4...@antv/x6-common@2.0.5) (2023-01-18)
### Bug Fixes
* optimize css loader ([#3156](https://github.com/antvis/x6/issues/3156)) ([9c48ad8](https://github.com/antvis/x6/commit/9c48ad8dfc99e623a57855295d07c35be5483073))
## @antv/x6-common [2.0.4](https://github.com/antvis/x6/compare/@antv/x6-common@2.0.3...@antv/x6-common@2.0.4) (2022-12-20)
### Bug Fixes
* fix window incompatibility problem ([#3070](https://github.com/antvis/x6/issues/3070)) ([d8e1e63](https://github.com/antvis/x6/commit/d8e1e637d8027b9494cd26efc87815d74bd51366))
## @antv/x6-common [2.0.1](https://github.com/antvis/x6/compare/@antv/x6-common@2.0.0...@antv/x6-common@2.0.1) (2022-11-25)

@ -1,6 +1,6 @@
{
"name": "@antv/x6-common",
"version": "2.0.9",
"version": "2.0.3",
"description": "Basic toolkit for X6",
"main": "lib/index.js",
"module": "es/index.js",

@ -45,7 +45,7 @@ export class PriorityQueue<T> {
*/
insert(priority: number, value: T, id?: string) {
const item: PriorityQueue.DataItem<T> = { priority, value }
const index = this.data.length
const index = this.data.length - 1
if (id) {
item.id = id
this.index[id] = index
@ -96,9 +96,7 @@ export class PriorityQueue<T> {
const data = this.data
const peek = data[0]
const last = data.pop()!
if (peek.id) {
delete this.index[peek.id]
}
delete this.index[data.length]
if (data.length > 0) {
data[0] = last

@ -2,7 +2,6 @@ import { Platform } from '../platform'
interface CssModule {
name: string
loadTimes: number
styleElement: HTMLStyleElement | null
}
@ -11,10 +10,7 @@ const cssModules: CssModule[] = []
export function ensure(name: string, content: string) {
const cssModule = cssModules.find((m) => m.name === name)
if (cssModule) {
cssModule.loadTimes += 1
if (cssModule.loadTimes > 1) {
return
}
return
}
if (!Platform.isApplyingHMR()) {
@ -29,7 +25,6 @@ export function ensure(name: string, content: string) {
cssModules.push({
name,
loadTimes: 1,
styleElement,
})
}
@ -39,13 +34,7 @@ export function clean(name: string) {
const index = cssModules.findIndex((m) => m.name === name)
if (index > -1) {
const cssModule = cssModules[index]
cssModule.loadTimes -= 1
if (cssModule.loadTimes > 0) {
return
}
let styleElement = cssModule.styleElement
let styleElement = cssModules[index].styleElement
if (styleElement && styleElement.parentNode) {
styleElement.parentNode.removeChild(styleElement)
}

@ -6,8 +6,6 @@ export const CASE_SENSITIVE_ATTR = [
'attributeName',
'attributeType',
'repeatCount',
'textLength',
'lengthAdjust',
]
export type Attributes = { [key: string]: string | number | null | undefined }

@ -729,7 +729,7 @@ type TypeEventHandlersBase<TDelegateTarget, TData, TCurrentTarget, TTarget> = {
TCurrentTarget,
TTarget
>]?:
| TypeEventHandler<TDelegateTarget, TData, TCurrentTarget, TTarget, string>
| TypeEventHandler<TDelegateTarget, TData, TCurrentTarget, TTarget, TType>
| false
| Record<string, unknown>
}

@ -198,14 +198,7 @@ export function text(
const autoLineHeight = defaultLineHeight === 'auto'
const lineHeight = autoLineHeight ? '1.5em' : defaultLineHeight || '1em'
let needEmptyElem = true
const childs = elem.children
if (childs.length === 1 && childs[0].tagName.toUpperCase() === 'TITLE') {
needEmptyElem = false
}
if (needEmptyElem) {
empty(elem)
}
empty(elem)
attr(elem, {
// Preserve spaces, do not consecutive spaces to get collapsed to one.

@ -1,4 +1,4 @@
export { debounce, throttle } from 'lodash-es'
export { debounce } from 'lodash-es'
type Fn = (...args: any[]) => any

@ -1,10 +1,6 @@
// compatible with NodeList.prototype.forEach() before chrome 51
// https://developer.mozilla.org/en-US/docs/Web/API/NodeList/forEach
if (
typeof window === 'object' &&
window.NodeList &&
!NodeList.prototype.forEach
) {
if (window.NodeList && !NodeList.prototype.forEach) {
NodeList.prototype.forEach = Array.prototype.forEach as any
}

@ -7,7 +7,7 @@ declare module '@antv/x6/lib/graph/graph' {
enableClipboard: () => Graph
disableClipboard: () => Graph
toggleClipboard: (enabled?: boolean) => Graph
isClipboardEmpty: (options?: Clipboard.Options) => boolean
isClipboardEmpty: () => boolean
getCellsInClipboard: () => Cell[]
cleanClipboard: () => Graph
copy: (cells: Cell[], options?: Clipboard.CopyOptions) => Graph
@ -55,10 +55,10 @@ Graph.prototype.toggleClipboard = function (enabled?: boolean) {
return this
}
Graph.prototype.isClipboardEmpty = function (options?: Clipboard.Options) {
Graph.prototype.isClipboardEmpty = function () {
const clipboard = this.getPlugin('clipboard') as Clipboard
if (clipboard) {
return clipboard.isEmpty(options)
return clipboard.isEmpty()
}
return true
}

@ -89,12 +89,7 @@ export class ClipboardImpl {
}
}
isEmpty(options: ClipboardImpl.Options = {}) {
if (options.useLocalStorage) {
// With useLocalStorage turned on, no real cells can be obtained without deserialize first
// https://github.com/antvis/X6/issues/2573
this.deserialize(options)
}
isEmpty() {
return this.cells.length <= 0
}

@ -32,12 +32,14 @@ export class Clipboard
if (this.disabled) {
this.options.enabled = true
}
return this
}
disable() {
if (!this.disabled) {
this.options.enabled = false
}
return this
}
toggleEnabled(enabled?: boolean) {
@ -58,8 +60,8 @@ export class Clipboard
return this
}
isEmpty(options: Clipboard.Options = {}) {
return this.clipboardImpl.isEmpty(options)
isEmpty() {
return this.clipboardImpl.isEmpty()
}
getCellsInClipboard() {

@ -1,10 +1,3 @@
## @antv/x6-plugin-dnd [2.0.4](https://github.com/antvis/x6/compare/@antv/x6-plugin-dnd@2.0.3...@antv/x6-plugin-dnd@2.0.4) (2023-01-13)
### Bug Fixes
* change dragging container options ([#3139](https://github.com/antvis/x6/issues/3139)) ([7b091f3](https://github.com/antvis/x6/commit/7b091f35dee147c5e7bf97577e14e11ceb7e8e3d))
## @antv/x6-plugin-dnd [2.0.3](https://github.com/antvis/x6/compare/@antv/x6-plugin-dnd@2.0.2...@antv/x6-plugin-dnd@2.0.3) (2022-11-25)

@ -1,6 +1,6 @@
{
"name": "@antv/x6-plugin-dnd",
"version": "2.0.4",
"version": "2.0.3",
"description": "dnd plugin for X6",
"main": "lib/index.js",
"module": "es/index.js",

@ -81,10 +81,7 @@ export class Dnd extends View {
this.targetModel.startBatch('dnd')
Dom.addClass(this.container, 'dragging')
Dom.appendTo(
this.container,
this.options.draggingContainer || document.body,
)
Dom.appendTo(this.container, this.options.containerParent || document.body)
this.sourceNode = node
this.prepareDragging(node, e.clientX, e.clientY)
@ -484,7 +481,7 @@ export namespace Dnd {
// duration?: number
// easing?: string
// }
draggingContainer?: HTMLElement
containerParent?: HTMLElement
/**
* dnd tool box container.
*/

@ -1,10 +1,3 @@
# @antv/x6-plugin-history [2.2.0](https://github.com/antvis/x6/compare/@antv/x6-plugin-history@2.1.3...@antv/x6-plugin-history@2.2.0) (2023-02-17)
### Features
* history add max stack size ([#3253](https://github.com/antvis/x6/issues/3253)) ([fba5310](https://github.com/antvis/x6/commit/fba531064ad8027c451a81b60d5efd7f7314a0fa))
## @antv/x6-plugin-history [2.1.3](https://github.com/antvis/x6/compare/@antv/x6-plugin-history@2.1.2...@antv/x6-plugin-history@2.1.3) (2022-11-25)

@ -1,6 +1,6 @@
{
"name": "@antv/x6-plugin-history",
"version": "2.2.0",
"version": "2.1.3",
"description": "history plugin for X6",
"main": "lib/index.js",
"module": "es/index.js",

@ -25,7 +25,6 @@ export class History
protected batchLevel = 0
protected lastBatchIndex = -1
protected freezed = false
protected stackSize = 0 // 0: not limit
protected readonly handlers: (<T extends History.ModelEvents>(
event: T,
@ -34,8 +33,6 @@ export class History
constructor(options: History.Options) {
super()
const { stackSize = 0 } = options
this.stackSize = stackSize
this.options = Util.getOptions(options)
this.validator = new History.Validator({
history: this,
@ -104,7 +101,7 @@ export class History
const cmd = this.redoStack.pop()
if (cmd) {
this.applyCommand(cmd, options)
this.undoStackPush(cmd)
this.undoStack.push(cmd)
this.notify('redo', cmd, options)
}
}
@ -427,7 +424,7 @@ export class History
const cmds = this.filterBatchCommand(this.batchCommands)
if (cmds.length > 0) {
this.redoStack = []
this.undoStackPush(cmds)
this.undoStack.push(cmds)
this.consolidateCommands()
this.notify('add', cmds, options)
}
@ -501,7 +498,7 @@ export class History
this.lastBatchIndex = Math.max(this.lastBatchIndex, 0)
this.emit('batch', { cmd, options })
} else {
this.undoStackPush(cmd)
this.undoStack.push(cmd)
this.consolidateCommands()
this.notify('add', cmd, options)
}
@ -563,17 +560,6 @@ export class History
this.undoStack.pop()
}
protected undoStackPush(cmd: History.Commands) {
if (this.stackSize === 0) {
this.undoStack.push(cmd)
return
}
if (this.undoStack.length >= this.stackSize) {
this.undoStack.shift()
}
this.undoStack.push(cmd)
}
@Basecoat.dispose()
dispose() {
this.validator.dispose()
@ -628,9 +614,7 @@ export namespace History {
cancelInvalid?: boolean
}
export interface Options extends Partial<CommonOptions> {
stackSize?: number
}
export interface Options extends Partial<CommonOptions> {}
interface Data {
id?: string

@ -1,10 +1,3 @@
# @antv/x6-plugin-keyboard [2.2.0](https://github.com/antvis/x6/compare/@antv/x6-plugin-keyboard@2.1.4...@antv/x6-plugin-keyboard@2.2.0) (2023-02-06)
### Features
* keyboard support clear and custom trigger ([#3202](https://github.com/antvis/x6/issues/3202)) ([668c932](https://github.com/antvis/x6/commit/668c93242fbcebb987cccc3dcfd56982f7c66252))
## @antv/x6-plugin-keyboard [2.1.4](https://github.com/antvis/x6/compare/@antv/x6-plugin-keyboard@2.1.3...@antv/x6-plugin-keyboard@2.1.4) (2022-11-29)

@ -1,6 +1,6 @@
{
"name": "@antv/x6-plugin-keyboard",
"version": "2.2.0",
"version": "2.1.4",
"description": "keyboard plugin for X6",
"main": "lib/index.js",
"module": "es/index.js",

@ -14,8 +14,6 @@ declare module '@antv/x6/lib/graph/graph' {
action?: KeyboardImpl.Action,
) => Graph
unbindKey: (keys: string | string[], action?: KeyboardImpl.Action) => Graph
clearKeys: () => Graph
triggerKey: (key: string, action: KeyboardImpl.Action) => Graph
}
}
@ -73,19 +71,3 @@ Graph.prototype.unbindKey = function (
}
return this
}
Graph.prototype.clearKeys = function() {
const keyboard = this.getPlugin('keyboard') as Keyboard
if(keyboard) {
keyboard.clear()
}
return this
}
Graph.prototype.triggerKey = function(key: string, action: KeyboardImpl.Action) {
const keyboard = this.getPlugin('keyboard') as Keyboard
if(keyboard) {
keyboard.trigger(key, action)
}
return this
}

@ -27,10 +27,12 @@ export class Keyboard extends Disposable {
enable() {
this.keyboardImpl.enable()
return this
}
disable() {
this.keyboardImpl.disable()
return this
}
toggleEnabled(enabled?: boolean) {
@ -59,17 +61,6 @@ export class Keyboard extends Disposable {
return this
}
trigger(key: string, action?: KeyboardImpl.Action) {
this.keyboardImpl.trigger(key, action)
return this
}
clear() {
this.keyboardImpl.clear()
return this
}
unbindKey(keys: string | string[], action?: KeyboardImpl.Action) {
this.keyboardImpl.off(keys, action)
return this

@ -21,6 +21,7 @@ export class KeyboardImpl extends Disposable implements IDisablable {
private readonly options: KeyboardImpl.Options & { graph: Graph },
) {
super()
const scroller = this.graph.getPlugin('scroller') as any
this.container = scroller ? scroller.container : this.graph.container
@ -75,14 +76,6 @@ export class KeyboardImpl extends Disposable implements IDisablable {
this.mousetrap.unbind(this.getKeys(keys), action)
}
clear() {
this.mousetrap.reset()
}
trigger(key: string, action?: KeyboardImpl.Action) {
this.mousetrap.trigger(key, action)
}
private focus(e: EventArgs['node:mouseup']) {
const isInputEvent = this.isInputEvent(e.e)
if (isInputEvent) {
@ -102,7 +95,7 @@ export class KeyboardImpl extends Disposable implements IDisablable {
protected formatkey(key: string) {
const formated = key
.toLocaleLowerCase()
.toLowerCase()
.replace(/\s/g, '')
.replace('delete', 'del')
.replace('cmd', 'command')

@ -1,6 +1,6 @@
{
"name": "@antv/x6-plugin-scroller",
"version": "2.0.8",
"version": "2.0.7",
"description": "scroller plugin for X6",
"main": "lib/index.js",
"module": "es/index.js",

@ -35,16 +35,17 @@ export class Scroller extends Basecoat<Scroller.EventArgs> {
return this.scrollerImpl.container
}
constructor(public options: Scroller.Options) {
constructor(public readonly options: Scroller.Options) {
super()
CssLoader.ensure(this.name, content)
}
public init(graph: Graph) {
this.graph = graph
const options = ScrollerImpl.getOptions({ ...this.options, graph })
this.options = options
this.scrollerImpl = new ScrollerImpl(options)
this.scrollerImpl = new ScrollerImpl({
...this.options,
graph,
})
this.setup()
this.startListening()
this.updateClassName()
@ -400,10 +401,8 @@ export namespace Scroller {
export interface EventArgs extends ScrollerImpl.EventArgs {}
type EventType = 'leftMouseDown' | 'rightMouseDown'
interface ScrollerOptions extends ScrollerImpl.Options {
export interface Options extends ScrollerImpl.CommonOptions {
pannable?: boolean | { enabled: boolean; eventTypes: EventType[] }
modifiers?: string | ModifierKey[] | null // alt, ctrl, shift, meta
}
export type Options = Omit<ScrollerOptions, 'graph'>
}

@ -1128,8 +1128,7 @@ export namespace ScrollerImpl {
panning: { e: Dom.MouseMoveEvent }
'pan:stop': { e: Dom.MouseUpEvent }
}
export interface Options {
graph: Graph
export interface CommonOptions {
enabled?: boolean
className?: string
width?: number
@ -1152,6 +1151,10 @@ export namespace ScrollerImpl {
scroller: ScrollerImpl,
) => TransformManager.FitToContentFullOptions)
}
export interface Options extends CommonOptions {
graph: Graph
}
export interface CenterOptions {
padding?: NumberExt.SideOptions
}
@ -1263,7 +1266,7 @@ export namespace ScrollerImpl {
result.background == null
) {
result.background = graphOptions.background
options.graph.background.clear()
delete graphOptions.background
}
return result as ScrollerImpl.Options

@ -62,12 +62,14 @@ export class Selection extends Basecoat<SelectionImpl.EventArgs> {
if (this.disabled) {
this.options.enabled = true
}
return this
}
disable() {
if (!this.disabled) {
this.options.enabled = false
}
return this
}
toggleEnabled(enabled?: boolean) {

@ -29,10 +29,12 @@ export class Snapline extends Disposable {
enable() {
this.snaplineImpl.enable()
return this
}
disable() {
this.snaplineImpl.disable()
return this
}
toggleEnabled(enabled?: boolean) {

@ -1,10 +1,3 @@
## @antv/x6-plugin-transform [2.1.5](https://github.com/antvis/x6/compare/@antv/x6-plugin-transform@2.1.4...@antv/x6-plugin-transform@2.1.5) (2022-12-24)
### Bug Fixes
* add defense for view in transform plugin ([#3092](https://github.com/antvis/x6/issues/3092)) ([fb8098c](https://github.com/antvis/x6/commit/fb8098c1c06440dd69f4e93881fd36f7e6de2a56))
## @antv/x6-plugin-transform [2.1.4](https://github.com/antvis/x6/compare/@antv/x6-plugin-transform@2.1.3...@antv/x6-plugin-transform@2.1.4) (2022-12-07)

@ -1,6 +1,6 @@
{
"name": "@antv/x6-plugin-transform",
"version": "2.1.5",
"version": "2.1.4",
"description": "transform plugin for X6",
"main": "lib/index.js",
"module": "es/index.js",

@ -7,7 +7,6 @@ export class Transform extends Basecoat<Transform.EventArgs> {
private graph: Graph
protected widgets: Map<Node, TransformImpl> = new Map()
public name = 'transform'
private disabled = false
constructor(public readonly options: Transform.Options) {
super()
@ -16,9 +15,6 @@ export class Transform extends Basecoat<Transform.EventArgs> {
init(graph: Graph) {
this.graph = graph
if (this.disabled) {
return
}
this.startListening()
}
@ -32,24 +28,6 @@ export class Transform extends Basecoat<Transform.EventArgs> {
this.graph.off('blank:mousedown', this.onBlankMouseDown, this)
}
enable() {
if (this.disabled) {
this.disabled = false
this.startListening()
}
}
disable() {
if (!this.disabled) {
this.disabled = true
this.stopListening()
}
}
isEnabled() {
return !this.disabled
}
protected onNodeClick({ node }: EventArgs['node:click']) {
this.clearWidgets()
const widget = this.createTransform(node)

@ -107,11 +107,7 @@ export class TransformImpl extends View<TransformImpl.EventArgs> {
render() {
this.renderHandles()
if (this.view) {
this.view.addClass(Private.NODE_CLS)
}
this.view.addClass(Private.NODE_CLS)
Dom.addClass(this.container, this.containerClassName)
Dom.toggleClass(
this.container,
@ -157,9 +153,7 @@ export class TransformImpl extends View<TransformImpl.EventArgs> {
}
remove() {
if (this.view) {
this.view.removeClass(Private.NODE_CLS)
}
this.view.removeClass(Private.NODE_CLS)
return super.remove()
}
@ -493,7 +487,7 @@ export class TransformImpl extends View<TransformImpl.EventArgs> {
Dom.removeClass(this.container, `${this.containerClassName}-active`)
if (this.handle) {
Dom.removeClass(this.handle, `${this.containerClassName}-active-handle`)
Dom.removeClass(this.handle, `${this.containerClassName}-active`)
const pos = this.handle.getAttribute(
'data-position',

@ -1,17 +1,3 @@
## @antv/x6-react-components [2.0.7](https://github.com/antvis/x6/compare/@antv/x6-react-components@2.0.6...@antv/x6-react-components@2.0.7) (2023-01-31)
### Bug Fixes
* don't hide when click on color picker ([#3172](https://github.com/antvis/x6/issues/3172)) ([cae8625](https://github.com/antvis/x6/commit/cae8625feb20fd93cc8002fa6ed00d345d3cf33c))
## @antv/x6-react-components [2.0.6](https://github.com/antvis/x6/compare/@antv/x6-react-components@2.0.5...@antv/x6-react-components@2.0.6) (2023-01-17)
### Bug Fixes
* stop propagation when click menu item ([#3147](https://github.com/antvis/x6/issues/3147)) ([90dad14](https://github.com/antvis/x6/commit/90dad14d7e1ad8639b80b215596c8f4bad7b00ed))
## @antv/x6-react-components [2.0.5](https://github.com/antvis/x6/compare/@antv/x6-react-components@2.0.4...@antv/x6-react-components@2.0.5) (2022-11-25)

@ -1,6 +1,6 @@
{
"name": "@antv/x6-react-components",
"version": "2.0.7",
"version": "2.0.5",
"description": "React components for building x6 editors",
"main": "lib/index.js",
"module": "es/index.js",

@ -37,9 +37,7 @@ export class ColorPicker extends React.Component<
onDocumentClick = (e: React.MouseEvent) => {
const target = e.target as HTMLDivElement
const picker = this.container.querySelector('.sketch-picker')!
if (target === picker || picker.contains(target)) {
if (target === this.container || this.container.contains(target)) {
return
}
@ -61,9 +59,12 @@ export class ColorPicker extends React.Component<
if (this.props.onChange) {
this.props.onChange(value, event)
}
this.setState({
active: false,
color: value.rgb,
})
this.unbindDocEvent()
}
handleClick = (e: React.MouseEvent) => {
@ -83,10 +84,8 @@ export class ColorPicker extends React.Component<
}
}
refContainer = (popoverRef: { getContainer: () => HTMLDivElement }) => {
if (popoverRef) {
this.container = popoverRef.getContainer()
}
refContainer = (container: HTMLDivElement) => {
this.container = container
}
renderPicker() {
@ -124,12 +123,10 @@ export class ColorPicker extends React.Component<
{...popoverProps}
content={this.renderPicker()}
overlayClassName={`${baseCls}-overlay`}
destroyTooltipOnHide
ref={this.refContainer}
trigger={[]}
>
<div
style={style}
ref={this.refContainer}
onClick={this.handleClick}
className={classNames(baseCls, {
[`${baseCls}-disabled`]: disabled,

@ -26,7 +26,6 @@ class MenubarItemInner extends React.PureComponent<
}
onClick = (e: React.MouseEvent) => {
e.stopPropagation()
this.props.context.activeMenubar()
this.removeDeactive(e.currentTarget.parentElement)
this.active()

@ -26,7 +26,10 @@ export class ReactShapeView extends NodeView<ReactShape> {
const node = this.cell
if (container) {
const elem = React.createElement(Wrap, { node, graph: this.graph })
const graph = node.model ? node.model.graph : null
// Actually in the dnd plugin, this graph is empty,
// in order to make the external perception type of graph is a graph, rather than graph | null, so hack this.
const elem = React.createElement(Wrap, { node, graph: graph! })
if (Portal.isActive()) {
const portal = createPortal(elem, container) as ReactPortal
Portal.connect(this.cell.id, portal)

@ -1,10 +1,3 @@
## @antv/x6-vue-shape [2.0.9](https://github.com/antvis/x6/compare/@antv/x6-vue-shape@2.0.8...@antv/x6-vue-shape@2.0.9) (2022-12-21)
### Bug Fixes
* get graph from right place ([#3078](https://github.com/antvis/x6/issues/3078)) ([844ee5f](https://github.com/antvis/x6/commit/844ee5fa043cbcd788ec1693f88576e797426228))
## @antv/x6-vue-shape [2.0.7](https://github.com/antvis/x6/compare/@antv/x6-vue-shape@2.0.6...@antv/x6-vue-shape@2.0.7) (2022-12-09)

@ -1,6 +1,6 @@
{
"name": "@antv/x6-vue-shape",
"version": "2.0.9",
"version": "2.0.7",
"description": "X6 shape for rendering vue components.",
"main": "lib/index.js",
"module": "es/index.js",

@ -1,5 +1,4 @@
import { defineComponent, h, reactive, isVue3, Vue } from 'vue-demi'
import { Graph } from '@antv/x6'
import { VueShape } from './node'
let active = false
@ -10,7 +9,6 @@ export function connect(
component: any,
container: HTMLDivElement,
node: VueShape,
graph: Graph,
) {
if (active) {
const { Teleport, markRaw } = Vue as any
@ -19,7 +17,6 @@ export function connect(
render: () => h(Teleport, { to: container } as any, [h(component)]),
provide: () => ({
getNode: () => node,
getGraph: () => graph,
}),
}),
)

@ -26,7 +26,6 @@ export class VueShapeView extends NodeView<VueShape> {
this.unmountVueComponent()
const root = this.getComponentContainer()
const node = this.cell
const graph = this.graph
if (root) {
const { component } = shapeMaps[node.shape]
@ -41,13 +40,12 @@ export class VueShapeView extends NodeView<VueShape> {
provide() {
return {
getNode: () => node,
getGraph: () => graph,
}
},
})
} else if (isVue3) {
if (isActive()) {
connect(this.targetId(), component, root, node, graph)
connect(this.targetId(), component, root, node)
} else {
this.vm = createApp({
render() {
@ -56,7 +54,6 @@ export class VueShapeView extends NodeView<VueShape> {
provide() {
return {
getNode: () => node,
getGraph: () => graph,
}
},
})

@ -1,60 +1,3 @@
# @antv/x6 [2.3.0](https://github.com/antvis/x6/compare/@antv/x6@2.2.1...@antv/x6@2.3.0) (2023-02-06)
### Bug Fixes
* **scheduler:** remove spammy console.log ([#3200](https://github.com/antvis/x6/issues/3200)) ([1f83a2b](https://github.com/antvis/x6/commit/1f83a2b8a84b53303293e724e7f9d0ee49182efc))
### Features
* add options for positionCell api ([#3208](https://github.com/antvis/x6/issues/3208)) ([58c0fe4](https://github.com/antvis/x6/commit/58c0fe459c0314997440b4af7dc0443abe199924))
## @antv/x6 [2.2.1](https://github.com/antvis/x6/compare/@antv/x6@2.2.0...@antv/x6@2.2.1) (2023-02-02)
### Bug Fixes
* ensure the container in html view ([#3196](https://github.com/antvis/x6/issues/3196)) ([3a59703](https://github.com/antvis/x6/commit/3a59703f1c2da3ac8c8471eb9b864ac4cf468f97))
# @antv/x6 [2.2.0](https://github.com/antvis/x6/compare/@antv/x6@2.1.7...@antv/x6@2.2.0) (2023-01-31)
### Features
* add port events ([#3185](https://github.com/antvis/x6/issues/3185)) ([3265fe5](https://github.com/antvis/x6/commit/3265fe5b983f22e34d60c647212824961ecfdab5))
## @antv/x6 [2.1.6](https://github.com/antvis/x6/compare/@antv/x6@2.1.5...@antv/x6@2.1.6) (2023-01-19)
## @antv/x6 [2.1.5](https://github.com/antvis/x6/compare/@antv/x6@2.1.4...@antv/x6@2.1.5) (2023-01-13)
### Bug Fixes
* update group even group is empty ([#3117](https://github.com/antvis/x6/issues/3117)) ([6abd068](https://github.com/antvis/x6/commit/6abd0683eab22eb0fa1a4702642ab76b91320694))
## @antv/x6 [2.1.4](https://github.com/antvis/x6/compare/@antv/x6@2.1.3...@antv/x6@2.1.4) (2023-01-03)
### Bug Fixes
* optimize rendering logic to prevent loops ([#3108](https://github.com/antvis/x6/issues/3108)) ([45337e4](https://github.com/antvis/x6/commit/45337e4a62224aaffd60fc8b2670a071c5560796))
## @antv/x6 [2.1.3](https://github.com/antvis/x6/compare/@antv/x6@2.1.2...@antv/x6@2.1.3) (2022-12-24)
### Bug Fixes
* schedule edge when source and target is not ready ([#3090](https://github.com/antvis/x6/issues/3090)) ([019333d](https://github.com/antvis/x6/commit/019333d79d7f22c44c400f29d501497f4323af1a))
## @antv/x6 [2.1.1](https://github.com/antvis/x6/compare/@antv/x6@2.1.0...@antv/x6@2.1.1) (2022-12-19)
### Bug Fixes
* arrowhead not get options bug ([#3065](https://github.com/antvis/x6/issues/3065)) ([3b668fe](https://github.com/antvis/x6/commit/3b668feb4eac47994f52d0cc977d22a8a2c06acd))
* set snapToGrid to false by default ([#3066](https://github.com/antvis/x6/issues/3066)) ([e2bb71d](https://github.com/antvis/x6/commit/e2bb71d95484b29187fafca97f1a386e9b984095))
# @antv/x6 [2.1.0](https://github.com/antvis/x6/compare/@antv/x6@2.0.9...@antv/x6@2.1.0) (2022-12-19)

@ -1,6 +1,6 @@
{
"name": "@antv/x6",
"version": "2.5.1",
"version": "2.1.0",
"description": "JavaScript diagramming library that uses SVG and HTML for rendering",
"main": "lib/index.js",
"module": "es/index.js",

@ -702,8 +702,8 @@ export class Graph extends Basecoat<EventArgs> {
/**
* Position the center of graph to the center of the viewport.
*/
center(options?: Transform.CenterOptions) {
return this.centerPoint(options)
center() {
return this.centerPoint()
}
/**
@ -712,25 +712,13 @@ export class Graph extends Basecoat<EventArgs> {
* only center along the specified dimension and keep the other coordinate
* unchanged.
*/
centerPoint(
x: number,
y: null | number,
options?: Transform.CenterOptions,
): this
centerPoint(
x: null | number,
y: number,
options?: Transform.CenterOptions,
): this
centerPoint(optons?: Transform.CenterOptions): this
centerPoint(
x?: number | null | Transform.CenterOptions,
y?: number | null,
options?: Transform.CenterOptions,
) {
centerPoint(x: number, y: null | number): this
centerPoint(x: null | number, y: number): this
centerPoint(): this
centerPoint(x?: number | null, y?: number | null) {
const scroller = this.getPlugin<any>('scroller')
if (scroller) {
scroller.centerPoint(x as number, y as number, options)
scroller.centerPoint(x as number, y as number)
} else {
this.transform.centerPoint(x as number, y as number)
}
@ -749,10 +737,10 @@ export class Graph extends Basecoat<EventArgs> {
return this
}
centerCell(cell: Cell, options?: Transform.PositionContentOptions) {
centerCell(cell: Cell) {
const scroller = this.getPlugin<any>('scroller')
if (scroller) {
scroller.centerCell(cell, options)
scroller.centerCell(cell)
} else {
this.transform.centerCell(cell)
}
@ -764,11 +752,10 @@ export class Graph extends Basecoat<EventArgs> {
point: Point.PointLike,
x: number | string,
y: number | string,
options: Transform.CenterOptions = {},
) {
const scroller = this.getPlugin<any>('scroller')
if (scroller) {
scroller.positionPoint(point, x, y, options)
scroller.positionPoint(point, x, y)
} else {
this.transform.positionPoint(point, x, y)
}
@ -776,14 +763,10 @@ export class Graph extends Basecoat<EventArgs> {
return this
}
positionRect(
rect: Rectangle.RectangleLike,
direction: Transform.Direction,
options?: Transform.CenterOptions,
) {
positionRect(rect: Rectangle.RectangleLike, direction: Transform.Direction) {
const scroller = this.getPlugin<any>('scroller')
if (scroller) {
scroller.positionRect(rect, direction, options)
scroller.positionRect(rect, direction)
} else {
this.transform.positionRect(rect, direction)
}
@ -791,14 +774,10 @@ export class Graph extends Basecoat<EventArgs> {
return this
}
positionCell(
cell: Cell,
direction: Transform.Direction,
options?: Transform.CenterOptions,
) {
positionCell(cell: Cell, direction: Transform.Direction) {
const scroller = this.getPlugin<any>('scroller')
if (scroller) {
scroller.positionCell(cell, direction, options)
scroller.positionCell(cell, direction)
} else {
this.transform.positionCell(cell, direction)
}
@ -1214,56 +1193,15 @@ export class Graph extends Basecoat<EventArgs> {
}
getPlugin<T extends Graph.Plugin>(pluginName: string): T | undefined {
return Array.from(this.installedPlugins).find(
(plugin) => plugin.name === pluginName,
) as T
}
let result: Graph.Plugin | undefined
getPlugins<T extends Graph.Plugin[]>(pluginName: string[]): T | undefined {
return Array.from(this.installedPlugins).filter((plugin) =>
pluginName.includes(plugin.name),
) as T
}
disablePlugins(plugins: string[] | string) {
let postPlugins = plugins
if (!Array.isArray(postPlugins)) {
postPlugins = [postPlugins]
}
const aboutToChangePlugins = this.getPlugins(postPlugins)
aboutToChangePlugins?.forEach((plugin) => {
plugin?.disable?.()
this.installedPlugins.forEach((plugin) => {
if (plugin.name === pluginName) {
result = plugin
}
})
return this
}
enablePlugins(plugins: string[] | string) {
let postPlugins = plugins
if (!Array.isArray(postPlugins)) {
postPlugins = [postPlugins]
}
const aboutToChangePlugins = this.getPlugins(postPlugins)
aboutToChangePlugins?.forEach((plugin) => {
plugin?.enable?.()
})
return this
}
disposePlugins(plugins: string[] | string) {
let postPlugins = plugins
if (!Array.isArray(postPlugins)) {
postPlugins = [postPlugins]
}
const aboutToChangePlugins = this.getPlugins(postPlugins)
aboutToChangePlugins?.forEach((plugin) => {
plugin.dispose()
})
return this
}
isPluginEnabled(pluginName: string) {
const pluginIns = this.getPlugin(pluginName)
return pluginIns?.isEnabled?.()
return result as T
}
// #endregion
@ -1411,8 +1349,5 @@ export namespace Graph {
name: string
init: (graph: Graph, ...options: any[]) => any
dispose: () => void
disable?: () => void
enable?: () => void
isEnabled?: () => boolean
}
}

@ -55,8 +55,6 @@ export namespace Options {
onPortRendered?: (args: OnPortRenderedArgs) => void
onEdgeLabelRendered?: (args: OnEdgeLabelRenderedArgs) => void
createCellView?: (this: Graph, cell: Cell) => CellView | null | undefined
}
export interface ManualBooleans {

@ -3,9 +3,7 @@ import { Base } from './base'
export class VirtualRenderManager extends Base {
protected init() {
this.resetRenderArea = FunctionExt.throttle(this.resetRenderArea, 200, {
leading: true,
})
this.resetRenderArea = FunctionExt.debounce(this.resetRenderArea, 200)
this.resetRenderArea()
this.startListening()
}

@ -244,13 +244,6 @@ export class Model extends Basecoat<Model.EventArgs> {
return node
}
updateNode(metadata: Node.Metadata, options: Model.SetOptions = {}) {
const node = this.createNode(metadata)
const prop = node.getProp()
node.dispose()
return this.updateCell(prop, options)
}
createNode(metadata: Node.Metadata) {
return Node.create(metadata)
}
@ -265,13 +258,6 @@ export class Model extends Basecoat<Model.EventArgs> {
return Edge.create(metadata)
}
updateEdge(metadata: Edge.Metadata, options: Model.SetOptions = {}) {
const edge = this.createEdge(metadata)
const prop = edge.getProp()
edge.dispose()
return this.updateCell(prop, options)
}
addCell(cell: Cell | Cell[], options: Model.AddOptions = {}) {
if (Array.isArray(cell)) {
return this.addCells(cell, options)
@ -309,23 +295,6 @@ export class Model extends Basecoat<Model.EventArgs> {
return this
}
updateCell(prop: Cell.Properties, options: Model.SetOptions = {}): boolean {
const existing = prop.id && this.getCell(prop.id)
if (existing) {
return this.batchUpdate(
'update',
() => {
Object.keys(prop).forEach((key) =>
existing.setProp(key, prop[key], options),
)
return true
},
prop,
)
}
return false
}
removeCell(cellId: string, options?: Collection.RemoveOptions): Cell | null
removeCell(cell: Cell, options?: Collection.RemoveOptions): Cell | null
removeCell(

@ -265,32 +265,6 @@ function findRoute(
return null
}
function snap(vertices: Point[], gridSize = 10) {
if (vertices.length <= 1) {
return vertices
}
for (let i = 0, len = vertices.length; i < len - 1; i += 1) {
const first = vertices[i]
const second = vertices[i + 1]
if (first.x === second.x) {
const x = gridSize * Math.round(first.x / gridSize)
if (first.x !== x) {
first.x = x
second.x = x
}
} else if (first.y === second.y) {
const y = gridSize * Math.round(first.y / gridSize)
if (first.y !== y) {
first.y = y
second.y = y
}
}
}
return vertices
}
export const router: Router.Definition<ManhattanRouterOptions> = function (
vertices,
optionsRaw,
@ -308,7 +282,7 @@ export const router: Router.Definition<ManhattanRouterOptions> = function (
)
const oldVertices = vertices.map((p) => Point.create(p))
const newVertices: Point[] = []
let newVertices: Point[] = []
// The origin of first route's grid, does not need snapping
let tailPoint = sourceEndpoint
@ -377,7 +351,10 @@ export const router: Router.Definition<ManhattanRouterOptions> = function (
}
if (options.snapToGrid) {
return snap(newVertices, edgeView.graph.grid.getGridSize())
newVertices = newVertices.map((vertice) => {
const gridSize = edgeView.graph.grid.getGridSize()
return vertice.snapToGrid(gridSize)
})
}
return newVertices

@ -74,7 +74,6 @@ class Arrowhead extends ToolsView.ToolItem<EdgeView, Arrowhead.Options> {
x: coords.x,
y: coords.y,
options: {
...this.options,
toolId: this.cid,
},
})

@ -7,7 +7,7 @@ export class JobQueue {
private initialTime = Date.now()
queueJob(job: Job) {
if (job.priority & JOB_PRIORITY.PRIOR) {
if (job.priority === JOB_PRIORITY.PRIOR) {
job.cb()
} else {
const index = this.findInsertionIndex(job)
@ -81,20 +81,11 @@ export class JobQueue {
}
private findInsertionIndex(job: Job) {
let left = 0
let ins = this.queue.length
let right = ins - 1
const priority = job.priority
while (left <= right) {
const mid = ((right - left) >> 1) + left
if (priority <= this.queue[mid].priority) {
left = mid + 1
} else {
ins = mid
right = mid - 1
}
let start = 0
while (this.queue[start] && this.queue[start].priority >= job.priority) {
start += 1
}
return ins
return start
}
private scheduleJob() {
@ -144,10 +135,10 @@ export interface Job {
}
export enum JOB_PRIORITY {
RenderEdge = /**/ 1 << 1,
RenderNode = /**/ 1 << 2,
Update = /* */ 1 << 3,
PRIOR = /* */ 1 << 20,
RenderEdge = 1,
RenderNode = 2,
Update = 3,
PRIOR = 100,
}
// function findInsertionIndex(job: Job) {

@ -1,4 +1,4 @@
import { KeyValue, Dom, Disposable, FunctionExt } from '@antv/x6-common'
import { KeyValue, Dom, Disposable } from '@antv/x6-common'
import { Rectangle } from '@antv/x6-geometry'
import { Model, Cell } from '../model'
import { View, CellView, NodeView, EdgeView } from '../view'
@ -8,7 +8,6 @@ import { Graph } from '../graph'
export class Scheduler extends Disposable {
public views: KeyValue<Scheduler.View> = {}
public willRemoveViews: KeyValue<Scheduler.View> = {}
protected zPivots: KeyValue<Comment>
private graph: Graph
private renderArea?: Rectangle
@ -52,7 +51,7 @@ export class Scheduler extends Disposable {
protected onModelReseted({ options }: Model.EventArgs['reseted']) {
this.queue.clearJobs()
this.removeZPivots()
this.resetViews()
this.removeViews()
this.renderViews(this.model.getCells(), options)
}
@ -60,8 +59,12 @@ export class Scheduler extends Disposable {
this.renderViews([cell], options)
}
protected onCellRemoved({ cell }: Model.EventArgs['cell:removed']) {
this.removeViews([cell])
protected onCellRemoved({ cell, options }: Model.EventArgs['cell:removed']) {
const viewItem = this.views[cell.id]
if (viewItem) {
const view = viewItem.view
this.requestViewUpdate(view, Scheduler.FLAG_REMOVE, options)
}
}
protected onCellZIndexChanged({
@ -178,15 +181,13 @@ export class Scheduler extends Disposable {
}
}
if (viewItem) {
this.requestViewUpdate(
viewItem.view,
flag,
options,
this.getRenderPriority(viewItem.view),
false,
)
}
this.requestViewUpdate(
viewItem.view,
flag,
options,
cell.isNode() ? JOB_PRIORITY.RenderNode : JOB_PRIORITY.RenderEdge,
false,
)
})
this.flush()
@ -215,43 +216,10 @@ export class Scheduler extends Disposable {
}
if (result) {
if (
cell.isEdge() &&
(result & view.getFlag(['source', 'target'])) === 0
) {
this.queue.queueJob({
id,
priority: JOB_PRIORITY.RenderEdge,
cb: () => {
this.updateView(view, flag, options)
},
})
}
console.log('left flag', result) // eslint-disable-line
}
}
protected removeViews(cells: Cell[]) {
cells.forEach((cell) => {
const id = cell.id
const viewItem = this.views[id]
if (viewItem) {
this.willRemoveViews[id] = viewItem
delete this.views[id]
this.queue.queueJob({
id,
priority: this.getRenderPriority(viewItem.view),
cb: () => {
this.removeView(viewItem.view)
},
})
}
})
this.flush()
}
protected flush() {
this.graph.options.async
? this.queue.queueFlush()
@ -264,13 +232,10 @@ export class Scheduler extends Disposable {
const viewItem = this.views[ids[i]]
if (viewItem && viewItem.state === Scheduler.ViewState.WAITTING) {
const { view, flag, options } = viewItem
this.requestViewUpdate(
view,
flag,
options,
this.getRenderPriority(view),
false,
)
const priority = view.cell.isNode()
? JOB_PRIORITY.RenderNode
: JOB_PRIORITY.RenderEdge
this.requestViewUpdate(view, flag, options, priority, false)
}
}
@ -316,25 +281,23 @@ export class Scheduler extends Disposable {
}
}
protected resetViews() {
this.willRemoveViews = { ...this.views }
Object.keys(this.willRemoveViews).forEach((id) => {
const viewItem = this.willRemoveViews[id]
protected removeViews() {
Object.keys(this.views).forEach((id) => {
const viewItem = this.views[id]
if (viewItem) {
this.removeView(viewItem.view)
this.removeView(viewItem.view.cell)
}
})
this.views = {}
this.willRemoveViews = {}
}
protected removeView(view: CellView) {
const cell = view.cell
const viewItem = this.willRemoveViews[cell.id]
if (view) {
protected removeView(cell: Cell) {
const viewItem = this.views[cell.id]
if (viewItem) {
viewItem.view.remove()
delete this.willRemoveViews[cell.id]
delete this.views[cell.id]
}
return viewItem.view
}
protected toggleVisible(cell: Cell, visible: boolean) {
@ -412,22 +375,15 @@ export class Scheduler extends Disposable {
}
protected createCellView(cell: Cell) {
const createViewHook = this.graph.options.createCellView
if (createViewHook) {
const ret = FunctionExt.call(createViewHook, this.graph, cell)
if (ret || ret === null) {
return ret
}
}
const view = cell.view
const options = { graph: this.graph }
const view = cell.view
if (view != null && typeof view === 'string') {
const def = CellView.registry.get(view)
if (def) {
return new def(cell, options) // eslint-disable-line new-cap
}
return CellView.registry.onNotFound(view)
}
@ -450,16 +406,10 @@ export class Scheduler extends Disposable {
for (let i = 0, n = edges.length; i < n; i += 1) {
const edge = edges[i]
const viewItem = this.views[edge.id]
if (!viewItem) {
continue
}
const edgeView = viewItem.view
if (!this.isViewMounted(edgeView)) {
continue
}
const flagLabels: FlagManager.Action[] = ['update']
if (edge.getTargetCell() === cell) {
flagLabels.push('target')
@ -478,39 +428,10 @@ export class Scheduler extends Disposable {
}
protected isInRenderArea(view: CellView) {
if (!this.renderArea) {
return true
}
if (view.isNodeView()) {
const node = view.cell
return this.renderArea.isIntersectWithRect(node.getBBox())
}
if (view.isEdgeView()) {
const edge = view.cell
const sourceCell = edge.getSourceCell()
const targetCell = edge.getTargetCell()
if (sourceCell) {
const sourceViewItem = this.views[sourceCell.id]
if (sourceViewItem && !this.isViewMounted(sourceViewItem.view)) {
return false
}
}
if (targetCell) {
const targetViewItem = this.views[targetCell.id]
if (targetViewItem && !this.isViewMounted(targetViewItem.view)) {
return false
}
}
}
return true
}
protected getRenderPriority(view: CellView) {
return view.cell.isNode()
? JOB_PRIORITY.RenderNode
: JOB_PRIORITY.RenderEdge
return (
!this.renderArea ||
this.renderArea.isIntersectWithRect(view.cell.getBBox())
)
}
@Disposable.dispose()

@ -36,8 +36,7 @@ export namespace HTML {
}
protected renderHTMLComponent() {
const container =
this.selectors && (this.selectors.foContent as HTMLDivElement)
const container = this.selectors.foContent as Element
if (container) {
Dom.empty(container)
const content = shapeMaps[this.cell.shape]

@ -1398,7 +1398,6 @@ export class EdgeView<
}
onMouseDown(e: Dom.MouseDownEvent, x: number, y: number) {
this.notifyMouseDown(e, x, y)
this.startEdgeDragging(e, x, y)
}
@ -2192,9 +2191,7 @@ export class EdgeView<
for (let i = 0, ii = cells.length; i < ii; i += 1) {
const view = graph.findViewByCell(cells[i])
// Prevent highlighting new edge
// Close https://github.com/antvis/X6/issues/2853
if (!view || view.cell.id === this.cell.id) {
if (!view) {
continue
}

@ -357,12 +357,7 @@ export class NodeView<
protected updatePorts() {
const groups = this.cell.getParsedGroups()
const groupList = Object.keys(groups)
if (groupList.length === 0) {
this.updatePortGroup()
} else {
groupList.forEach((groupName) => this.updatePortGroup(groupName))
}
Object.keys(groups).forEach((groupName) => this.updatePortGroup(groupName))
}
protected updatePortGroup(groupName?: string) {
@ -457,28 +452,6 @@ export class NodeView<
return { e, x, y, view, node, cell } as NodeView.PositionEventArgs<E>
}
protected getPortEventArgs<E>(
e: E,
port: string,
pos?: { x: number; y: number },
) {
const view = this // eslint-disable-line
const node = view.cell
const cell = node
if (pos) {
return {
e,
x: pos.x,
y: pos.y,
view,
node,
cell,
port,
} as NodeView.PositionEventArgs<E>
}
return { e, view, node, cell, port } as NodeView.MouseEventArgs<E>
}
notifyMouseDown(e: Dom.MouseDownEvent, x: number, y: number) {
super.onMouseDown(e, x, y)
this.notify('node:mousedown', this.getEventArgs(e, x, y))
@ -494,33 +467,19 @@ export class NodeView<
this.notify('node:mouseup', this.getEventArgs(e, x, y))
}
notifyPortEvent(
name: string,
e: Dom.EventObject,
pos?: { x: number; y: number },
) {
const port = this.findAttr('port', e.target)
if (port) {
this.notify(name, this.getPortEventArgs(e, port, pos))
}
}
onClick(e: Dom.ClickEvent, x: number, y: number) {
super.onClick(e, x, y)
this.notify('node:click', this.getEventArgs(e, x, y))
this.notifyPortEvent('node:port:click', e, { x, y })
}
onDblClick(e: Dom.DoubleClickEvent, x: number, y: number) {
super.onDblClick(e, x, y)
this.notify('node:dblclick', this.getEventArgs(e, x, y))
this.notifyPortEvent('node:port:dblclick', e, { x, y })
}
onContextMenu(e: Dom.ContextMenuEvent, x: number, y: number) {
super.onContextMenu(e, x, y)
this.notify('node:contextmenu', this.getEventArgs(e, x, y))
this.notifyPortEvent('node:port:contextmenu', e, { x, y })
}
onMouseDown(e: Dom.MouseDownEvent, x: number, y: number) {
@ -528,7 +487,6 @@ export class NodeView<
return
}
this.notifyMouseDown(e, x, y)
this.notifyPortEvent('node:port:mousedown', e, { x, y })
this.startNodeDragging(e, x, y)
}
@ -552,7 +510,6 @@ export class NodeView<
})
}
this.notifyMouseMove(e, x, y)
this.notifyPortEvent('node:port:mousemove', e, { x, y })
}
this.setEventData<EventData.Mousemove>(e, data)
@ -565,7 +522,6 @@ export class NodeView<
this.stopMagnetDragging(e, x, y)
} else {
this.notifyMouseUp(e, x, y)
this.notifyPortEvent('node:port:mouseup', e, { x, y })
if (action === 'move') {
const meta = data as EventData.Moving
const view = meta.targetView || this
@ -584,26 +540,22 @@ export class NodeView<
onMouseOver(e: Dom.MouseOverEvent) {
super.onMouseOver(e)
this.notify('node:mouseover', this.getEventArgs(e))
this.notifyPortEvent('node:port:mouseover', e)
}
onMouseOut(e: Dom.MouseOutEvent) {
super.onMouseOut(e)
this.notify('node:mouseout', this.getEventArgs(e))
this.notifyPortEvent('node:port:mouseout', e)
}
onMouseEnter(e: Dom.MouseEnterEvent) {
this.updateClassName(e)
super.onMouseEnter(e)
this.notify('node:mouseenter', this.getEventArgs(e))
this.notifyPortEvent('node:port:mouseenter', e)
}
onMouseLeave(e: Dom.MouseLeaveEvent) {
super.onMouseLeave(e)
this.notify('node:mouseleave', this.getEventArgs(e))
this.notifyPortEvent('node:port:mouseleave', e)
}
onMouseWheel(e: Dom.EventObject, x: number, y: number, delta: number) {
@ -895,6 +847,7 @@ export class NodeView<
) {
this.graph.model.startBatch('add-edge')
const edgeView = this.createEdgeFromMagnet(magnet, x, y)
edgeView.notifyMouseDown(e, x, y) // backwards compatibility events
edgeView.setEventData(
e,
edgeView.prepareArrowheadDragging('target', {
@ -905,7 +858,6 @@ export class NodeView<
}),
)
this.setEventData<Partial<EventData.Magnet>>(e, { edgeView })
edgeView.notifyMouseDown(e, x, y)
}
protected getDefaultEdge(sourceView: CellView, sourceMagnet: Element) {
@ -1135,13 +1087,14 @@ export namespace NodeView {
interface MagnetEventArgs {
magnet: Element
}
export interface MouseEventArgs<E> {
e: E
node: Node
cell: Node
view: NodeView
port?: string
}
export interface PositionEventArgs<E>
extends MouseEventArgs<E>,
CellView.PositionEventArgs {}
@ -1166,17 +1119,6 @@ export namespace NodeView {
'node:mousewheel': PositionEventArgs<Dom.EventObject> &
CellView.MouseDeltaEventArgs
'node:port:click': PositionEventArgs<Dom.ClickEvent>
'node:port:dblclick': PositionEventArgs<Dom.DoubleClickEvent>
'node:port:contextmenu': PositionEventArgs<Dom.ContextMenuEvent>
'node:port:mousedown': PositionEventArgs<Dom.MouseDownEvent>
'node:port:mousemove': PositionEventArgs<Dom.MouseMoveEvent>
'node:port:mouseup': PositionEventArgs<Dom.MouseUpEvent>
'node:port:mouseover': MouseEventArgs<Dom.MouseOverEvent>
'node:port:mouseout': MouseEventArgs<Dom.MouseOutEvent>
'node:port:mouseenter': MouseEventArgs<Dom.MouseEnterEvent>
'node:port:mouseleave': MouseEventArgs<Dom.MouseLeaveEvent>
'node:customevent': PositionEventArgs<Dom.MouseDownEvent> & {
name: string
}

24572
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

8
scripts/preinstall Executable file

@ -0,0 +1,8 @@
#!/usr/bin/env node
if (!/pnpm/.test(process.env.npm_execpath || '')) {
console.warn(
`This repository requires using pnpm as the package manager for scripts to work properly.`,
)
process.exit(1)
}

@ -1,19 +1,18 @@
if (window) {
;(window as any).react = require('react')
;(window as any).reactDom = require('react-dom')
;(window as any).antd = require('antd')
;(window as any).dagre = require('dagre')
;(window as any).x6 = require('@antv/x6')
;(window as any).x6PluginSnapline = require('@antv/x6-plugin-snapline')
;(window as any).x6PluginClipboard = require('@antv/x6-plugin-clipboard')
;(window as any).x6PluginKeyboard = require('@antv/x6-plugin-keyboard')
;(window as any).x6PluginSelection = require('@antv/x6-plugin-selection')
;(window as any).x6PluginTransform = require('@antv/x6-plugin-transform')
;(window as any).x6PluginStencil = require('@antv/x6-plugin-stencil')
;(window as any).x6PluginHistory = require('@antv/x6-plugin-history')
;(window as any).x6ReactShape = require('@antv/x6-react-shape')
;(window as any).layout = require('@antv/layout')
;(window as any).classnames = require('classnames')
;(window as any).hierarchy = require('@antv/hierarchy')
;(window as any).elkjs = require('elkjs/lib/elk.bundled.js')
}
(window as any).react = require('react');
(window as any).reactDom = require('react-dom');
(window as any).antd = require('antd');
(window as any).dagre = require('dagre');
(window as any).x6 = require('@antv/x6');
(window as any).x6PluginSnapline = require('@antv/x6-plugin-snapline');
(window as any).x6PluginClipboard = require('@antv/x6-plugin-clipboard');
(window as any).x6PluginKeyboard = require('@antv/x6-plugin-keyboard');
(window as any).x6PluginSelection = require('@antv/x6-plugin-selection');
(window as any).x6PluginTransform = require('@antv/x6-plugin-transform');
(window as any).x6PluginStencil = require('@antv/x6-plugin-stencil');
(window as any).x6PluginHistory = require('@antv/x6-plugin-history');
(window as any).x6ReactShape = require('@antv/x6-react-shape');
(window as any).layout = require('@antv/layout');
(window as any).hierarchy = require('@antv/hierarchy');
(window as any).elkjs = require('elkjs/lib/elk.bundled.js');
}

@ -1,26 +1,23 @@
import { defineConfig } from 'dumi'
import { repository, version } from './package.json'
import { defineConfig } from 'dumi';
import { repository, version } from './package.json';
export default defineConfig({
locales: [
{ id: 'zh', name: '中文' },
{ id: 'en', name: 'English' },
],
locales: [{ id: 'zh', name: '中文' }, { id: 'en', name: 'English' }],
themeConfig: {
title: 'X6',
description: 'JavaScript diagramming library',
defaultLanguage: 'zh',
siteUrl: 'https://x6.antv.antgroup.com',
isAntVSite: false,
githubUrl: repository, // GitHub 地址
showSearch: true, // 是否显示搜索框
showGithubCorner: true, // 是否显示头部的 GitHub icon
showGithubStars: true, // 是否显示 GitHub star 数量
showAntVProductsCard: true, // 是否显示 AntV 产品汇总的卡片
showLanguageSwitcher: false, // 是否显示官网语言切换
showWxQrcode: true, // 是否显示头部菜单的微信公众号
showChartResize: true, // 是否在 demo 页展示图表视图切换
showAPIDoc: false, // 是否在 demo 页展示API文档
githubUrl: repository, // GitHub 地址
showSearch: true, // 是否显示搜索框
showGithubCorner: true, // 是否显示头部的 GitHub icon
showGithubStars: true, // 是否显示 GitHub star 数量
showAntVProductsCard: true, // 是否显示 AntV 产品汇总的卡片
showLanguageSwitcher: false, // 是否显示官网语言切换
showWxQrcode: true, // 是否显示头部菜单的微信公众号
showChartResize: true, // 是否在 demo 页展示图表视图切换
showAPIDoc: false, // 是否在 demo 页展示API文档
versions: {
[version]: 'https://x6.antv.antgroup.com',
'1.x': 'https://x6.antv.vision',
@ -76,8 +73,7 @@ export default defineConfig({
zh: 'X6 是基于 HTML 和 SVG 的图编辑引擎,提供低成本的定制能力和开箱即用的内置扩展,方便我们快速搭建 DAG 图、ER 图、流程图、血缘图等应用。',
en: 'X6 是基于 HTML 和 SVG 的图编辑引擎,提供低成本的定制能力和开箱即用的内置扩展,方便我们快速搭建 DAG 图、ER 图、流程图、血缘图等应用。',
},
image:
'https://mdn.alipayobjects.com/huamei_f4t1bn/afts/img/A*A1g0RaZ-GJcAAAAAAAAAAAAADtOHAQ/original',
image: 'https://mdn.alipayobjects.com/huamei_f4t1bn/afts/img/A*A1g0RaZ-GJcAAAAAAAAAAAAADtOHAQ/original',
buttons: [
{
text: {
@ -156,44 +152,19 @@ export default defineConfig({
zh: '可视化编排可以用简单的方式将复杂的流程呈现出来,让用户更容易理解工作流',
en: '可视化编排可以用简单的方式将复杂的流程呈现出来,让用户更容易理解工作流',
},
image:
'https://mdn.alipayobjects.com/huamei_f4t1bn/afts/img/A*QsT0TpxA8-AAAAAAAAAAAAAADtOHAQ/original',
image: 'https://mdn.alipayobjects.com/huamei_f4t1bn/afts/img/A*QsT0TpxA8-AAAAAAAAAAAAAADtOHAQ/original',
isAppLogo: true,
},
],
companies: [
{
name: '阿里云',
img: 'https://gw.alipayobjects.com/mdn/rms_2274c3/afts/img/A*V_xMRIvw2iwAAAAAAAAAAABkARQnAQ',
},
{
name: '支付宝',
img: 'https://gw.alipayobjects.com/mdn/rms_2274c3/afts/img/A*lYDrRZvcvD4AAAAAAAAAAABkARQnAQ',
},
{
name: '天猫',
img: 'https://gw.alipayobjects.com/mdn/rms_2274c3/afts/img/A*BQrxRK6oemMAAAAAAAAAAABkARQnAQ',
},
{
name: '淘宝网',
img: 'https://gw.alipayobjects.com/mdn/rms_2274c3/afts/img/A*1l8-TqUr7UcAAAAAAAAAAABkARQnAQ',
},
{
name: '网上银行',
img: 'https://gw.alipayobjects.com/mdn/rms_2274c3/afts/img/A*ZAKFQJ5Bz4MAAAAAAAAAAABkARQnAQ',
},
{
name: '京东',
img: 'https://gw.alipayobjects.com/mdn/rms_2274c3/afts/img/A*yh-HRr3hCpgAAAAAAAAAAABkARQnAQ',
},
{
name: 'yunos',
img: 'https://gw.alipayobjects.com/mdn/rms_2274c3/afts/img/A*_js7SaNosUwAAAAAAAAAAABkARQnAQ',
},
{
name: '菜鸟',
img: 'https://gw.alipayobjects.com/mdn/rms_2274c3/afts/img/A*TgV-RZDODJIAAAAAAAAAAABkARQnAQ',
},
{ name: '阿里云', img: 'https://gw.alipayobjects.com/mdn/rms_2274c3/afts/img/A*V_xMRIvw2iwAAAAAAAAAAABkARQnAQ' },
{ name: '支付宝', img: 'https://gw.alipayobjects.com/mdn/rms_2274c3/afts/img/A*lYDrRZvcvD4AAAAAAAAAAABkARQnAQ', },
{ name: '天猫', img: 'https://gw.alipayobjects.com/mdn/rms_2274c3/afts/img/A*BQrxRK6oemMAAAAAAAAAAABkARQnAQ', },
{ name: '淘宝网', img: 'https://gw.alipayobjects.com/mdn/rms_2274c3/afts/img/A*1l8-TqUr7UcAAAAAAAAAAABkARQnAQ', },
{ name: '网上银行', img: 'https://gw.alipayobjects.com/mdn/rms_2274c3/afts/img/A*ZAKFQJ5Bz4MAAAAAAAAAAABkARQnAQ', },
{ name: '京东', img: 'https://gw.alipayobjects.com/mdn/rms_2274c3/afts/img/A*yh-HRr3hCpgAAAAAAAAAAABkARQnAQ', },
{ name: 'yunos', img: 'https://gw.alipayobjects.com/mdn/rms_2274c3/afts/img/A*_js7SaNosUwAAAAAAAAAAABkARQnAQ', },
{ name: '菜鸟', img: 'https://gw.alipayobjects.com/mdn/rms_2274c3/afts/img/A*TgV-RZDODJIAAAAAAAAAAABkARQnAQ', },
],
docs: [
{
@ -288,28 +259,27 @@ export default defineConfig({
},
],
docsearchOptions: {
appId: '7J0MWEOGMO',
apiKey: 'e0d8089bb224298dfd4415b3e98bb700',
indexName: 'x6_sites_2.0',
versionV3: true,
apiKey: 'fe8bee8366e56a9463229c3c81200866',
indexName: 'antv_x6',
},
playground: {
extraLib: '',
container:
'<div id="container" style="min-width: 400px; min-height: 600px;"></div>',
container: '<div id="container"></div>',
devDependencies: {
typescript: 'latest',
},
},
announcement: {
zh: '',
en: '',
},
en: ''
}
},
mfsu: false,
alias: {
'@': __dirname,
},
links: [],
scripts: [],
})
links: [
],
scripts: [
],
})

@ -1,56 +1,3 @@
## @antv/x6-sites [1.5.3](https://github.com/antvis/x6/compare/@antv/x6-sites@1.5.2...@antv/x6-sites@1.5.3) (2023-02-23)
## @antv/x6-sites [1.5.2](https://github.com/antvis/x6/compare/@antv/x6-sites@1.5.1...@antv/x6-sites@1.5.2) (2023-02-18)
# @antv/x6-sites [1.5.0](https://github.com/antvis/x6/compare/@antv/x6-sites@1.4.1...@antv/x6-sites@1.5.0) (2023-02-06)
### Features
* keyboard support clear and custom trigger ([#3202](https://github.com/antvis/x6/issues/3202)) ([668c932](https://github.com/antvis/x6/commit/668c93242fbcebb987cccc3dcfd56982f7c66252))
# @antv/x6-sites [1.4.0](https://github.com/antvis/x6/compare/@antv/x6-sites@1.3.2...@antv/x6-sites@1.4.0) (2023-01-31)
### Bug Fixes
* fix index error for priorityQueue ([#3179](https://github.com/antvis/x6/issues/3179)) ([d64150b](https://github.com/antvis/x6/commit/d64150bfadf10fe21f44734a0267261260b8c53b))
* prevent highlighting new edge ([#3170](https://github.com/antvis/x6/issues/3170)) ([bd30f7f](https://github.com/antvis/x6/commit/bd30f7f61de530a9b6671aaedd4be2e026de8d44))
### Features
* add port events ([#3185](https://github.com/antvis/x6/issues/3185)) ([3265fe5](https://github.com/antvis/x6/commit/3265fe5b983f22e34d60c647212824961ecfdab5))
## @antv/x6-sites [1.3.2](https://github.com/antvis/x6/compare/@antv/x6-sites@1.3.1...@antv/x6-sites@1.3.2) (2023-01-13)
### Bug Fixes
* change dragging container options ([#3139](https://github.com/antvis/x6/issues/3139)) ([7b091f3](https://github.com/antvis/x6/commit/7b091f35dee147c5e7bf97577e14e11ceb7e8e3d))
* update group even group is empty ([#3117](https://github.com/antvis/x6/issues/3117)) ([6abd068](https://github.com/antvis/x6/commit/6abd0683eab22eb0fa1a4702642ab76b91320694))
## @antv/x6-sites [1.3.1](https://github.com/antvis/x6/compare/@antv/x6-sites@1.3.0...@antv/x6-sites@1.3.1) (2023-01-03)
### Bug Fixes
* optimize rendering logic to prevent loops ([#3108](https://github.com/antvis/x6/issues/3108)) ([45337e4](https://github.com/antvis/x6/commit/45337e4a62224aaffd60fc8b2670a071c5560796))
# @antv/x6-sites [1.3.0](https://github.com/antvis/X6/compare/@antv/x6-sites@1.2.2...@antv/x6-sites@1.3.0) (2023-01-01)
### Features
* add data processing dag example ([#3091](https://github.com/antvis/X6/issues/3091)) ([d3301d3](https://github.com/antvis/X6/commit/d3301d33d575269d9219ab1337a2ec1785d61494))
## @antv/x6-sites [1.2.2](https://github.com/antvis/X6/compare/@antv/x6-sites@1.2.1...@antv/x6-sites@1.2.2) (2022-12-24)
### Bug Fixes
* schedule edge when source and target is not ready ([#3090](https://github.com/antvis/X6/issues/3090)) ([019333d](https://github.com/antvis/X6/commit/019333d79d7f22c44c400f29d501497f4323af1a))
# @antv/x6-sites [1.2.0](https://github.com/antvis/X6/compare/@antv/x6-sites@1.1.2...@antv/x6-sites@1.2.0) (2022-12-16)

@ -1,7 +0,0 @@
Legal Disclaimer
Within this source code, the comments in Chinese shall be the original, governing version. Any comment in other languages are for reference only. In the event of any conflict between the Chinese language version comments and other language version comments, the Chinese language version shall prevail.
法律免责声明
关于代码注释部分,中文注释为官方版本,其它语言注释仅做参考。中文注释可能与其它语言注释存在不一致,当中文注释与其它语言注释存在不一致时,请以中文注释为准。

@ -13,29 +13,26 @@ redirect_from:
new Graph(options: Options)
```
| 选项 | 类型 | 必选 | 描述 | 默认值 |
| ------------------------------------------------------------------------------ | ------------------------------ | :--: | ------------------------------------------------------------------------------------------------- | ------------------------------------------------- |
| containers | HTMLElement | ✓ | 画布的容器。 | |
| width | number | | 画布宽度,默认使用容器宽度。 | - |
| height | number | | 画布高度,默认使用容器高度。 | - |
| scaling | { min?: number, max?: number } | | 画布的最小最大缩放级别。 | { min: 0.01, max: 16 } |
| [autoResize](/zh/docs/tutorial/basic/graph#画布大小) | boolean \| Element \| Document | | 是否监听容器大小改变,并自动更新画布大小。 | `false` |
| [panning](/zh/docs/api/graph/panning) | boolean \| `PanningManager.Options` | | 画布是否可以拖拽平移,默认禁用。 | `false` |
| [mousewheel](/zh/docs/api/graph/mousewheel) | boolean \| `MouseWheel.Options` | | 鼠标滚轮缩放,默认禁用| `false` |
| [grid](/zh/docs/api/graph/grid) | boolean \| number \| `GridManager.Options` | | 网格,默认使用 `10px` 的网格,但不绘制网格背景。 | `false` |
| [background](/zh/docs/api/graph/background) | false \| `BackgroundManager.Options` | | 背景,默认不绘制背景| `false` |
| [translating](/zh/docs/api/interacting/interaction#translating) | `Translating.Options` | | 限制节点移动。 | { restrict: false } |
| [embedding](/zh/docs/api/interacting/interaction#embedding) | boolean \| `Embedding.Options` | | 嵌套节点,默认禁用| `false` |
| [connecting](/zh/docs/api/interacting/interaction#connecting) | `Connecting.Options` | | 连线选项。 | { snap: false, ... } |
| [highlighting](/zh/docs/api/interacting/interaction#highlighting) | `Highlighting.Options` | | 高亮选项。 | {...} |
| [interacting](/zh/docs/api/interacting/interaction#interacting) | `Interacting.Options` | | 定制节点和边的交互行为。 | { edgeLabelMovable: false } |
| [magnetThreshold](/zh/docs/api/graph/view#magnetthreshold) | number \| 'onleave' | | 鼠标移动多少次后才触发连线,或者设置为 `'onleave'` 时表示鼠标移出元素时才触发连线。 | `0` |
| [moveThreshold](/zh/docs/api/graph/view#movethreshold) | number | | 触发 `'mousemove'` 事件之前,允许鼠标移动的次数。 | `0` |
| [clickThreshold](/zh/docs/api/graph/view#clickthreshold) | number | | 当鼠标移动次数超过指定的数字时,将不触发鼠标点击事件| `0` |
| [preventDefaultContextMenu](/zh/docs/api/graph/view#preventdefaultcontextmenu) | boolean | | 是否禁用浏览器默认右键菜单。 | `true` |
| [preventDefaultBlankAction](/zh/docs/api/graph/view#preventdefaultblankaction) | boolean | | 在画布空白位置响应鼠标事件时,是否禁用鼠标默认行为。 | `true` |
| [async](/zh/docs/api/graph/view#async) | boolean | | 是否异步渲染 | `true` |
| [virtual](/zh/docs/api/graph/view#virtual) | boolean | | 是否只渲染可视区域内容 | `false` |
| [onPortRendered](/zh/docs/api/graph/view#onportrendered) | (args: OnPortRenderedArgs) => void | | 当某个连接桩渲染完成时触发的回调。 | - |
| [onEdgeLabelRendered](/zh/docs/api/graph/view#onedgelabelrendered) | (args: OnEdgeLabelRenderedArgs) => void | | 当边的文本标签渲染完成时触发的回调。 | - |
| [createCellView](/zh/docs/api/graph/view#createcellview) | (this: Graph, cell: Cell) => CellView \| null \| undefined | | 是自定义元素的视图。 | - |
| 选项 | 类型 | 必选 | 默认值 | 描述 |
| ------------------------------------------------------------------------------ | ------------------------------ | :--: | ------------------------------------------------- | ------------------------------------------------------------------------------------------------- |
| [container](#container) | HTMLElement | ✓ | | 画布的容器。 |
| [width](#width) | number | | `undefined` | 画布宽度,默认使用容器宽度。 |
| [height](#height) | number | | `undefined` | 画布高度,默认使用容器高度。 |
| [autoResize](#autoresize) | boolean \| Element \| Document | | `false` | 是否监听容器大小改变,并自动更新画布大小。默认监听画布容器,也可以指定监听的元素,如 `Document` |
| [panning](/zh/docs/api/graph/panning) | object | | { enabled: false, eventTypes: ['leftMouseDown'],} | 画布是否可以拖动 |
| [grid](/zh/docs/api/graph/grid) | boolean \| number \| object | | `false` | 网格,默认使用 `10px` 的网格,但不绘制网格背景。 |
| [background](/zh/docs/api/graph/background) | false \| object | | `false` | 背景,默认不绘制背景 |
| [mousewheel](/zh/docs/api/graph/mousewheel) | boolean \| object | | `false` | 鼠标滚轮缩放,默认禁用。 |
| [translating](/zh/docs/api/graph/transform#translating) | object | | object | 平移节点 |
| [embedding](/zh/docs/api/graph/interaction#embedding) | boolean \| object | | `false` | 嵌套节点,默认禁用。 |
| [connecting](/zh/docs/api/graph/interaction#connecting) | object | | object | 连线选项 |
| [highlighting](/zh/docs/api/graph/interaction#highlighting) | object | | object | 高亮选项。 |
| [interacting](/zh/docs/api/graph/interaction#interacting) | object \| function | | `{ edgeLabelMovable: false }` | 定制节点和边的交互行为。 |
| [magnetThreshold](/zh/docs/api/graph/view#magnetThreshold) | number \| 'onleave' | | `0` | 鼠标移动多少次后才触发连线,或者设置为 `'onleave'` 时表示鼠标移出元素时才触发连线。 |
| [moveThreshold](/zh/docs/api/graph/view#moveThreshold) | number | | `0` | 触发 `'mousemove'` 事件之前,允许鼠标移动的次数。 |
| [clickThreshold](/zh/docs/api/graph/view#clickThreshold) | number | | `0` | 当鼠标移动次数超过指定的数字时,将不触发鼠标点击事件。 |
| [preventDefaultContextMenu](/zh/docs/api/graph/view#preventDefaultContextMenu) | boolean | | `true` | 是否禁用浏览器默认右键菜单 |
| [preventDefaultBlankAction](/zh/docs/api/graph/view#preventDefaultBlankAction) | boolean | | `true` | 在画布空白位置响应鼠标事件时,是否禁用鼠标默认行为。 |
| [guard](/zh/docs/api/graph/view#guard) | function | | `() => false` | 返回是否应该忽略某个鼠标事件,返回 `true` 时忽略指定的鼠标事件。 |
| [async](/zh/docs/api/graph/view#async) | boolean | | `true` | 是否异步渲染 |
| [virtual](/zh/docs/api/graph/view#virtual) | boolean | | `false` | 是否只渲染可视区域内容 |

@ -10,14 +10,10 @@ redirect_from:
### async
是否是异步渲染的画布。异步渲染不会阻塞 UI对需要添加大量节点和边时的性能提升非常明显。但需要注意的是一些同步操作可能会出现意外结果比如获取某个节点的视图、获取节点/边的包围盒等,因为这些同步操作触发时异步渲染可能并没有完成。
是否是异步渲染的画布。异步渲染不会阻塞 UI对需要添加大量节点和边时的性能提升非常明显。但需要注意的是一些同步操作可能会出现意外结果比如获取某个节点的视图、获取节点/边的包围盒等,因为这些同步操作触发时异步渲染可能并没有完成,此时只能通过监听 `render:done` 事件来确保所有变更都已经生效,然后在事件回调中进行这些操作
<!-- <iframe src="/demos/api/graph/async"></iframe> -->
### virtual
是否只渲染可视区域内的元素,默认为 `false`,如果设置为 `true`,首屏加载只会渲染当前可视区域内的元素,当拖动画布或者缩放画布时,会根据画布窗口大小自动加载剩余元素。在元素数量很大的场景,性能提升非常明显。
### magnetThreshold
鼠标移动多少次后才触发连线,或者设置为 'onleave' 时表示鼠标移出元素时才触发连线,默认为 `0`
@ -38,6 +34,14 @@ redirect_from:
在画布空白位置响应鼠标事件时,是否禁用鼠标默认行为,默认为 `true`
### guard
```sign
(e: Dom.EventObject, view?: CellView | null) => boolean
```
是否应该忽略某个鼠标事件,返回 `true` 时忽略指定的鼠标事件,否则不忽略。
### onPortRendered
```sign
@ -56,7 +60,9 @@ redirect_from:
) => void
```
当某个连接桩渲染完成时触发的回调,参数如下:
当某个连接桩渲染完成时触发的回调
<span class="tag-param">args 参数<span>
| 名称 | 类型 | 非空 | 描述 |
| ---------------- | ---------------- | :--: | ---------------------------------------- |
@ -69,6 +75,7 @@ redirect_from:
| contentContainer | Element | ✓ | 连接桩内容的容器元素。 |
| contentSelectors | Markup.Selectors | | 连接桩内容 Markup 渲染后的选择器键值对。 |
<span class="tag-example">使用<span>
例如,我们可以渲染一个 React 类型的连接桩。
@ -90,7 +97,7 @@ const graph = new Graph({
});
```
<!-- <iframe src="/demos/tutorial/advanced/react/react-port"></iframe> -->
<iframe src="/demos/tutorial/advanced/react/react-port"></iframe>
### onEdgeLabelRendered
@ -106,8 +113,9 @@ const graph = new Graph({
) => void
```
当边的文本标签渲染完成时触发的回调,参数如下:
当边的文本标签渲染完成时触发的回调
<span class="tag-param">args 参数<span>
| 名称 | 类型 | 非空 | 描述 |
| --------- | ---------------- | :--: | -------------------------------------- |
@ -116,6 +124,7 @@ const graph = new Graph({
| container | Element | ✓ | 文本标签容器。 |
| selectors | Markup.Selectors | ✓ | 文本标签 Markup 渲染后的选择器键值对。 |
<span class="tag-example">使用<span>
例如,我们可以在标签上渲染任何想要的元素。
@ -155,7 +164,7 @@ const graph = new Graph({
});
```
<!-- <iframe src="/demos/tutorial/advanced/react/react-label-base"></iframe> -->
<iframe src="/demos/tutorial/advanced/react/react-label-base"></iframe>
我们也可以在定义 Label 的 Markup 时添加 `<foreignObject>` 元素来支持 HTML 和 React 的渲染能力。
@ -176,21 +185,72 @@ const graph = new Graph({
});
```
<!-- <iframe src="/demos/tutorial/advanced/react/react-label-markup"></iframe> -->
<iframe src="/demos/tutorial/advanced/react/react-label-markup"></iframe>
### createCellView
### onToolItemCreated
```sign
(
this: Graph,
cell: Cell,
) => CellView | null | undefined
args: {
name: string
cell: Cell
view: CellView
tool: View
},
) => void
```
自定义元素的视图,可以返回一个 `CellView`,会替换默认的视图,如果返回 `null`,则不会渲染,如果返回 `undefined`,会按照默认方式渲染。
当工具项渲染完成时触发的回调。
<span class="tag-param">args 参数<span>
| 名称 | 类型 | 非空 | 描述 |
| ---- | -------- | :--: | ------------- |
| cell | Cell | ✓ | 节点/边实例。 |
| view | CellView | ✓ | 节点/边视图。 |
| name | string | ✓ | 工具项名称。 |
| tool | View | ✓ | 工具视图。 |
<span class="tag-example">使用<span>
例如,我们为 `vertices` 工具设置间隔填充效果。
```ts
const graph = new Graph({
container: this.container,
grid: true,
onToolItemCreated({ name, cell, tool }) {
if (name === "vertices" && cell === edge2) {
const options = (tool as any).options;
if (options && options.index % 2 === 1) {
tool.setAttrs({ fill: "red" });
}
}
},
});
```
<iframe src="/demos/api/registry/edge-tool/vertices"></iframe>
## 方法
### isAsync()
```sign
isAsync(): boolean
```
返回画布是否是异步渲染模式。异步渲染不会阻塞 UI对需要添加大量节点和边时的性能提升非常明显异步画布的使用细节请参考 [`async`](#async) 选项。
### isFrozen()
```sign
isFrozen(): boolean
```
返回[异步画布](#async)是否处于冻结状态。处于冻结状态的画布不会立即响应画布中节点和边的变更,直到调用 [`unfreeze(...)`](#unfreeze) 方法来解除冻结并重新渲染画布。
### findView(...)
```sign

@ -72,7 +72,7 @@ export interface Connecting {
### snap
`snap` 设置为 `true` 时连线的过程中距离节点或者连接桩 `50px` 时会触发自动吸附,可以通过配置 `radius` 属性自定义触发吸附的距离。当 `snap` 设置为 `false` 时不会触发自动吸附。默认值为 `false`
`snap` 设置为 `true` 时连线的过程中距离节点或者连接桩 `50px` 时会触发自动吸附,可以通过配置 `radius` 属性自定义触发吸附的距离。当 `snap` 设置为 `false` 时不会触发自动吸附。默认值为 `false`
```ts
const graph = new Graph({
@ -92,35 +92,35 @@ const graph = new Graph({
### allowBlank
是否允许连接到画布空白位置的点,默认为 `true`
是否允许连接到画布空白位置的点,默认为 `true`
### allowMulti
是否允许在相同的起始节点和终止之间创建多条边,默认为 `true` 。当设置为 `false` 时,在起始和终止节点之间只允许创建一条边,当设置为 `'withPort'` 时,在起始和终止节点的相同连接桩之间只允许创建一条边(即,起始和终止节点之间可以创建多条边,但必须要要链接在不同的连接桩上)。
是否允许在相同的起始节点和终止之间创建多条边,默认为 `true`。当设置为 `false` 时,在起始和终止节点之间只允许创建一条边,当设置为 `'withPort'` 时,在起始和终止节点的相同连接桩之间只允许创建一条边(即,起始和终止节点之间可以创建多条边,但必须要要链接在不同的连接桩上)。
### allowLoop
是否允许创建循环连线,即边的起始节点和终止节点为同一节点,默认为 `true`
是否允许创建循环连线,即边的起始节点和终止节点为同一节点,默认为 `true`
### allowNode
是否允许边链接到节点(非节点上的连接桩),默认为 `true`
是否允许边链接到节点(非节点上的连接桩),默认为 `true`
### allowEdge
是否允许边链接到另一个边,默认为 `true`
是否允许边链接到另一个边,默认为 `true`
### allowPort
是否允许边链接到连接桩,默认为 `true`
是否允许边链接到连接桩,默认为 `true`
### highlight
拖动边时,是否高亮显示所有可用的连接桩或节点,默认值为 `false`
拖动边时,是否高亮显示所有可用的连接桩或节点,默认值为 `false`
### anchor
当连接到节点时,通过 [ `anchor` ](/zh/docs/api/registry/node-anchor) 来指定被连接的节点的锚点,默认值为 `center`
当连接到节点时,通过 [`anchor`](/zh/docs/api/registry/node-anchor) 来指定被连接的节点的锚点,默认值为 `center`
#### sourceAnchor
@ -132,7 +132,7 @@ const graph = new Graph({
### edgeAnchor
当连接到边时,通过 [ `edgeAnchor` ](/zh/docs/api/registry/edge-anchor) 来指定被连接的边的锚点,默认值为 `ratio`
当连接到边时,通过 [`edgeAnchor`](/zh/docs/api/registry/edge-anchor) 来指定被连接的边的锚点,默认值为 `ratio`
### sourceEdgeAnchor
@ -144,7 +144,7 @@ const graph = new Graph({
### connectionPoint
指定[连接点](/zh/docs/api/registry/connector),默认值为 `boundary`
指定[连接点](/zh/docs/api/registry/connector),默认值为 `boundary`
### sourceConnectionPoint
@ -156,11 +156,11 @@ const graph = new Graph({
#### router
[路由](/zh/docs/api/registry/router)将边的路径点 `vertices` 做进一步转换处理,并在必要时添加额外的点,然后返回处理后的点,默认值为 `normal`
[路由](/zh/docs/api/registry/router)将边的路径点 `vertices` 做进一步转换处理,并在必要时添加额外的点,然后返回处理后的点,默认值为 `normal`
### connector
[连接器](/zh/docs/api/registry/connector)将起点、路由返回的点、终点加工为 <path> 元素的 d 属性,决定了边渲染到画布后的样式,默认值为 `normal`
[连接器](/zh/docs/api/registry/connector)将起点、路由返回的点、终点加工为 <path> 元素的 d 属性,决定了边渲染到画布后的样式,默认值为 `normal`
### createEdge
@ -168,7 +168,7 @@ const graph = new Graph({
### validateMagnet
点击 `magnet` 时 根据 `validateMagnet` 返回值来判断是否新增边,触发时机是 `magnet` 被按下,如果返回 `false` ,则没有任何反应,如果返回 `true` ,会在当前 `magnet` 创建一条新的边。
点击 `magnet` 时 根据 `validateMagnet` 返回值来判断是否新增边,触发时机是 `magnet` 被按下,如果返回 `false`,则没有任何反应,如果返回 `true`,会在当前 `magnet` 创建一条新的边。
```ts
validateMagnet({ e, magnet, view, cell }) {
@ -178,7 +178,7 @@ validateMagnet({ e, magnet, view, cell }) {
### validateConnection
在移动边的时候判断连接是否有效,如果返回 `false` ,当鼠标放开的时候,不会连接到当前元素,否则会连接到当前元素。
在移动边的时候判断连接是否有效,如果返回 `false`,当鼠标放开的时候,不会连接到当前元素,否则会连接到当前元素。
```ts
validateConnection({
@ -200,7 +200,7 @@ validateConnection({
### validateEdge
当停止拖动边的时候根据 `validateEdge` 返回值来判断边是否生效,如果返回 `false` , 该边会被清除。
当停止拖动边的时候根据 `validateEdge` 返回值来判断边是否生效,如果返回 `false`, 该边会被清除。
```ts
validateEdge({ edge, type, previous }) {
@ -240,19 +240,19 @@ export interface Embedding {
### enabled
是否允许节点之间嵌套,默认值为 `false`
是否允许节点之间嵌套,默认值为 `false`
### findParent
在节点被移动时通过 `findParent` 指定的方法返回父节点。默认值为 `bbox`
在节点被移动时通过 `findParent` 指定的方法返回父节点。默认值为 `bbox`
### frontOnly
如果 `frontOnly``true` ,则只能嵌入显示在最前面的节点,默认值为 `true`
如果 `frontOnly``true`,则只能嵌入显示在最前面的节点,默认值为 `true`
### validate
`validate` 为判断节点能否被嵌入父节点的函数,默认返回 `true`
`validate` 为判断节点能否被嵌入父节点的函数,默认返回 `true`
## interacting
@ -283,17 +283,17 @@ export type Interacting =
| ((this: Graph, cellView: CellView) => InteractionMap | boolean);
```
* `boolean` 节点或边是否可交互
* `InteractionMap` 节点或边的交互细节,支持以下属性:
+ `'nodeMovable'` 节点是否可以被移动。
+ `'magnetConnectable'` 当在具有 `'magnet'` 属性的元素上按下鼠标开始拖动时,是否触发连线交互。
+ `'edgeMovable'` 边是否可以被移动。
+ `'edgeLabelMovable'` 边的标签是否可以被移动。
+ `'arrowheadMovable'` 边的起始/终止箭头是否可以被移动。
+ `'vertexMovable'` 边的路径点是否可以被移动。
+ `'vertexAddable'` 是否可以添加边的路径点。
+ `'vertexDeletable'` 边的路径点是否可以被删除。
* `(this: Graph, cellView: CellView) => InteractionMap | boolean`
- `boolean` 节点或边是否可交互
- `InteractionMap` 节点或边的交互细节,支持以下属性:
- `'nodeMovable'` 节点是否可以被移动。
- `'magnetConnectable'` 当在具有 `'magnet'` 属性的元素上按下鼠标开始拖动时,是否触发连线交互。
- `'edgeMovable'` 边是否可以被移动。
- `'edgeLabelMovable'` 边的标签是否可以被移动。
- `'arrowheadMovable'` 边的起始/终止箭头是否可以被移动。
- `'vertexMovable'` 边的路径点是否可以被移动。
- `'vertexAddable'` 是否可以添加边的路径点。
- `'vertexDeletable'` 边的路径点是否可以被删除。
- `(this: Graph, cellView: CellView) => InteractionMap | boolean`
```ts
const graph = new Graph({
@ -334,41 +334,10 @@ new Graph({
支持的 `highlighting` 配置项有:
* `'default'` 默认高亮选项,当以下几种高亮配置缺省时被使用。
* `'embedding'` 拖动节点进行嵌入操作过程中,节点可以被嵌入时被使用。
* `'nodeAvailable'` 连线过程中,节点可以被链接时被使用。
* `'magnetAvailable'` 连线过程中,连接桩可以被链接时被使用。
* `'magnetAdsorbed'` 连线过程中,自动吸附到连接桩时被使用。
- `'default'` 默认高亮选项,当以下几种高亮配置缺省时被使用。
- `'embedding'` 拖动节点进行嵌入操作过程中,节点可以被嵌入时被使用。
- `'nodeAvailable'` 连线过程中,节点可以被链接时被使用。
- `'magnetAvailable'` 连线过程中,连接桩可以被链接时被使用。
- `'magnetAdsorbed'` 连线过程中,自动吸附到连接桩时被使用。
上面 `magnetAvailable.name` 其实是高亮器的名称X6 内置了 `stroke``className` 两种高亮器,详细信息参考 [Highlighter](/zh/docs/api/registry/highlighter)
## translating
可以在全局配置 `translating` 来限制节点的移动范围。
```ts
const graph = new Graph({
translating: {
restrict: true,
},
})
```
### restrict
节点的可移动范围。支持以下两种方式:
* `boolean` 如果设置为 `true`, 节点不能移动超出画布区域
* `Rectangle.RectangleLike | (arg: CellView) => Rectangle.RectangleLike` 指定一个节点的移动范围
```ts
const graph = new Graph({
translating: {
restrict: {
x: 0,
y: 0,
width: 100,
height: 100,
}
}
})

@ -241,9 +241,8 @@ getBBox(): Rectangle
返回边的包围盒。
:::warning{title=注意:}
[[warning]]
| 需要注意的是,该方法通过边的端点和路径点计算包围盒,并不是渲染到画布后的包围盒,涉及的计算只是一些算数运算。
:::
#### getPolyline()

@ -499,7 +499,7 @@ function parseStringLabel(label: string): Label {
```ts
Edge.config({
defaultLabel: {
defaultlabel: {
markup: [
{
tagName: "rect",

@ -716,7 +716,7 @@ toJSON(options?: ToJSONOptions): object
| 名称 | 类型 | 必选 | 默认值 | 描述 |
| ------------ | ---- | :--: | ------- | --------------------------------------------------------------------------------------------------------- |
| options.deep | diff | | `false` | 是否导出节点和边的差异数据(与节点和边的[默认配置](/zh/docs/api/model/cell#选项默认值)不同的部分)。 |
| options.deep | diff | | `false` | 是否导出节点和边的差异数据(与节点和边的[默认配置](/zh/docs/tutorial/basic/cell#选项默认值)不同的部分)。 |
### parseJSON(...)

@ -247,9 +247,8 @@ getBBox(options: { deep?: boolean }): Rectangle
获取节点的包围盒。
:::warning{title=注意:}
[[warning]]
| 需要注意的是,该方法通过节点的大小和位置计算包围盒,并不是渲染到画布后的包围盒,涉及的计算只是一些算数运算。
:::
<span class="tag-param">参数<span>

@ -78,9 +78,8 @@ redirect_from:
- 当其值在 `[0, 1]` 之间或为百分比(如 `75%`)时,表示元素的宽度是参照宽度百分之多少。例如 `refWidth: 0.75` 表示元素的宽度是参照宽度的 `75%`
- 当其值 `<0``>1` 时,表示元素的宽度在参照宽度的基础上减少或增加多少。例如 `refWidth: 20` 表示元素比相对元素宽 `20px`
:::warning{title=注意:}
[[warning]]
| 需要注意的是,该属性只适用于那些支持宽度 `width` 和高度 `height` 的元素,如 `<rect>` 元素。
:::
### refWidth2
@ -102,9 +101,8 @@ redirect_from:
- 当其值在 `[0, 1]` 之间或为百分比(如 `75%`)时,表示元素的高度是参照高度百分之多少。例如 `refHeight: 0.75` 表示元素的高度是参照高度的 `75%`
- 当其值 `<0``>1` 时,表示元素的高度在参照高度的基础上减少或增加多少。例如 `refHeight: 20` 表示元素比相对元素高 `20px`
:::warning{title=注意:}
[[warning]]
| 需要注意的是,该属性只适用于那些支持宽度 `width` 和高度 `height` 的元素,如 `<rect>` 元素。
:::
### refHeight2
@ -126,9 +124,8 @@ redirect_from:
- 当其值在 `[0, 1]` 之间或为百分比(如 `75%`)时,表示元素的 `cx` 是参照宽度百分之多少。例如 `refCx: 0.75` 表示元素中心 `x` 坐标位于参照宽度的 `75%` 处。
- 当其值 `<0``>1` 时,表示元素的 `cx` 是在参照宽度的基础上减少或增加多少。例如 `refCx: 20` 表示元素中心 `x` 坐标位于参照宽度加 `20px` 处。
:::warning{title=注意:}
[[warning]]
| 需要注意的是,该属性只适用于那些支持 `cx``cy` 属性的元素,如 `<ellipse>` 元素。
:::
### refCy
@ -137,9 +134,8 @@ redirect_from:
- 当其值在 `[0, 1]` 之间或为百分比(如 `75%`)时,表示元素的 `cy` 是参照高度百分之多少。例如 `refCy: 0.75` 表示元素中心 `y` 坐标位于参照高度的 `75%` 处。
- 当其值 `<0``>1` 时,表示元素的 `cy` 是在参照宽度的基础上减少或增加多少。例如 `refCy: 20` 表示元素中心 `y` 坐标位于参照高度加 `20px` 处。
:::warning{title=注意:}
[[warning]]
| 需要注意的是,该属性只适用于那些支持 `cx``cy` 属性的元素,如 `<ellipse>` 元素。
:::
### refRx
@ -148,9 +144,8 @@ redirect_from:
- 当其值在 `[0, 1]` 之间或为百分比(如 `75%`)时,表示元素的 `rx` 是参照宽度百分之多少。例如 `refRx: 0.75` 表示元素的 `rx` 是参照宽度的 `75%`
- 当其值 `<0``>1` 时,表示元素的 `rx` 是在参照宽度的基础上减少或增加多少。例如 `refRx: 20` 表示元素的 `rx` 是参照宽度加 `20px`
:::warning{title=注意:}
[[warning]]
| 需要注意的是,该属性只适用于那些支持 `rx``ry` 属性的元素,如 `<rect>` 元素。
:::
### refRy
@ -159,9 +154,8 @@ redirect_from:
- 当其值在 `[0, 1]` 之间或为百分比(如 `75%`)时,表示元素的 `ry` 是参照高度百分之多少。例如 `refRy: 0.75` 表示元素的 `ry` 是参照高度的 `75%`
- 当其值 `<0``>1` 时,表示元素的 `ry` 是在参照宽度的基础上减少或增加多少。例如 `refRy: 20` 表示元素的 `ry` 是参照高度加 `20px`
:::warning{title=注意:}
[[warning]]
| 需要注意的是,该属性只适用于那些支持 `rx``ry` 属性的元素,如 `<rect>` 元素。
:::
### refRCircumscribed
@ -170,9 +164,8 @@ redirect_from:
- 当其值在 `[0, 1]` 之间或为百分比(如 `75%`)时,表示 `r` 是参照长度百分之多少。例如 `refRCircumscribed: 0.75` 表示 `r` 是参照长度的 `75%`
- 当其值 `<0``>1` 时,表示 `r` 是在参照长度的基础上减少或增加多少。例如 `refRCircumscribed: 20` 表示 `r` 是参照长度加 `20px`
:::warning{title=注意:}
[[warning]]
| 需要注意的是,该属性只适用于那些支持 `r` 属性的元素,如 `<rect>` 元素。
:::
### refRInscribed
@ -183,9 +176,8 @@ _简称_**`refR`**
- 当其值在 `[0, 1]` 之间或为百分比(如 `75%`)时,表示 `r` 是参照长度百分之多少。例如 `refRInscribed: 0.75` 表示 `r` 是参照长度的 `75%`
- 当其值 `<0``>1` 时,表示 `r` 是在参照长度的基础上减少或增加多少。例如 `refRInscribed: 20` 表示 `r` 是参照长度加 `20px`
:::warning{title=注意:}
[[warning]]
| 需要注意的是,该属性只适用于那些支持 `r` 属性的元素,如 `<rect>` 元素。
:::
### refDKeepOffset
@ -569,9 +561,8 @@ edge.attr("connection/sourceMarker", {
适用于所有 `<path>` 元素,在路径的终点添加一个 SVG 元素(如终点箭头),并自动旋转该元素,使其与根据路径方向保持一致。了解更多详情请参考[这篇教程](/zh/docs/tutorial/intermediate/marker)。
:::warning{title=注意:}
[[warning]]
| 需要注意的是,该元素初始时就被旋转了 `180` 度,在此基础上再自动调整旋转角度,并与路径的方向保持一致。例如,对于一个水平的直线,我们为其起点指定了一个向左的箭头,我们也可以为其重点指定相同的箭头,这个箭头会自动指向右侧(自动旋转了 `180` 度)。
:::
### vertexMarker

@ -221,11 +221,11 @@ graph.addEdge({
支持的参数如下表:
| 参数名 | 参数类型 | 是否必选 | 默认值 | 参数说明 |
| --------- | ---------------------------------------- | -------- | --------- | ------------------------------------------------------------ |
| offset | number \|'center' | 否 | `32` | 路由的第一个点和最后一个点与节点之间的距离。当取值为 `'center'` 时,节点距离的中心作为路由点坐标。 |
| min | number | 否 | `16` | 路由的第一个点和最后一个点与节点之间的最小距离。 |
| direction | `'T'`\|`'B'`\|`'L'`\|`'R'`\|`'H'`\|`'V'` | 否 | undefined | 路由方向,缺省时将自动选择最优方向。 |
| 参数名 | 参数类型 | 是否必选 | 默认值 | 参数说明 |
| --------- | ------------------ | :------: | ------ | -------------------------------------------------------------------------------------------------- | --- | ---- | --- | --------- | ------------------------------------ |
| offset | number \| 'center' | 否 | `32` | 路由的第一个点和最后一个点与节点之间的距离。当取值为 `'center'` 时,节点距离的中心作为路由点坐标。 |
| min | number | 否 | `16` | 路由的第一个点和最后一个点与节点之间的最小距离。 |
| direction | `'T' | 'B' | 'L' | 'R' | 'H' | 'V'` | 否 | undefined | 路由方向,缺省时将自动选择最优方向。 |
例如:

@ -62,9 +62,8 @@ graph.addNode({
上面这些属性默认相对于节点的大小进行计算,另外我们可以通过 `ref` 属性来提供一个子元素选择器,这时所有的计算都相对于 `ref` 指代的元素,从而实现相对于子元素的大小和位置。
:::warning{title=注意:}
[[warning]]
| 需要注意的是,设置 `ref` 后,所有计算都依赖子元素在浏览器中的 bbox 测量,所以性能会比相对于节点的方式要慢。
:::
```ts
graph.addNode({

@ -11,9 +11,9 @@ X6 是基于 HTML 和 SVG 的图编辑引擎,提供低成本的定制能力和
如果你还没有使用过 X6 建议通过 [快速上手](/zh/docs/tutorial/getting-started) 抢先体验 X6 的魅力。
<p align="left">
<a href="https://github.com/antvis/X6/actions/workflows/ci.yml"><img alt="build" src="https://img.shields.io/github/actions/workflow/status/antvis/x6/ci.yml?branch=master&logo=github&style=flat-square"></a>
<!-- <a href="https://app.codecov.io/gh/antvis/X6"><img alt="coverage" src="https://img.shields.io/codecov/c/gh/antvis/x6?logo=codecov&style=flat-square&token=15CO54WYUV"></a>
<a href="https://lgtm.com/projects/g/antvis/x6/context:javascript"><img alt="Language grade: JavaScript" src="https://img.shields.io/lgtm/grade/javascript/g/antvis/x6.svg?logo=lgtm&style=flat-square"></a> -->
<a href="https://github.com/antvis/X6/actions/workflows/ci.yml"><img alt="build" src="https://img.shields.io/github/workflow/status/antvis/x6/%F0%9F%91%B7%E3%80%80CI/master?logo=github&style=flat-square"></a>
<a href="https://app.codecov.io/gh/antvis/X6"><img alt="coverage" src="https://img.shields.io/codecov/c/gh/antvis/x6?logo=codecov&style=flat-square&token=15CO54WYUV"></a>
<a href="https://lgtm.com/projects/g/antvis/x6/context:javascript"><img alt="Language grade: JavaScript" src="https://img.shields.io/lgtm/grade/javascript/g/antvis/x6.svg?logo=lgtm&style=flat-square"></a>
<a href="https://www.npmjs.com/package/@antv/x6"><img alt="NPM Package" src="https://img.shields.io/npm/v/@antv/x6.svg?style=flat-square"></a>
<a href="https://www.npmjs.com/package/@antv/x6"><img alt="NPM Downloads" src="https://img.shields.io/npm/dm/@antv/x6?logo=npm&style=flat-square"></a>
</p>

Some files were not shown because too many files have changed in this diff Show More