feat: new version of basic styles for light version; feat: shortcuts-call behavior for calling a Graph function by shortcuts; docs: update the docs for new feature; docs: demos for more interactions

This commit is contained in:
Yanyan-Wang 2020-11-12 19:42:59 +08:00 committed by Yanyan Wang
parent 4111b2b52e
commit aa27cc4e11
90 changed files with 1147 additions and 624 deletions

View File

@ -1,5 +1,9 @@
# ChangeLog
#### 3.8.4
- feat: new version of basic styles for light version;
- feat: shortcuts-call behavior for calling a Graph function by shortcuts;
#### 3.8.3
- feat: drag the viewport of the minimap out of the the view;
- fix: extend modelRect with description problem, closes: #2235;

View File

@ -88,7 +88,7 @@ We provide the function for transformantion:
```javascript
import { transform } from '@antv/matrix-util';
// transform a 3*3 matrix
trasform(m, [
transform(m, [
['t', x, y], // translate with vector (x, y)
['r', Math.PI], // rotate
['s', 2, 2], // scale at x-axis and y-axis
@ -122,7 +122,7 @@ G6.registerNode('example', {
if (!matrix) matrix = mat3.create();
// transform a 3*3 matrix
const newMatrix = trasform(matrix, [
const newMatrix = transform(matrix, [
['t', 100, 50], // translate
['r', Math.PI / 4], // rotate
['s', 2, 0.5], // scale

View File

@ -88,7 +88,7 @@ rect.transform([
```javascript
import { transform } from '@antv/matrix-util';
// 3*3 矩阵变换,用于二维渲染
trasform(m, [
transform(m, [
['t', 100, 50], // translate (100, 50)
['r', Math.PI], // rotate Math.PI
['s', 2, 2], // scale 2 times at x-axis and y-axis
@ -123,7 +123,7 @@ G6.registerNode('example', {
if (!matrix) matrix = mat3.create();
// 3*3 矩阵变换,用于二维渲染
const newMatrix = trasform(matrix, [
const newMatrix = transform(matrix, [
['t', 100, 50], // translate
['r', Math.PI / 4], // rotate
['s', 2, 0.5], // scale

View File

@ -707,3 +707,46 @@ const graph = new G6.Graph({
},
});
```
### shortcuts-call
- Description: allow the end-user to call a function of Graph with shortcuts keys. e.g. press down 'control' and '1' on keyboard to make the graph fit the canvas. Attention: make sure the focus is on the canvas when the end-user is pressing keys to call the function;
- Configurations:
- `type: 'shortcuts-call'`;
- `trigger`: the subject key to trigger the behavior, options: `'shift'`, `'alt'`, `'ctrl'`, `'control'`;
- `combinedKey`: the vice key for combination with `trigger` to trigger the behavior. When the `trigger` is pressed down, press the `combinedKey` will call the graph function with name `functionName`. If `combinedKey` is not specified or assigned with `undefined`, pressing the `trigger` down will call the function;
- `functionName`: the name of the Graph function to be called. If the name is wrong or it is not a function of the Graph, the keydown events will not be triggered.
- `functionParams`: the parameters or the called function. Make sure the parameters are correct for the function to be called according to corresponding docs, errors might occur otherwise.
**Using Default Configuration**
```javascript
const graph = new G6.Graph({
modes: {
default: ['shortcuts-call'],
},
});
```
**Using Customized Configuration**
```javascript
const graph = new G6.Graph({
modes: {
default: [
// Press 'alt' and 'm' to call graph.moveTo(10, 10). Be sure that the fucos is on the canvas when press the keys
{
type: 'shortcuts-call',
// subject key
trigger: 'alt',
// vice key
combinedKey: 'm',
// move the graph to 10,10
functionName: 'moveTo',
functionParams: [10, 10]
},
],
},
});
```

View File

@ -712,3 +712,46 @@ const graph = new G6.Graph({
},
});
```
### shortcuts-call
- 含义:允许终端用户使用键盘组合键调用 Graph 的函数,例如按下键盘上的 control 与 1对图进行适应画布。注意终端用户使用该功能时焦点必须在画布上才能够正确触发
- 配置项:
- `type'shortcuts-call'`
- `trigger`:触发该交互的主键,可选 `'shift'``'alt'``'ctrl'``'control'`。默认为 `'control'`。设置时需要注意可能与其他正在别使用的 Behavior 的 trigger 产生冲突;
- `combinedKey`:触发该交互的副按键,在按住主键 `trigger` 后,按下该副按键,将会调用 `functionName` 指定的函数。若不设置或设置为 undefined 则代表只根据 `trigger` 触发;
- `functionName`: 被调用的 Graph 的一个函数名,若传入一个错误的函数名,将会不产生任何效果;
- `functionParams`: 被调用的函数的参数,请根据各函数的文档传入正确的参数,错误的参数可能导致报错。
**使用默认配置**
```javascript
const graph = new G6.Graph({
modes: {
default: ['shortcuts-call'],
},
});
```
**使用自定义参数**
```javascript
const graph = new G6.Graph({
modes: {
default: [
// 当按住 'alt' 键,并按下 'm' 键,将调用 graph.moveTo(10, 10)
{
type: 'shortcuts-call',
// 主健
trigger: 'alt',
// 副键
combinedKey: 'm',
// 将图内容的左上角移动到 10,10
functionName: 'moveTo',
functionParams: [10, 10]
},
],
},
});
```

View File

@ -0,0 +1,16 @@
{
"title": {
"zh": "中文分类",
"en": "Category"
},
"demos": [
{
"filename": "shortestPath.js",
"title": {
"zh": "最短路径",
"en": "Shortest Path"
},
"screenshot": "https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*YtBHR5akE2gAAAAAAAAAAABkARQnAQ"
}
]
}

View File

@ -0,0 +1,80 @@
import G6 from '@antv/g6';
const tipDiv = document.createElement('div');
tipDiv.innerHTML = `Press 'shift' and click two nodes to select begin and end nodes. 按住 'shift' 并点选两个节点作为起点和终点。`;
document.getElementById('container').appendChild(tipDiv);
const button = document.createElement('button');
button.innerHTML = `查看最短路径`;
document.getElementById('container').appendChild(button);
const width = document.getElementById('container').scrollWidth;
const height = (document.getElementById('container').scrollHeight || 500) - 40;
const graph = new G6.Graph({
container: 'container',
width,
height,
linkCenter: true,
modes: {
default: ['click-select', 'drag-canvas', 'drag-node', 'zoom-canvas'],
},
fitView: true,
});
fetch('https://gw.alipayobjects.com/os/bmw-prod/b0ca4b15-bd0c-43ec-ae41-c810374a1d55.json')
.then((res) => res.json())
.then((data) => {
const clearStates = () => {
graph.getNodes().forEach(node => {
graph.clearItemStates(node);
});
graph.getEdges().forEach(edge => {
graph.clearItemStates(edge);
});
}
graph.on('canvas:click', e => {
clearStates();
});
graph.data(data);
graph.render();
button.addEventListener('click', e => {
const selectedNodes = graph.findAllByState('node', 'selected');
if (selectedNodes.length !== 2) {
alert('Please select TWO nodes!\n\r请选择有且两个节点');
return;
}
clearStates();
const { findShortestPath } = G6.Algorithm;
const { path } = findShortestPath(graph, selectedNodes[0].getID(), selectedNodes[1].getID());
const pathNodeMap = {};
path.forEach(id => {
const pathNode = graph.findById(id);
pathNode.toFront();
graph.setItemState(pathNode, 'highlight', true);
pathNodeMap[id] = true;
});
graph.getEdges().forEach(edge => {
const edgeModel = edge.getModel();
const source = edgeModel.source;
const target = edgeModel.target;
const sourceInPathIdx = path.indexOf(source);
const targetInPathIdx = path.indexOf(target);
if (sourceInPathIdx === -1 || targetInPathIdx === -1) return;
if (Math.abs(sourceInPathIdx - targetInPathIdx) === 1) {
graph.setItemState(edge, 'highlight', true);
} else {
graph.setItemState(edge, 'inactive', true);
}
});
graph.getNodes().forEach(node => {
if (!pathNodeMap[node.getID()]) {
graph.setItemState(node, 'inactive', true);
}
});
});
});

View File

@ -0,0 +1,10 @@
---
title: Shortest Path
order: 1
---
Graph algorithms provide one of the most effective methods for analyzing relational data. They describe how to process graphs to discover some qualitative or quantitative measures. Graph algorithms are based on graph theory and use the relationship between them to structure and change complex systems. We can use these algorithms to discover hidden information, verify business assumptions, and change behavior to make predictions. This demo shows how to use `findShortestPath` for finding the shortest path between two selected end nodes, and then highlight the path.
## Usage
Fore more information, please refer to the API docs [findShortestPath](/en/docs/api/Algorithm/#findshortestpathgraph-start-end-directed-weightpropertyname)。

View File

@ -0,0 +1,10 @@
---
title: 最短路径
order: 1
---
图算法提供了一种最有效的分析关联数据的方法,它们描述了如何处理图以发现一些定性或者定量的结论。图算法基于图论,利用节点之间的关系来推断复杂系统的结构和变化。我们可以使用这些算法来发现隐藏的信息,验证业务假设,并对行为进行预测。该 demo 以 `findShortestPath` 为例查找两点之间的最短路径,并高亮展示。
## 使用指南
更多信息请参见 API 文档 [findShortestPath](/zh/docs/api/Algorithm/#findshortestpathgraph-start-end-directed-weightpropertyname)。

View File

@ -126,7 +126,7 @@ const graph = new G6.Graph({
},
},
modes: {
default: ['drag-combo', 'drag-node', 'drag-canvas'],
default: ['drag-combo', 'drag-node', 'drag-canvas', 'click-select'],
},
});
graph.data(data);
@ -159,3 +159,14 @@ graph.on('combo:dragenter', (e) => {
graph.on('combo:dragleave', (e) => {
graph.setItemState(e.item, 'dragenter', false);
});
graph.on('combo:mouseenter', (evt) => {
const { item } = evt;
graph.setItemState(item, 'active', true);
});
graph.on('combo:mouseleave', (evt) => {
const { item } = evt;
graph.setItemState(item, 'active', false);
});

View File

@ -124,7 +124,7 @@ const graph = new G6.Graph({
},
},
modes: {
default: ['drag-combo', 'drag-node', 'drag-canvas'],
default: ['drag-combo', 'drag-node', 'drag-canvas', 'click-select'],
},
});
graph.data(data);
@ -157,3 +157,13 @@ graph.on('combo:dragenter', (e) => {
graph.on('combo:dragleave', (e) => {
graph.setItemState(e.item, 'dragenter', false);
});
graph.on('combo:mouseenter', (evt) => {
const { item } = evt;
graph.setItemState(item, 'active', true);
});
graph.on('combo:mouseleave', (evt) => {
const { item } = evt;
graph.setItemState(item, 'active', false);
});

View File

@ -49,7 +49,7 @@ const graph = new G6.Graph({
},
},
modes: {
default: ['drag-canvas', 'drag-node', 'drag-combo', 'collapse-expand-combo'],
default: ['drag-canvas', 'drag-node', 'drag-combo', 'collapse-expand-combo', 'click-select'],
},
});
@ -72,3 +72,13 @@ graph.on('combo:dragenter', (e) => {
graph.on('combo:dragleave', (e) => {
graph.setItemState(e.item, 'dragenter', false);
});
graph.on('combo:mouseenter', (evt) => {
const { item } = evt;
graph.setItemState(item, 'active', true);
});
graph.on('combo:mouseleave', (evt) => {
const { item } = evt;
graph.setItemState(item, 'active', false);
});

View File

@ -51,7 +51,7 @@ const graph = new G6.Graph({
},
},
modes: {
default: ['drag-canvas', 'drag-node', 'drag-combo', 'collapse-expand-combo'],
default: ['drag-canvas', 'drag-node', 'drag-combo', 'collapse-expand-combo', 'click-select'],
},
});
@ -75,3 +75,13 @@ graph.on('combo:dragenter', (e) => {
graph.on('combo:dragleave', (e) => {
graph.setItemState(e.item, 'dragenter', false);
});
graph.on('combo:mouseenter', (evt) => {
const { item } = evt;
graph.setItemState(item, 'active', true);
});
graph.on('combo:mouseleave', (evt) => {
const { item } = evt;
graph.setItemState(item, 'active', false);
});

View File

@ -0,0 +1,32 @@
import G6 from '@antv/g6';
const graphDiv = document.getElementById('container');
const tipDiv = document.createElement('div');
tipDiv.innerHTML =
`Press both the keys 'control' and '1' to call graph.fitView. The keys and the called function can be configured.【ATTENTION】: make sure the focus is on the canvas when you pressing keys
<br /> 按住 'control' 并按下 '1' 将会调用 graph.fitView组合按键及被调用的函数及其参数均可被配置注意使用组合件调用函数时请保证当前焦点在画布上`;
graphDiv.appendChild(tipDiv);
const width = document.getElementById('container').scrollWidth;
const height = (document.getElementById('container').scrollHeight || 500) - 100;
const graph = new G6.Graph({
container: 'container',
width,
height,
fitCenter: true,
modes: {
default: [{
type: 'shortcuts-call',
functionName: 'moveTo',
functionParams: [0, 0]
}]
}
});
fetch('https://gw.alipayobjects.com/os/bmw-prod/b0ca4b15-bd0c-43ec-ae41-c810374a1d55.json')
.then((res) => res.json())
.then((data) => {
graph.data(data);
graph.render();
graph.zoom(2);
});

View File

@ -0,0 +1,13 @@
{
"title": {
"zh": "中文分类",
"en": "Category"
},
"demos": [
{
"filename": "index.js",
"title": "使用快捷键适配画布",
"screenshot": "https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*F0RGQ67xbGYAAAAAAAAAAAAAARQnAQ"
}
]
}

View File

@ -0,0 +1,12 @@
---
title: Fit View with Shortcuts
order: 15
---
Allow the end-user to call a function of Graph with shortcuts keys.
允许终端用户使用键盘组合键调用 Graph 的函数。
## Usage
E.g. press down 'control' and '1' on keyboard to make the graph fit the canvas. Attention: make sure the focus is on the canvas when the end-user is pressing keys to call the function. For more information, please refer to [shortcuts-call](/en/docs/manual/middle/states/defaultBehavior/shortcuts-call).

View File

@ -0,0 +1,10 @@
---
title: 快捷键适应画布
order: 15
---
允许终端用户使用键盘组合键调用 Graph 的函数。
## 如何使用
例如按下键盘上的 control 与 1对图进行适应画布。注意终端用户使用该功能时焦点必须在画布上才能够正确触发。详细内容参考文档 [shortcuts-call](/zh/docs/manual/middle/states/defaultBehavior/shortcuts-call)。

View File

@ -51,44 +51,40 @@ const graph = new G6.Graph({
},
defaultNode: {
size: [10, 10],
style: {
lineWidth: 2,
fill: '#DEE9FF',
stroke: '#5B8FF9',
},
/* style for the keyShape */
// style: {
// lineWidth: 2,
// fill: '#DEE9FF',
// stroke: '#5B8FF9',
// },
},
defaultEdge: {
size: 1,
/* style for the keyShape */
style: {
stroke: '#e2e2e2',
stroke: '#aaa',
lineAppendWidth: 2,
opacity: 0.3
},
},
nodeStateStyles: {
active: {
opacity: 1,
},
inactive: {
opacity: 0.2,
},
},
edgeStateStyles: {
active: {
stroke: '#999',
},
},
/* styles for different states, there are built-in styles for states: active, inactive, selected, highlight, disable */
// nodeStateStyles: {
// active: {
// opacity: 1,
// },
// inactive: {
// opacity: 0.2,
// },
// },
// edgeStateStyles: {
// active: {
// stroke: '#999',
// },
// },
});
fetch('https://gw.alipayobjects.com/os/antvdemo/assets/data/xiaomi.json')
.then((res) => res.json())
.then((data) => {
graph.data({
nodes: data.nodes,
edges: data.edges.map(function (edge, i) {
edge.id = 'edge' + i;
return Object.assign({}, edge);
}),
});
graph.data(data);
graph.render();
});

View File

@ -1,60 +0,0 @@
import G6 from '@antv/g6';
const data = {
nodes: [
{ id: 'node1', x: 150, y: 250 },
{ id: 'node2', x: 350, y: 250 },
],
edges: [{
source: 'node1', target: 'node2'
}]
};
const descriptionDiv = document.createElement('div');
descriptionDiv.innerHTML =
'Draw on the canvas to create a lasso to select items.';
const graphDiv = document.getElementById('container');
graphDiv.appendChild(descriptionDiv);
const width = document.getElementById('container').scrollWidth;
const height = (document.getElementById('container').scrollHeight || 500) - 20;
const graph = new G6.Graph({
container: 'container',
width,
height,
fitCenter: true,
modes: {
default: [{
type: 'lasso-select',
delegateStyle: {
fill: '#f00',
fillOpacity: 0.05,
stroke: '#f00',
lineWidth: 1
},
onSelect: (nodes, edges) => {
console.log('onSelect', nodes, edges)
},
selectedState: 'customStateName',
trigger: 'drag'
}, 'drag-node'],
},
nodeStateStyles: {
customStateName: {
stroke: '#f00',
lineWidth: 3
}
},
edgeStateStyles: {
customStateName: {
stroke: '#f00',
lineWidth: 3
}
}
});
graph.data(data);
graph.render();
graph.on('nodeselectchange', e => {
console.log(e.selectedItems, e.select);
})

View File

@ -1,47 +0,0 @@
import G6 from '@antv/g6';
const data = {
nodes: [
{ id: 'node1', x: 150, y: 250 },
{ id: 'node2', x: 350, y: 250 },
],
edges: [{
source: 'node1', target: 'node2'
}]
};
const descriptionDiv = document.createElement('div');
descriptionDiv.innerHTML =
'Press down the \'shift\' on keyboard and draw on the canvas.';
const graphDiv = document.getElementById('container');
graphDiv.appendChild(descriptionDiv);
const width = document.getElementById('container').scrollWidth;
const height = (document.getElementById('container').scrollHeight || 500) - 20;
const graph = new G6.Graph({
container: 'container',
width,
height,
fitCenter: true,
modes: {
default: ['lasso-select', 'drag-node'],
},
nodeStateStyles: {
selected: {
stroke: '#f00',
lineWidth: 3
}
},
edgeStateStyles: {
selected: {
lineWidth: 3,
stroke: '#f00'
}
}
});
graph.data(data);
graph.render();
graph.on('nodeselectchange', e => {
console.log(e.selectedItems, e.select);
})

View File

@ -1,18 +0,0 @@
{
"title": {
"zh": "中文分类",
"en": "Category"
},
"demos": [
{
"filename": "default.js",
"title": "默认配置",
"screenshot": "https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*8WwrRplTPG8AAAAAAAAAAAAAARQnAQ"
},
{
"filename": "config.js",
"title": "配置样式、trigger 等",
"screenshot": "https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*8WwrRplTPG8AAAAAAAAAAAAAARQnAQ"
}
]
}

View File

@ -1,10 +0,0 @@
---
title: Lasso Select
order: 14
---
Buit-in behavior `'lasso-select'` is a new feature of V3.6.2, which allows the users select items by drawing a irregular polygon as lasso.
## Usage
`'lasso-select'` can be configured with different `trigger` to distinguish the other conflict behaviors, e.g. `'drag-canvas'`. For more detail, please refer to [lasso-select](/en/docs/manual/middle/states/defaultBehavior#lasso-select).

View File

@ -1,10 +0,0 @@
---
title: 拉索选择
order: 14
---
自 V3.6.2 起支持使用内置交互 `'lasso-select'`,允许终端用户在画布上绘制一个不规则多边形作为拉索选中几点/边/ combo。
## 何时使用
`'lasso-select'` 允许配置不同的 `trigger` 来区分拖拽画布。更多内容请参考 [lasso-select](/zh/docs/manual/middle/states/defaultBehavior#lasso-select)。

View File

@ -0,0 +1,81 @@
import G6 from '@antv/g6';
const data = {
nodes: [
{ id: 'node1', x: 150, y: 250 },
{ id: 'node2', x: 350, y: 250 },
],
edges: [{
source: 'node1', target: 'node2'
}]
};
let shift = true;
const graphDiv = document.getElementById('container');
const switchDiv = document.createElement('div');
switchDiv.innerHTML =
`Press 'shift' and drag begin on empty space to brush select. Click 「HERE」 to switch trigger to \'drag\', and disable drag-canvas
<br /> 按住 'shift' 并从画布空白处开始拖拽即可开始框选点击这里 trigger 切换为 'drag'同时关闭画布拖拽`;
graphDiv.appendChild(switchDiv);
const width = document.getElementById('container').scrollWidth;
const height = (document.getElementById('container').scrollHeight || 500) - 30;
const graph = new G6.Graph({
container: 'container',
width,
height,
fitCenter: true,
modes: {
default: ['brush-select', 'drag-node', 'drag-canvas'],
altSelect: [{
type: 'brush-select',
trigger: 'drag'
}, 'drag-node']
},
/* styles for different states, there are built-in styles for states: active, inactive, selected, highlight, disable. you can extend or custom it by the following lines */
/* 不同状态下节点和边的样式G6 提供以下状态名的默认样式active, inactive, selected, highlight, disable。可以通过如下方式修改或者扩展全局状态样式*/
// nodeStateStyles: {
// selected: {
// stroke: '#f00',
// lineWidth: 3
// }
// },
// edgeStateStyles: {
// selected: {
// lineWidth: 3,
// stroke: '#f00'
// }
// }
});
graph.on('node:mouseenter', e => {
graph.setItemState(e.item, 'active', true);
});
graph.on('node:mouseleave', e => {
graph.setItemState(e.item, 'active', false);
});
graph.on('nodeselectchange', e => {
console.log(e.selectedItems, e.select);
});
switchDiv.addEventListener('click', e => {
shift = !shift;
if (shift) {
graph.setMode('default');
switchDiv.innerHTML =
`Press \'shift\' and drag begin on empty space to brush select. Click Here to switch trigger to \'drag\', and disable drag-canvas
<br /> 按住 'shift' 并从画布空白处开始拖拽即可开始框选点击这里 trigger 切换为 'drag'同时关闭画布拖拽`;
} else {
graph.setMode('altSelect')
switchDiv.innerHTML =
`Press \'alt\' and drag begin on empty space to brush select. Click Here to switch trigger to key \'shift\', and enable drag-canvas
<br /> 按住 'alt' 并从画布空白处开始拖拽即可开始框选点击这里 trigger 切换为 'shift'同时开启画布拖拽`;
}
});
graph.data(data);
graph.render();

View File

@ -0,0 +1,81 @@
import G6 from '@antv/g6';
const data = {
nodes: [
{ id: 'node1', x: 150, y: 250 },
{ id: 'node2', x: 350, y: 250 },
],
edges: [{
source: 'node1', target: 'node2'
}]
};
let shift = true;
const graphDiv = document.getElementById('container');
const switchDiv = document.createElement('div');
switchDiv.innerHTML =
`Press \'shift\' to select multiple nodes. Click Here to switch trigger to key \'alt\'
<br /> 按住 'shift' 可多选节点点击这里 trigger 切换为 'alt'`;
graphDiv.appendChild(switchDiv);
const width = document.getElementById('container').scrollWidth;
const height = (document.getElementById('container').scrollHeight || 500) - 20;
const graph = new G6.Graph({
container: 'container',
width,
height,
fitCenter: true,
modes: {
default: ['click-select', 'drag-node'],
altSelect: [{
type: 'click-select',
trigger: 'alt'
}, 'drag-node']
},
/* styles for different states, there are built-in styles for states: active, inactive, selected, highlight, disable. you can extend or custom it by the following lines */
/* 不同状态下节点和边的样式G6 提供以下状态名的默认样式active, inactive, selected, highlight, disable。可以通过如下方式修改或者扩展全局状态样式*/
// nodeStateStyles: {
// selected: {
// stroke: '#f00',
// lineWidth: 3
// }
// },
// edgeStateStyles: {
// selected: {
// lineWidth: 3,
// stroke: '#f00'
// }
// }
});
graph.on('node:mouseenter', e => {
graph.setItemState(e.item, 'active', true);
});
graph.on('node:mouseleave', e => {
graph.setItemState(e.item, 'active', false);
});
graph.on('nodeselectchange', e => {
console.log(e.selectedItems, e.select);
});
switchDiv.addEventListener('click', e => {
shift = !shift;
if (shift) {
graph.setMode('default');
switchDiv.innerHTML =
`Press \'shift\' to select multiple nodes. Click Here to switch trigger to key \'alt\'
<br /> 按住 'shift' 可多选节点点击这里 trigger 切换为 'alt'`;
} else {
graph.setMode('altSelect')
switchDiv.innerHTML =
`Press \'alt\' to select multiple nodes. Click Here to switch trigger to key \'shift\'
<br /> 按住 'alt' 可多选节点点击这里 trigger 切换为 'shift'`;
}
});
graph.data(data);
graph.render();

View File

@ -0,0 +1,79 @@
import G6 from '@antv/g6';
const data = {
nodes: [
{ id: 'node1', x: 150, y: 250 },
{ id: 'node2', x: 350, y: 250 },
],
edges: [{
source: 'node1', target: 'node2'
}]
};
let shift = true;
const switchDiv = document.createElement('div');
switchDiv.innerHTML =
`Press down the 'shift' on keyboard and drag to begin select. Click「HERE」to switch trigger to \'drag\', and custom lasso style, and disable drag-canvas
<br /> 按住 'shift' 可开始拉索选择点击这里切换 trigger 'drag'同时修改拉索样式和关闭画布拖拽`;
const graphDiv = document.getElementById('container');
graphDiv.appendChild(switchDiv);
const width = document.getElementById('container').scrollWidth;
const height = (document.getElementById('container').scrollHeight || 500) - 20;
const graph = new G6.Graph({
container: 'container',
width,
height,
fitCenter: true,
modes: {
default: ['lasso-select', 'drag-node', 'drag-canvas'],
dragLasso: [{
type: 'lasso-select',
delegateStyle: {
fill: '#f00',
fillOpacity: 0.05,
stroke: '#f00',
lineWidth: 1
},
onSelect: (nodes, edges) => {
console.log('onSelect', nodes, edges)
},
trigger: 'drag'
}, 'drag-node'],
},
nodeStateStyles: {
selected: {
stroke: '#f00',
lineWidth: 3
}
},
edgeStateStyles: {
selected: {
lineWidth: 3,
stroke: '#f00'
}
}
});
graph.data(data);
graph.render();
graph.on('nodeselectchange', e => {
console.log(e.selectedItems, e.select);
})
switchDiv.addEventListener('click', e => {
shift = !shift;
if (shift) {
graph.setMode('default');
switchDiv.innerHTML =
`Press down the 'shift' on keyboard and drag to begin select. Click「HERE」to switch trigger to \'drag\', and custom lasso style, and disable drag-canvas
<br /> 按住 'shift' 可开始拉索选择点击这里切换 trigger 'drag'同时修改拉索样式和关闭画布拖拽`;
} else {
graph.setMode('dragLasso')
switchDiv.innerHTML =
`Drag on the canvas to begin lasso select. Click「HERE」to switch trigger to \'shift\', and enable drag-canvas
<br /> 拖拽画布即可进行拉索选择点击这里切换 trigger 'drag'同时开启画布拖拽`;
}
});

View File

@ -0,0 +1,23 @@
{
"title": {
"zh": "中文分类",
"en": "Category"
},
"demos": [
{
"filename": "click.js",
"title": "点击单选或多选",
"screenshot": "https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*F0RGQ67xbGYAAAAAAAAAAAAAARQnAQ"
},
{
"filename": "brush.js",
"title": "框选",
"screenshot": "https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*ZDEiRIQRByEAAAAAAAAAAAAAARQnAQ"
},
{
"filename": "lasso.js",
"title": "拉索选择",
"screenshot": "https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*8WwrRplTPG8AAAAAAAAAAAAAARQnAQ"
}
]
}

View File

@ -0,0 +1,14 @@
---
title: Select
order: 14
---
G6 provides some built-in behaviors for selection, including selecting a single item, selecting multiple items, selecting items by brushing, and selecting items by a lasso. Where behavior `'lasso-select'` for selecting by a lasso is a new feature of V3.6.2, which allows the users select items by drawing a irregular polygon as lasso.
## Usage
- Selecting a single item or selecting multiple items: a built-in behavior `'click-select'` with default configurations allows the end-user to select a single item by clicking. You can configure `multiple: true` for it to allow multiple selection by combining mouse clicking and keydown on keyboard. By default, the combined key is `shift`, and you can switch the `trigger` to one of `'shift'`, `'ctrl'`, `'alt'`, `'control'` as you want. For more detail, please refer to click-select](/en/docs/manual/middle/states/defaultBehavior#click-select);
- Selecting multiple items by brush: a built-in behavior `'brush-select'` with default configurations allows the end-user to select multiple items by combining `shift` keydown and draging start from any empty space on the canvas. The key can be switched to one of `'drag'`, `'shift'`, `'ctrl'`, `'alt'`, `'control'` by configuring `trigger`. Notice that, when you are using `'drag'` for `trigger`, the brush selection will start when the end-user drag the canvas without combining key, which might be conflict with `'drag-canvas'` if you configured. So we suggest to use one key for `trigger` to solve the conflict, For more detail, please refer to [brush-select](/en/docs/manual/middle/states/defaultBehavior#brush-select);
- Selecting multiple items by a lasso: a built-in behavior `'lasso-select` allows end-user to draw a lasso to select items inside it. Similar to `'brush-select'`, there are multiple options for `trigger` for keyboard combination. For more detail, please refer to [lasso-select](/en/docs/manual/middle/states/defaultBehavior#lasso-select).

View File

@ -0,0 +1,12 @@
---
title: 选中
order: 14
---
G6 提供内置的单选、多选、框选、拉索选择四种选中元素的方式。其中,内置交互 `'lasso-select'`自 V3.6.2 起支持,允许终端用户在画布上绘制一个不规则多边形作为拉索选中几点/边/ combo。
## 如何使用
- 单选与多选:内置交互 `'click-select'` 的默认配置允许终端用户单击选中节点;配置 `multiple: true` 即可允许组合键盘按键进行多选,默认的键盘按键为 `Shift`,可配置 `trigger``'shift'`、`'ctrl'`、`'alt'`、`'control'` 中的一个来更换键盘按。文档参见 [click-select](/zh/docs/manual/middle/states/defaultBehavior#click-select)
- 框选:内置交互 `'brush-select'` 为框选交互,在默认配置下,终端用户可以按住 `shift` 并从画布空白处开始拖拽进行框选。`shift` 也可以通过配置 `trigger` 替换为 `'drag'`、`'shift'`、`'ctrl'`、`'alt'`、`'control'`。需要注意的时,当使用 `'drag'`,即无键盘组合按键直接进行拖拽框选,可能会与 `'drag-canavs'` 的交互产生冲突。因此,我们推荐使用一个键盘组合按键进行区分。文档参见 [brush-select](/zh/docs/manual/middle/states/defaultBehavior#brush-select)
- 拉索选择:与 `'brush-select'` 类似,内置交互 `'lasso-select'` 允许配置不同的 `trigger` 来区分拖拽画布。更多内容请参考 [lasso-select](/zh/docs/manual/middle/states/defaultBehavior#lasso-select)。

View File

@ -53,28 +53,55 @@ const graph = new G6.Graph({
linkCenter: true,
// translate the graph to align the canvas's center, support by v3.5.1
fitCenter: true,
defaultNode: {
size: 45,
style: {
fill: '#DEE9FF',
stroke: '#5B8FF9',
},
modes: {
// 支持的 behavior
default: ['drag-node'],
},
defaultEdge: {
type: 'arc',
style: {
stroke: '#F6BD16',
},
/* you can configure the global edge style as following lines */
// style: {
// stroke: '#F6BD16',
// },
labelCfg: {
autoRotate: true,
refY: -10,
},
},
modes: {
// 支持的 behavior
default: ['drag-node'],
},
/* styles for different states, there are built-in styles for states: active, inactive, selected, highlight, disable */
// edgeStateStyles: {
// // edge style of active state
// active: {
// opacity: 0.5,
// stroke: '#f00'
// },
// // edge style of selected state
// selected: {
// stroke: '#ff0'
// lineWidth: 3,
// },
// },
});
graph.data(data);
graph.render();
graph.on('edge:mouseenter', (evt) => {
const { item } = evt;
graph.setItemState(item, 'active', true);
});
graph.on('edge:mouseleave', (evt) => {
const { item } = evt;
graph.setItemState(item, 'active', false);
});
graph.on('edge:click', (evt) => {
const { item } = evt;
graph.setItemState(item, 'selected', true);
});
graph.on('canvas:click', (evt) => {
graph.getEdges().forEach(edge => {
graph.clearItemStates(edge);
});
});

View File

@ -86,18 +86,46 @@ const graph = new G6.Graph({
modes: {
default: ['drag-canvas'],
},
defaultNode: {
style: {
fill: '#DEE9FF',
stroke: '#5B8FF9',
},
},
defaultEdge: {
type: 'cubic-vertical',
style: {
stroke: '#F6BD16',
},
/* you can configure the global edge style as following lines */
// style: {
// stroke: '#F6BD16',
// },
},
/* styles for different states, there are built-in styles for states: active, inactive, selected, highlight, disable */
// edgeStateStyles: {
// // edge style of active state
// active: {
// opacity: 0.5,
// stroke: '#f00'
// },
// // edge style of selected state
// selected: {
// stroke: '#ff0'
// lineWidth: 3,
// },
// },
});
graph.data(data);
graph.render();
graph.on('edge:mouseenter', (evt) => {
const { item } = evt;
graph.setItemState(item, 'active', true);
});
graph.on('edge:mouseleave', (evt) => {
const { item } = evt;
graph.setItemState(item, 'active', false);
});
graph.on('edge:click', (evt) => {
const { item } = evt;
graph.setItemState(item, 'selected', true);
});
graph.on('canvas:click', (evt) => {
graph.getEdges().forEach(edge => {
graph.clearItemStates(edge);
});
});

View File

@ -62,18 +62,46 @@ const graph = new G6.Graph({
modes: {
default: ['drag-canvas'],
},
defaultNode: {
style: {
fill: '#DEE9FF',
stroke: '#5B8FF9',
},
},
defaultEdge: {
type: 'cubic-horizontal',
style: {
stroke: '#F6BD16',
},
/* you can configure the global edge style as following lines */
// style: {
// stroke: '#F6BD16',
// },
},
/* styles for different states, there are built-in styles for states: active, inactive, selected, highlight, disable */
// edgeStateStyles: {
// // edge style of active state
// active: {
// opacity: 0.5,
// stroke: '#f00'
// },
// // edge style of selected state
// selected: {
// stroke: '#ff0'
// lineWidth: 3,
// },
// },
});
graph.data(data);
graph.render();
graph.on('edge:mouseenter', (evt) => {
const { item } = evt;
graph.setItemState(item, 'active', true);
});
graph.on('edge:mouseleave', (evt) => {
const { item } = evt;
graph.setItemState(item, 'active', false);
});
graph.on('edge:click', (evt) => {
const { item } = evt;
graph.setItemState(item, 'selected', true);
});
graph.on('canvas:click', (evt) => {
graph.getEdges().forEach(edge => {
graph.clearItemStates(edge);
});
});

View File

@ -34,19 +34,18 @@ const graph = new G6.Graph({
height,
// translate the graph to align the canvas's center
fitCenter: true,
defaultNode: {
style: {
fill: '#DEE9FF',
stroke: '#5B8FF9',
},
modes: {
// 支持的 behavior
default: ['drag-node'],
},
defaultEdge: {
type: 'loop',
/* you can configure the global edge style as following lines */
style: {
stroke: '#F6BD16',
// stroke: '#F6BD16',
endArrow: {
path: 'M 0,0 L 20,10 L 20,-10 Z',
fill: '#F6BD16',
fill: '#eee',
},
},
// 更多关于 loop 的配置请参考http://antv.alipay.com/zh/docs/manual/middle/elements/edges/loop/#%E8%87%AA%E7%8E%AF%E7%89%B9%E6%AE%8A%E9%85%8D%E7%BD%AE-loopcfg
@ -54,10 +53,19 @@ const graph = new G6.Graph({
position: 'top',
},
},
modes: {
// 支持的 behavior
default: ['drag-node'],
},
/* styles for different states, there are built-in styles for states: active, inactive, selected, highlight, disable */
// edgeStateStyles: {
// // edge style of active state
// active: {
// opacity: 0.5,
// stroke: '#f00'
// },
// // edge style of selected state
// selected: {
// stroke: '#ff0'
// lineWidth: 3,
// },
// },
});
// 需要等 G 4.0 局部渲染完善后,就不用临时关闭了
@ -66,3 +74,24 @@ canvas.set('localRefresh', false);
graph.data(data);
graph.render();
graph.on('edge:mouseenter', (evt) => {
const { item } = evt;
graph.setItemState(item, 'active', true);
});
graph.on('edge:mouseleave', (evt) => {
const { item } = evt;
graph.setItemState(item, 'active', false);
});
graph.on('edge:click', (evt) => {
const { item } = evt;
graph.setItemState(item, 'selected', true);
});
graph.on('canvas:click', (evt) => {
graph.getEdges().forEach(edge => {
graph.clearItemStates(edge);
});
});

View File

@ -35,23 +35,53 @@ const graph = new G6.Graph({
height,
// translate the graph to align the canvas's center, support by v3.5.1
fitCenter: true,
defaultNode: {
style: {
fill: '#DEE9FF',
stroke: '#5B8FF9',
},
},
defaultEdge: {
type: 'polyline',
style: {
stroke: '#F6BD16',
},
},
// make the edge link to the centers of the end nodes
linkCenter: true,
modes: {
// behavior
default: ['drag-node'],
},
defaultEdge: {
type: 'polyline',
/* you can configure the global edge style as following lines */
// style: {
// stroke: '#F6BD16',
// },
},
/* styles for different states, there are built-in styles for states: active, inactive, selected, highlight, disable */
// edgeStateStyles: {
// // edge style of active state
// active: {
// opacity: 0.5,
// stroke: '#f00'
// },
// // edge style of selected state
// selected: {
// stroke: '#ff0'
// lineWidth: 3,
// },
// },
});
graph.data(data);
graph.render();
graph.on('edge:mouseenter', (evt) => {
const { item } = evt;
graph.setItemState(item, 'active', true);
});
graph.on('edge:mouseleave', (evt) => {
const { item } = evt;
graph.setItemState(item, 'active', false);
});
graph.on('edge:click', (evt) => {
const { item } = evt;
graph.setItemState(item, 'selected', true);
});
graph.on('canvas:click', (evt) => {
graph.getEdges().forEach(edge => {
graph.clearItemStates(edge);
});
});

View File

@ -32,29 +32,57 @@ const graph = new G6.Graph({
container: 'container',
width,
height,
// translate the graph to align the canvas's center, support by v3.5.1
/* translate the graph to align the canvas's center, support by v3.5.1 */
fitCenter: true,
defaultNode: {
style: {
fill: '#DEE9FF',
stroke: '#5B8FF9',
},
modes: {
/* behavior */
default: ['drag-node'],
},
defaultEdge: {
type: 'polyline',
// configure the bending radius and min distance to the end nodes
/* configure the bending radius and min distance to the end nodes */
style: {
radius: 10,
offset: 30,
endArrow: true,
stroke: '#F6BD16',
/* and other styles */
// stroke: '#F6BD16',
},
},
modes: {
// behavior
default: ['drag-node'],
},
/* styles for different states, there are built-in styles for states: active, inactive, selected, highlight, disable */
// edgeStateStyles: {
// // edge style of active state
// active: {
// opacity: 0.5,
// stroke: '#f00'
// },
// // edge style of selected state
// selected: {
// stroke: '#ff0'
// lineWidth: 3,
// },
// },
});
graph.data(data);
graph.render();
graph.on('edge:mouseenter', (evt) => {
const { item } = evt;
graph.setItemState(item, 'active', true);
});
graph.on('edge:mouseleave', (evt) => {
const { item } = evt;
graph.setItemState(item, 'active', false);
});
graph.on('edge:click', (evt) => {
const { item } = evt;
graph.setItemState(item, 'selected', true);
});
graph.on('canvas:click', (evt) => {
graph.getEdges().forEach(edge => {
graph.clearItemStates(edge);
});
});

View File

@ -57,23 +57,53 @@ const graph = new G6.Graph({
height,
// translate the graph to align the canvas's center, support by v3.5.1
fitCenter: true,
defaultNode: {
style: {
fill: '#DEE9FF',
stroke: '#5B8FF9',
},
},
defaultEdge: {
type: 'polyline',
style: {
stroke: '#F6BD16',
},
},
// make the edge link to the centers of the end nodes
linkCenter: true,
modes: {
// behavior
default: ['drag-node'],
},
defaultEdge: {
type: 'polyline',
/* you can configure the global edge style as following lines */
// style: {
// stroke: '#F6BD16',
// },
},
/* styles for different states, there are built-in styles for states: active, inactive, selected, highlight, disable */
// edgeStateStyles: {
// // edge style of active state
// active: {
// opacity: 0.5,
// stroke: '#f00'
// },
// // edge style of selected state
// selected: {
// stroke: '#ff0'
// lineWidth: 3,
// },
// },
});
graph.data(data);
graph.render();
graph.on('edge:mouseenter', (evt) => {
const { item } = evt;
graph.setItemState(item, 'active', true);
});
graph.on('edge:mouseleave', (evt) => {
const { item } = evt;
graph.setItemState(item, 'active', false);
});
graph.on('edge:click', (evt) => {
const { item } = evt;
graph.setItemState(item, 'selected', true);
});
graph.on('canvas:click', (evt) => {
graph.getEdges().forEach(edge => {
graph.clearItemStates(edge);
});
});

View File

@ -398,21 +398,6 @@ const graph = new G6.Graph({
animate: true,
defaultNode: {
size: 20,
style: {
lineWidth: 2,
fill: '#C6E5FF',
stroke: '#5B8FF9',
},
},
defaultEdge: {
size: 1,
color: '#e2e2e2',
style: {
endArrow: {
path: 'M 0,0 L 8,4 L 8,-4 Z',
fill: '#e2e2e2',
},
},
},
});
graph.data(data);

View File

@ -404,15 +404,8 @@ const graph = new G6.Graph({
animate: true,
defaultNode: {
size: 20,
style: {
lineWidth: 2,
fill: '#C6E5FF',
stroke: '#5B8FF9',
},
},
defaultEdge: {
size: 1,
color: '#e2e2e2',
style: {
endArrow: {
path: 'M 0,0 L 8,4 L 8,-4 Z',

View File

@ -399,15 +399,8 @@ const graph = new G6.Graph({
animate: true,
defaultNode: {
size: 20,
style: {
lineWidth: 2,
fill: '#C6E5FF',
stroke: '#5B8FF9',
},
},
defaultEdge: {
size: 1,
color: '#e2e2e2',
style: {
endArrow: {
path: 'M 0,0 L 8,4 L 8,-4 Z',

View File

@ -402,15 +402,8 @@ const graph = new G6.Graph({
animate: true,
defaultNode: {
size: 20,
style: {
lineWidth: 2,
fill: '#C6E5FF',
stroke: '#5B8FF9',
},
},
defaultEdge: {
size: 1,
color: '#e2e2e2',
style: {
endArrow: {
path: 'M 0,0 L 8,4 L 8,-4 Z',

View File

@ -400,15 +400,8 @@ const graph = new G6.Graph({
animate: true,
defaultNode: {
size: 20,
style: {
lineWidth: 2,
fill: '#C6E5FF',
stroke: '#5B8FF9',
},
},
defaultEdge: {
size: 1,
color: '#e2e2e2',
style: {
endArrow: {
path: 'M 0,0 L 8,4 L 8,-4 Z',

View File

@ -17,14 +17,6 @@ const graph = new G6.Graph({
animate: true,
defaultNode: {
size: 5,
style: {
fill: '#C6E5FF',
stroke: '#5B8FF9',
},
},
defaultEdge: {
size: 1,
color: '#e2e2e2',
},
});

View File

@ -11,15 +11,6 @@ const graph = new G6.Graph({
},
defaultNode: {
size: 15,
color: '#5B8FF9',
style: {
lineWidth: 2,
fill: '#C6E5FF',
},
},
defaultEdge: {
size: 1,
color: '#e2e2e2',
},
});

View File

@ -111,15 +111,6 @@ const graph = new G6.Graph({
},
defaultNode: {
size: 20,
color: '#5B8FF9',
style: {
lineWidth: 2,
fill: '#C6E5FF',
},
},
defaultEdge: {
size: 1,
color: '#e2e2e2',
},
});
graph.data(data);

View File

@ -18,15 +18,6 @@ const graph = new G6.Graph({
},
defaultNode: {
size: 15,
color: '#5B8FF9',
style: {
lineWidth: 2,
fill: '#C6E5FF',
},
},
defaultEdge: {
size: 1,
color: '#e2e2e2',
},
modes: {
default: ['zoom-canvas', 'drag-canvas', 'drag-node']

View File

@ -68,15 +68,6 @@ fetch('https://gw.alipayobjects.com/os/antvdemo/assets/data/relations.json')
},
defaultNode: {
size: 15,
color: '#5B8FF9',
style: {
lineWidth: 2,
fill: '#C6E5FF',
},
},
defaultEdge: {
size: 1,
color: '#e2e2e2',
},
});

View File

@ -404,21 +404,6 @@ const graph = new G6.Graph({
animate: true,
defaultNode: {
size: 20,
color: '#5B8FF9',
style: {
lineWidth: 2,
fill: '#C6E5FF',
},
},
defaultEdge: {
size: 1,
color: '#e2e2e2',
style: {
endArrow: {
path: 'M 0,0 L 8,4 L 8,-4 Z',
fill: '#e2e2e2',
},
},
},
});
graph.data(data);

View File

@ -30,14 +30,6 @@ const graph = new G6.Graph({
},
defaultNode: {
color: '#5B8FF9',
style: {
lineWidth: 2,
fill: '#C6E5FF',
},
},
defaultEdge: {
size: 1,
color: '#e2e2e2',
},
});

View File

@ -10,17 +10,6 @@ const graph = new G6.Graph({
type: 'force',
preventOverlap: true,
},
defaultNode: {
color: '#5B8FF9',
style: {
lineWidth: 2,
fill: '#C6E5FF',
},
},
defaultEdge: {
size: 1,
color: '#e2e2e2',
},
});
fetch('https://gw.alipayobjects.com/os/antvdemo/assets/data/relations.json')

View File

@ -434,21 +434,6 @@ const graph = new G6.Graph({
animate: true,
defaultNode: {
size: 30,
style: {
lineWidth: 2,
stroke: '#5B8FF9',
fill: '#C6E5FF',
},
},
defaultEdge: {
size: 1,
color: '#e2e2e2',
style: {
endArrow: {
path: 'M 0,0 L 8,4 L 8,-4 Z',
fill: '#e2e2e2',
},
},
},
});
graph.data(data);

View File

@ -477,13 +477,8 @@ const graph = new G6.Graph({
animate: true,
defaultNode: {
size: 20,
style: {
lineWidth: 2,
},
},
defaultEdge: {
size: 1,
color: '#e2e2e2',
style: {
endArrow: {
path: 'M 0,0 L 8,4 L 8,-4 Z',

View File

@ -479,13 +479,9 @@ const graph = new G6.Graph({
animate: true,
defaultNode: {
size: 20,
style: {
lineWidth: 2,
},
},
defaultEdge: {
size: 1,
color: '#e2e2e2',
style: {
endArrow: {
path: 'M 0,0 L 8,4 L 8,-4 Z',

View File

@ -25,18 +25,9 @@ const graph = new G6.Graph({
animate: true,
defaultNode: {
size: 10,
style: {
lineWidth: 2,
stroke: '#5B8FF9',
fill: '#C6E5FF',
},
},
defaultEdge: {
size: 1,
color: '#666',
style: {
opacity: 0.1,
},
},
});

View File

@ -401,14 +401,6 @@ const graph = new G6.Graph({
animate: true,
defaultNode: {
size: 20,
style: {
fill: '#C6E5FF',
stroke: '#5B8FF9',
},
},
defaultEdge: {
size: 1,
color: '#e2e2e2',
},
});
graph.data(data);

View File

@ -477,10 +477,6 @@ const graph = new G6.Graph({
defaultNode: {
size: 20,
},
defaultEdge: {
size: 1,
color: '#e2e2e2',
},
});
graph.data(data);
graph.render();

View File

@ -0,0 +1,71 @@
import G6 from '@antv/g6';
const tipDiv = document.createElement('div');
tipDiv.innerHTML = 'Random Layout';
const graphDiv = document.getElementById('container');
graphDiv.appendChild(tipDiv);
const width = graphDiv.scrollWidth;
const height = (graphDiv.scrollHeight || 500) - 20;
const graph = new G6.Graph({
container: 'container',
width,
height,
layout: {
type: 'random',
},
modes: {
default: ['drag-node'],
},
animate: true
});
fetch('https://gw.alipayobjects.com/os/antvdemo/assets/data/relations.json')
.then((res) => res.json())
.then((data) => {
graph.data(data);
graph.render();
setTimeout(() => {
tipDiv.innerHTML = 'Circular Layout';
graph.updateLayout({
type: 'circular',
radius: 200
});
}, 3000);
setTimeout(() => {
tipDiv.innerHTML = 'Grid Layout';
graph.updateLayout({
type: 'grid'
});
}, 6000);
setTimeout(() => {
tipDiv.innerHTML = 'Force Layout';
graph.updateLayout({
type: 'force',
preventOverlap: true,
nodeSize: 20,
});
}, 9000);
setTimeout(() => {
tipDiv.innerHTML = 'Radial Layout';
graph.updateLayout({
type: 'radial',
preventOverlap: true,
nodeSize: 15
});
}, 12000);
setTimeout(() => {
tipDiv.innerHTML = 'Concentric Layout';
graph.updateLayout({
type: 'concentric',
minNodeSpacing: 30
});
}, 15000);
setTimeout(() => {
tipDiv.innerHTML = 'MDS Layout';
graph.updateLayout({
type: 'mds',
linkDistance: 100,
});
}, 18000);
});

View File

@ -4,6 +4,14 @@
"en": "Category"
},
"demos": [
{
"filename": "layoutTranslate.js",
"title": {
"zh": "布局切换",
"en": "Layout Translate"
},
"screenshot": "https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*eZRNQ4tpkecAAAAAAAAAAAAAARQnAQ"
},
{
"filename": "subgraphLayout.js",
"title": {

View File

@ -399,14 +399,6 @@ const graph = new G6.Graph({
},
defaultNode: {
size: 20,
style: {
fill: '#C6E5FF',
stroke: '#5B8FF9',
},
},
defaultEdge: {
size: 1,
color: '#e2e2e2',
},
});
graph.data(data);

View File

@ -398,21 +398,6 @@ const graph = new G6.Graph({
animate: true,
defaultNode: {
size: 20,
style: {
lineWidth: 2,
fill: '#C6E5FF',
stroke: '#5B8FF9',
},
},
defaultEdge: {
size: 1,
color: '#e2e2e2',
style: {
endArrow: {
path: 'M 0,0 L 8,4 L 8,-4 Z',
fill: '#e2e2e2',
},
},
},
});
graph.data(data);

View File

@ -677,15 +677,6 @@ const graph = new G6.Graph({
},
defaultNode: {
size: 20,
style: {
lineWidth: 2,
fill: '#C6E5FF',
stroke: '#5B8FF9',
},
},
defaultEdge: {
size: 1,
color: '#e2e2e2',
},
});

View File

@ -399,16 +399,7 @@ const graph = new G6.Graph({
maxPreventOverlapIteration: 100,
},
animate: true,
defaultNode: {
style: {
lineWidth: 2,
fill: '#C6E5FF',
stroke: '#5B8FF9',
},
},
defaultEdge: {
size: 1,
color: '#e2e2e2',
style: {
endArrow: {
path: 'M 0,0 L 8,4 L 8,-4 Z',

View File

@ -401,15 +401,8 @@ const graph = new G6.Graph({
animate: true,
defaultNode: {
size: 20,
style: {
lineWidth: 2,
fill: '#C6E5FF',
stroke: '#5B8FF9',
},
},
defaultEdge: {
size: 1,
color: '#e2e2e2',
style: {
endArrow: {
path: 'M 0,0 L 8,4 L 8,-4 Z',

View File

@ -406,15 +406,8 @@ const graph = new G6.Graph({
animate: true,
defaultNode: {
size: 20,
style: {
lineWidth: 2,
fill: '#C6E5FF',
stroke: '#5B8FF9',
},
},
defaultEdge: {
size: 1,
color: '#e2e2e2',
style: {
endArrow: {
path: 'M 0,0 L 8,4 L 8,-4 Z',

View File

@ -438,8 +438,6 @@ const graph = new G6.Graph({
},
animate: true,
defaultEdge: {
size: 1,
color: '#e2e2e2',
style: {
endArrow: {
path: 'M 0,0 L 8,4 L 8,-4 Z',

View File

@ -29,16 +29,9 @@ fetch('https://gw.alipayobjects.com/os/antvdemo/assets/data/algorithm-category.j
[0, 0.5],
[1, 0.5],
],
style: {
fill: '#C6E5FF',
stroke: '#5B8FF9',
},
},
defaultEdge: {
type: 'cubic-horizontal',
style: {
stroke: '#A3B1BF',
},
},
layout: {
type: 'compactBox',

View File

@ -30,16 +30,6 @@ fetch('https://gw.alipayobjects.com/os/antvdemo/assets/data/algorithm-category.j
[0, 0.5],
[1, 0.5],
],
style: {
fill: '#C6E5FF',
stroke: '#5B8FF9',
},
},
defaultEdge: {
type: 'cubic-vertical',
style: {
stroke: '#A3B1BF',
},
},
layout: {
type: 'compactBox',

View File

@ -102,15 +102,6 @@ const graph = new G6.TreeGraph({
},
defaultNode: {
size: 30,
style: {
fill: '#C6E5FF',
stroke: '#5B8FF9',
},
},
defaultEdge: {
style: {
stroke: '#A3B1BF',
},
},
layout: {
type: 'compactBox',

View File

@ -29,16 +29,9 @@ fetch('https://gw.alipayobjects.com/os/antvdemo/assets/data/algorithm-category.j
[0, 0.5],
[1, 0.5],
],
style: {
fill: '#C6E5FF',
stroke: '#5B8FF9',
},
},
defaultEdge: {
type: 'cubic-horizontal',
style: {
stroke: '#A3B1BF',
},
},
layout: {
type: 'dendrogram',

View File

@ -30,16 +30,9 @@ fetch('https://gw.alipayobjects.com/os/antvdemo/assets/data/algorithm-category.j
[0, 0.5],
[1, 0.5],
],
style: {
fill: '#C6E5FF',
stroke: '#5B8FF9',
},
},
defaultEdge: {
type: 'cubic-vertical',
style: {
stroke: '#A3B1BF',
},
},
layout: {
type: 'dendrogram',

View File

@ -15,16 +15,9 @@ fetch('https://gw.alipayobjects.com/os/antvdemo/assets/data/algorithm-category.j
[0, 0.5],
[1, 0.5],
],
style: {
fill: '#C6E5FF',
stroke: '#5B8FF9',
},
},
defaultEdge: {
type: 'cubic-horizontal',
style: {
stroke: '#A3B1BF',
},
},
layout: {
type: 'indented',

View File

@ -113,15 +113,10 @@ const graph = new G6.TreeGraph({
defaultNode: {
type: 'card-node',
size: [100, 40],
style: {
fill: '#C6E5FF',
stroke: '#5B8FF9',
},
},
defaultEdge: {
type: 'cubic-horizontal',
style: {
stroke: '#A3B1BF',
endArrow: true,
},
},

View File

@ -29,16 +29,9 @@ fetch('https://gw.alipayobjects.com/os/antvdemo/assets/data/algorithm-category.j
[0, 0.5],
[1, 0.5],
],
style: {
fill: '#C6E5FF',
stroke: '#5B8FF9',
},
},
defaultEdge: {
type: 'cubic-horizontal',
style: {
stroke: '#A3B1BF',
},
},
layout: {
type: 'mindmap',

View File

@ -29,16 +29,9 @@ fetch('https://gw.alipayobjects.com/os/antvdemo/assets/data/algorithm-category.j
[0, 0.5],
[1, 0.5],
],
style: {
fill: '#C6E5FF',
stroke: '#5B8FF9',
},
},
defaultEdge: {
type: 'cubic-horizontal',
style: {
stroke: '#A3B1BF',
},
},
layout: {
type: 'mindmap',

View File

@ -29,16 +29,9 @@ fetch('https://gw.alipayobjects.com/os/antvdemo/assets/data/algorithm-category.j
[0, 0.5],
[1, 0.5],
],
style: {
fill: '#C6E5FF',
stroke: '#5B8FF9',
},
},
defaultEdge: {
type: 'cubic-horizontal',
style: {
stroke: '#A3B1BF',
},
},
layout: {
type: 'mindmap',

View File

@ -29,16 +29,9 @@ fetch('https://gw.alipayobjects.com/os/antvdemo/assets/data/algorithm-category.j
[0, 0.5],
[1, 0.5],
],
style: {
fill: '#C6E5FF',
stroke: '#5B8FF9',
},
},
defaultEdge: {
type: 'cubic-horizontal',
style: {
stroke: '#A3B1BF',
},
},
layout: {
type: 'mindmap',

View File

@ -26,15 +26,6 @@ fetch('https://gw.alipayobjects.com/os/antvdemo/assets/data/algorithm-category.j
},
defaultNode: {
size: 26,
style: {
fill: '#C6E5FF',
stroke: '#5B8FF9',
},
},
defaultEdge: {
style: {
stroke: '#A3B1BF',
},
},
layout: {
type: 'compactBox',

View File

@ -26,15 +26,6 @@ fetch('https://gw.alipayobjects.com/os/antvdemo/assets/data/algorithm-category.j
},
defaultNode: {
size: 26,
style: {
fill: '#C6E5FF',
stroke: '#5B8FF9',
},
},
defaultEdge: {
style: {
stroke: '#A3B1BF',
},
},
layout: {
type: 'dendrogram',

View File

@ -275,6 +275,14 @@ module.exports = {
en: 'Component',
},
},
{
slug: 'algorithm',
icon: 'gallery',
title: {
zh: '算法',
en: 'Algorithm',
},
},
{
slug: 'case',
icon: 'case',

View File

@ -29,11 +29,13 @@ const dijkstra = (
if (D[minNodId] === Infinity) continue; // Unreachable vertices cannot be the intermediate point
let relatedEdges = [];
if (!directed) relatedEdges = minNode.getOutEdges();
if (directed) relatedEdges = minNode.getOutEdges();
else relatedEdges = minNode.getEdges();
relatedEdges.forEach((e) => {
const w = e.getTarget().getID();
const edgeTarget = e.getTarget().getID();
const edgeSource = e.getSource().getID();
const w = edgeTarget === minNodId ? edgeSource : edgeTarget;
const weight =
weightPropertyName && e.getModel()[weightPropertyName]
? e.getModel()[weightPropertyName]

View File

@ -206,8 +206,12 @@ export default {
if (!code) {
return;
}
const triggerLowerCase = this.trigger.toLowerCase();
const codeLowerCase = code.toLowerCase();
// 按住 control 键时,允许用户设置 trigger 为 ctrl
if (code.toLowerCase() === this.trigger.toLowerCase() || code.toLowerCase() === 'control') {
if (codeLowerCase === triggerLowerCase
|| (codeLowerCase === 'control' && triggerLowerCase === 'ctrl')
|| (codeLowerCase === 'ctrl' && triggerLowerCase === 'control')) {
this.keydown = true;
} else {
this.keydown = false;

View File

@ -16,6 +16,7 @@ import DragCombo from './drag-combo';
import CollapseExpandCombo from './collapse-expand-combo';
import LassoSelect from './lasso-select';
import CreateEdge from './create-edge';
import ShortcutsCall from './shortcuts-call';
const behaviors = {
'drag-canvas': DragCanvas,
@ -33,7 +34,8 @@ const behaviors = {
'collapse-expand': CollapseExpand,
'drag-combo': DragCombo,
'collapse-expand-combo': CollapseExpandCombo,
'create-edge': CreateEdge
'create-edge': CreateEdge,
'shortcuts-call': ShortcutsCall
};
each(behaviors, (behavior, type: string) => {

View File

@ -0,0 +1,87 @@
import { G6Event, IG6GraphEvent } from '../types';
const DEFAULT_TRIGGER = 'ctrl';
const ALLOW_EVENTS = ['shift', 'ctrl', 'alt', 'control'];
const DEFAULT_COMBINED_KEY = '1';
export default {
getDefaultCfg(): object {
return {
trigger: DEFAULT_TRIGGER,
combinedKey: DEFAULT_COMBINED_KEY,
functionName: 'fitView',
functionParams: []
};
},
getEvents(): { [key in G6Event]?: string } {
// 检测输入是否合法
if (!(ALLOW_EVENTS.indexOf(this.trigger.toLowerCase()) > -1)) {
this.trigger = DEFAULT_TRIGGER;
console.warn(
`Behavior shortcuts-fit-view 的 trigger 参数 '${this.trigger}' 不合法,请输入 'drag'、'shift'、'ctrl' 或 'alt'`,
);
}
if (this.combinedKey === this.trigger) {
this.combinedKey = undefined;
}
if (!this.graph[this.functionName]) {
console.warn(
`Behavior shortcuts-fit-view 的 functionName 参数 '${this.functionName}' 不合法,它不是 Graph 的一个函数名`,
);
return {};
}
return {
keyup: 'onKeyUp',
keydown: 'onKeyDown'
};
},
onKeyDown(e: IG6GraphEvent) {
const code = e.key;
if (!code) {
return;
}
const triggerLowerCase = this.trigger.toLowerCase();
const codeLowerCase = code.toLowerCase();
// 按住 control 键时,允许用户设置 trigger 为 ctrl
if (!this.triggerKeydown) {
if (codeLowerCase === triggerLowerCase
|| (codeLowerCase === 'control' && triggerLowerCase === 'ctrl')
|| (codeLowerCase === 'ctrl' && triggerLowerCase === 'control')) {
this.triggerKeydown = true;
} else {
this.triggerKeydown = false;
}
}
const { graph } = this;
// 未配置 combinedKey直接 fitView
if (this.triggerKeydown && !this.combinedKey) {
if (this.functionParams && this.functionParams.length) graph[this.functionName](...this.functionParams);
else graph[this.functionName]();
return;
}
const combinedKeyLowerCase = this.combinedKey.toLowerCase();
if (this.triggerKeydown) {
if (codeLowerCase === combinedKeyLowerCase
|| (codeLowerCase === 'control' && combinedKeyLowerCase === 'ctrl')
|| (codeLowerCase === 'ctrl' && combinedKeyLowerCase === 'control')) {
if (this.functionParams && this.functionParams.length) graph[this.functionName](...this.functionParams);
else graph[this.functionName]();
}
}
},
onKeyUp() {
if (this.brush) {
// 清除所有选中状态后设置拖得动状态为false并清除框选的brush
this.brush.remove(true);
this.brush = null;
this.dragging = false;
}
this.triggerKeydown = false;
},
};

View File

@ -89,11 +89,11 @@ export default {
},
defaultEdge: {
type: 'line',
size: 1,
style: {
stroke: colorSet.edgeMainStroke,
lineAppendWidth: 4,
lineAppendWidth: 2,
},
size: 1,
color: colorSet.edgeMainStroke,
},
// 边应用状态后的样式,默认仅提供 active、selected、highlight、inactive、disable用户可以自己扩展

View File

@ -63,7 +63,7 @@ const singleEdge: ShapeOptions = {
x: 0,
y: 0,
stroke: Global.defaultEdge.style.stroke,
lineWidth: Global.defaultEdge.style.lineWidth
lineAppendWidth: Global.defaultEdge.style.lineAppendWidth
},
labelCfg: {
style: {

View File

@ -22,7 +22,7 @@ Shape.registerEdge(
x: 0,
y: 0,
stroke: Global.defaultEdge.style.stroke,
lineWidth: Global.defaultEdge.style.lineWidth
lineAppendWidth: Global.defaultEdge.style.lineAppendWidth
},
// 文本样式配置
labelCfg: {

View File

@ -25,6 +25,13 @@ export const mixColor = (backColor, frontColor, frontAlpha) => {
*/
export const getColorsWithSubjectColor = (subjectColor, backColor = '#fff', theme: 'default' | 'dark' = 'default', disableColor = 'rgb(150, 150, 150)') => {
const lightSubject = mixColor(backColor, subjectColor, 0.05).rgb().toString();
const lightestDisable = mixColor(backColor, disableColor, 0.02).rgb().toString();
const lightDisable = mixColor(backColor, disableColor, 0.05).rgb().toString();
const middleDisable = mixColor(backColor, disableColor, 0.1).rgb().toString();
const deepDisable = mixColor(backColor, disableColor, 0.2).rgb().toString();
const deepestDisable = mixColor(backColor, disableColor, 0.3).rgb().toString();
const paletteFromSubject = generate(subjectColor, { theme, backgroundColor: backColor });
const subjectHex = color(subjectColor).hex().toLowerCase();
const subjectIdx = paletteFromSubject.indexOf(subjectHex);
@ -49,35 +56,35 @@ export const getColorsWithSubjectColor = (subjectColor, backColor = '#fff', them
highlightStroke: deeperSubject,
highlightFill: mixColor(backColor, subjectColor, 0.2).rgb().toString(),
disableStroke: mixColor(backColor, disableColor, 0.3).rgb().toString(),
disableFill: mixColor(backColor, disableColor, 0.05).rgb().toString(),
disableStroke: deepestDisable,
disableFill: lightDisable,
// for edges
edgeMainStroke: disableColor,
edgeMainStroke: deepestDisable,
edgeActiveStroke: subjectColor,
edgeInactiveStroke: mixColor(backColor, disableColor, 0.2).rgb().toString(),
edgeInactiveStroke: deepDisable,
edgeSelectedStroke: subjectColor,
edgeHighlightStroke: subjectColor,
edgeDisableStroke: mixColor(backColor, disableColor, 0.1).rgb().toString(),
edgeDisableStroke: middleDisable,
// for combos
comboMainStroke: mixColor(backColor, disableColor, 0.3).rgb().toString(),
comboMainFill: mixColor(backColor, disableColor, 0.02).rgb().toString(),
comboMainStroke: deepestDisable,
comboMainFill: lightestDisable,
comboActiveStroke: subjectColor,
comboActiveFill: lightSubject,
comboInactiveStroke: mixColor(backColor, disableColor, 0.3).rgb().toString(),
comboInactiveFill: mixColor(backColor, disableColor, 0.02).rgb().toString(),
comboInactiveStroke: deepestDisable,
comboInactiveFill: lightestDisable,
comboSelectedStroke: subjectColor,
comboSelectedFill: mixColor(backColor, disableColor, 0.02).rgb().toString(),
comboSelectedFill: lightestDisable,
comboHighlightStroke: deeperSubject, // 'rgb(53, 119, 222)', // TODO: how to generate it ???
comboHighlightFill: mixColor(backColor, disableColor, 0.02).rgb().toString(),
comboHighlightFill: lightestDisable,
comboDisableStroke: mixColor(backColor, disableColor, 0.2).rgb().toString(),
comboDisableFill: mixColor(backColor, disableColor, 0.05).rgb().toString(),
comboDisableStroke: deepDisable,
comboDisableFill: lightDisable,
}
}

View File

@ -1203,7 +1203,7 @@ describe('mapper fn', () => {
const edge = graph.addItem('edge', { id: 'edge2', source: 'node', target: 'node2Mapped' });
keyShape = edge.getKeyShape();
expect(keyShape.attr('stroke')).toEqual('rgb(150, 150, 150)');
expect(keyShape.attr('stroke')).toEqual('rgb(224, 224, 224)');
expect(keyShape.attr('lineWidth')).toEqual(1);
expect(keyShape.attr('fillOpacity')).toEqual(1);

View File

@ -524,12 +524,12 @@ describe('shape edge test', () => {
const path = edge.get('group').get('children')[0];
let bbox = path.getBBox();
console.log(bbox);
expect(bbox.minX).toEqual(89.60845891791658);
expect(bbox.minX).toEqual(90.60845891791658);
graph.emit('node:dragstart', { x: 100, y: 100, item: node });
graph.emit('node:drag', { x: 200, y: 200, item: node });
graph.emit('node:dragend', { x: 200, y: 200, item: node });
bbox = path.getBBox();
expect(bbox.minX).toEqual(189.6084589179166);
expect(bbox.minX).toEqual(190.6084589179166);
});
it('clear', () => {

View File

@ -56,7 +56,7 @@ describe('polyline e test', () => {
const edge = edges[0];
const keyShape = edge.getKeyShape();
expect(keyShape.attr('lineWidth')).toEqual(1);
expect(keyShape.attr('stroke')).toEqual('rgb(150, 150, 150)');
expect(keyShape.attr('stroke')).toEqual('rgb(224, 224, 224)');
});
it('polyline radius and default offset', () => {
@ -92,7 +92,7 @@ describe('polyline e test', () => {
const edge = edges[0];
const keyShape = edge.getKeyShape();
expect(keyShape.attr('lineWidth')).toEqual(1);
expect(keyShape.attr('stroke')).toEqual('rgb(150, 150, 150)');
expect(keyShape.attr('stroke')).toEqual('rgb(224, 224, 224)');
});
it('polyline radius and no offset', () => {
@ -129,7 +129,7 @@ describe('polyline e test', () => {
const edge = edges[0];
const keyShape = edge.getKeyShape();
expect(keyShape.attr('lineWidth')).toEqual(1);
expect(keyShape.attr('stroke')).toEqual('rgb(150, 150, 150)');
expect(keyShape.attr('stroke')).toEqual('rgb(224, 224, 224)');
});
it('polyline with label', () => {
const data = {
@ -261,7 +261,7 @@ describe('polyline e test', () => {
const edge = edges[0];
const keyShape = edge.getKeyShape();
expect(keyShape.attr('lineWidth')).toEqual(1);
expect(keyShape.attr('stroke')).toEqual('rgb(150, 150, 150)');
expect(keyShape.attr('stroke')).toEqual('rgb(224, 224, 224)');
});
});

View File

@ -376,7 +376,7 @@ describe('graph edge states', () => {
expect(item.hasState('state1')).toEqual(true);
const keyShape = edge.getKeyShape();
expect(keyShape.attr('lineWidth')).toEqual(3);
expect(keyShape.attr('stroke')).toEqual('rgb(150, 150, 150)');
expect(keyShape.attr('stroke')).toEqual('rgb(224, 224, 224)');
});
graph.on('edge:mouseleave', (e) => {
const item = e.item;
@ -401,7 +401,7 @@ describe('graph edge states', () => {
expect(edge.hasState('state2')).toEqual(false);
const keyShape = edge.getKeyShape();
expect(keyShape.attr('lineWidth')).toEqual(1);
expect(keyShape.attr('stroke')).toEqual('rgb(150, 150, 150)');
expect(keyShape.attr('stroke')).toEqual('rgb(224, 224, 224)');
});
});
graph.emit('edge:mouseenter', { item: edge });