feat: basic style(light version) for edges and combos

This commit is contained in:
Yanyan-Wang 2020-11-11 15:28:43 +08:00 committed by Yanyan Wang
parent 7f2a28dd19
commit 93973b80dc
17 changed files with 244 additions and 78 deletions

View File

@ -33,34 +33,34 @@ const graph = new G6.Graph({
fitCenter: true,
// Set groupByTypes to false to get rendering result with reasonable visual zIndex for combos
groupByTypes: false,
defaultCombo: {
type: 'circle',
style: {
lineWidth: 1,
},
labelCfg: {
refY: 10,
position: 'top',
style: {
fontSize: 18,
},
},
},
modes: {
default: ['drag-canvas', 'drag-node', 'drag-combo', 'collapse-expand-combo'],
},
comboStateStyles: {
// the style configurations for the hover state on the combo
hover: {
lineWidth: 3,
},
},
nodeStateStyles: {
// the hover configurations for the hover state on the node
hover: {
lineWidth: 3,
defaultCombo: {
type: 'circle',
/* style for the keyShape */
// style: {
// lineWidth: 1,
// },
labelCfg: {
/* label's offset to the keyShape */
// refY: 10,
/* label's position, options: center, top, bottom, left, right */
position: 'top',
/* label's style */
// style: {
// fontSize: 18,
// },
},
},
/* styles for different states, there are built-in styles for states: active, inactive, selected, highlight, disable */
/* you can extend it or override it as you want */
// comboStateStyles: {
// active: {
// fill: '#f00',
// opacity: 0.5
// },
// },
});
graph.data(data);
@ -68,10 +68,19 @@ graph.render();
graph.on('combo:mouseenter', (evt) => {
const { item } = evt;
graph.setItemState(item, 'hover', true);
graph.setItemState(item, 'active', true);
});
graph.on('combo:mouseleave', (evt) => {
const { item } = evt;
graph.setItemState(item, 'hover', false);
graph.setItemState(item, 'active', false);
});
graph.on('combo:click', (evt) => {
const { item } = evt;
graph.setItemState(item, 'selected', true);
});
graph.on('canvas:click', (evt) => {
graph.getCombos().forEach(combo => {
graph.clearItemStates(combo);
});
});

View File

@ -33,35 +33,36 @@ const graph = new G6.Graph({
fitCenter: true,
// Set groupByTypes to false to get rendering result with reasonable visual zIndex for combos
groupByTypes: false,
defaultCombo: {
type: 'rect',
size: [50, 50], // Combo 的最小大小
style: {
lineWidth: 1,
},
labelCfg: {
refY: 10,
position: 'top',
style: {
fontSize: 18,
},
},
},
modes: {
default: ['drag-canvas', 'drag-node', 'drag-combo', 'collapse-expand-combo'],
},
comboStateStyles: {
// the style configurations for the hover state on the combo
hover: {
lineWidth: 3,
},
},
nodeStateStyles: {
// the hover configurations for the hover state on the node
hover: {
lineWidth: 3,
defaultCombo: {
type: 'rect',
/* The minimum size of the combo. combo 最小大小 */
size: [50, 50],
/* style for the keyShape */
// style: {
// lineWidth: 1,
// },
labelCfg: {
/* label's offset to the keyShape */
// refY: 10,
/* label's position, options: center, top, bottom, left, right */
position: 'top',
/* label's style */
// style: {
// fontSize: 18,
// },
},
},
/* styles for different states, there are built-in styles for states: active, inactive, selected, highlight, disable */
/* you can extend it or override it as you want */
// comboStateStyles: {
// active: {
// fill: '#f00',
// opacity: 0.5
// },
// },
});
graph.data(data);
@ -69,10 +70,19 @@ graph.render();
graph.on('combo:mouseenter', (evt) => {
const { item } = evt;
graph.setItemState(item, 'hover', true);
graph.setItemState(item, 'active', true);
});
graph.on('combo:mouseleave', (evt) => {
const { item } = evt;
graph.setItemState(item, 'hover', false);
graph.setItemState(item, 'active', false);
});
graph.on('combo:click', (evt) => {
const { item } = evt;
graph.setItemState(item, 'selected', true);
});
graph.on('canvas:click', (evt) => {
graph.getCombos().forEach(combo => {
graph.clearItemStates(combo);
});
});

View File

@ -1,4 +1,4 @@
// window.g6 = require('./src/index.ts'); // import the source for debugging
window.g6 = require('./dist/g6.min.js'); // import the package for webworker
window.g6 = require('./src/index.ts'); // import the source for debugging
// window.g6 = require('./dist/g6.min.js'); // import the package for webworker
window.insertCss = require('insert-css');
window.Chart = require('@antv/chart-node-g6');

View File

@ -72,9 +72,6 @@ export default {
fill: colorSet.inactiveFill,
stroke: colorSet.inactiveStroke,
lineWidth: 1,
'text-shape': {
fontWeight: 500
}
},
disable: {
fill: colorSet.disableFill,
@ -87,21 +84,55 @@ export default {
fill: textColor,
textAlign: 'center',
textBaseline: 'middle',
fontSize: 12,
},
},
defaultEdge: {
type: 'line',
style: {
stroke: disableColor,
stroke: colorSet.edgeMainStroke,
lineAppendWidth: 4,
},
size: 1,
color: disableColor,
color: colorSet.edgeMainStroke,
},
// 边应用状态后的样式,默认仅提供 active、selected、highlight、inactive、disable用户可以自己扩展
edgeStateStyles: {
active: {
stroke: colorSet.edgeActiveStroke,
lineWidth: 1,
},
selected: {
stroke: colorSet.edgeSelectedStroke,
lineWidth: 2,
shadowColor: colorSet.edgeSelectedStroke,
shadowBlur: 10,
'text-shape': {
fontWeight: 500
},
},
highlight: {
stroke: colorSet.edgeHighlightStroke,
lineWidth: 2,
'text-shape': {
fontWeight: 500
}
},
inactive: {
stroke: colorSet.edgeInactiveStroke,
lineWidth: 1,
},
disable: {
stroke: colorSet.edgeDisableStroke,
lineWidth: 1,
},
},
comboLabel: {
style: {
fill: textColor,
// textAlign: 'center',
textBaseline: 'middle',
fontSize: 12,
},
refY: 10, // Combo 的默认文本不居中时的偏移量
refX: 10, // Combo 的默认文本不居中时的偏移量
@ -109,18 +140,53 @@ export default {
defaultCombo: {
type: 'circle',
style: {
fill: '#F3F9FF',
fill: colorSet.comboMainFill,
lineWidth: 1,
stroke: '#A3B1BF',
opacity: 0.8,
stroke: colorSet.comboMainStroke,
r: 5,
width: 20,
height: 10,
},
size: [20, 5],
color: '#A3B1BF',
color: colorSet.comboMainStroke,
padding: [25, 20, 15, 20],
},
// combo 应用状态后的样式,默认仅提供 active、selected、highlight、inactive、disable用户可以自己扩展
comboStateStyles: {
active: {
stroke: colorSet.comboActiveStroke,
lineWidth: 1,
fill: colorSet.comboActiveFill,
},
selected: {
stroke: colorSet.comboSelectedStroke,
lineWidth: 2,
fill: colorSet.comboSelectedFill,
shadowColor: colorSet.comboSelectedStroke,
shadowBlur: 10,
'text-shape': {
fontWeight: 500
},
},
highlight: {
stroke: colorSet.comboHighlightStroke,
lineWidth: 2,
fill: colorSet.comboHighlightFill,
'text-shape': {
fontWeight: 500
}
},
inactive: {
stroke: colorSet.comboInactiveStroke,
fill: colorSet.comboInactiveFill,
lineWidth: 1,
},
disable: {
stroke: colorSet.comboDisableStroke,
fill: colorSet.comboDisableFill,
lineWidth: 1,
},
},
delegateStyle: {
fill: '#F3F9FF',
fillOpacity: 0.5,

View File

@ -24,7 +24,7 @@ export default class Combo extends Node implements ICombo {
public getShapeCfg(model: ComboConfig): ComboConfig {
const styles = this.get('styles');
const bbox = this.get('bbox');
if (styles) {
if (styles && bbox) {
// merge graph的item样式与数据模型中的样式
const newModel = model;
const size = {

View File

@ -101,8 +101,10 @@ export default class ItemBase implements IItemBase {
const model = this.get('model');
let { id } = model;
const itemType = this.get('type');
if (!id) {
id = uniqueId(this.get('type'));
id = uniqueId(itemType);
this.get('model').id = id;
}
@ -117,7 +119,7 @@ export default class ItemBase implements IItemBase {
this.init();
this.draw();
const shapeType = (model.shape as string) || (model.type as string) || 'circle';
const shapeType = (model.shape as string) || (model.type as string) || (itemType === 'edge' ? 'line' : 'circle');
const shapeFactory = this.get('shapeFactory');
if (shapeFactory && shapeFactory[shapeType]) {
const { options } = shapeFactory[shapeType];
@ -384,7 +386,6 @@ export default class ItemBase implements IItemBase {
public setState(state: string, value: string | boolean) {
const states: string[] = this.get('states');
const shapeFactory = this.get('shapeFactory');
// debugger
let stateName = state;
let filterStateName = state;
if (isString(value)) {

View File

@ -27,6 +27,23 @@ const singleCombo: ShapeOptions = {
*/
refX: Global.comboLabel.refX,
refY: Global.comboLabel.refY,
options: {
style: {
stroke: Global.defaultCombo.style.stroke,
fill: Global.defaultCombo.style.fill,
lineWidth: Global.defaultCombo.style.lineWidth
},
labelCfg: {
style: {
fill: Global.comboLabel.style.fill,
fontSize: Global.comboLabel.style.fontSize,
},
},
stateStyles: {
...Global.comboStateStyles
}
},
/**
* Combo
* @internal Combo [width, height]

View File

@ -19,15 +19,18 @@ Shape.registerCombo(
stroke: Global.defaultCombo.style.stroke,
fill: Global.defaultCombo.style.fill,
lineWidth: Global.defaultCombo.style.lineWidth,
opacity: 0.8,
},
labelCfg: {
style: {
fill: '#595959',
fill: Global.comboLabel.style.fill,
fontSize: Global.comboLabel.style.fontSize,
},
refX: 0,
refY: 0,
},
stateStyles: {
...Global.comboStateStyles
}
},
shapeType: 'circle',
// 文本位置

View File

@ -18,13 +18,13 @@ Shape.registerCombo(
radius: 0,
stroke: Global.defaultCombo.style.stroke,
fill: Global.defaultCombo.style.fill,
lineWidth: Global.defaultCombo.style.lineWidth,
fillOpacity: 1,
lineWidth: Global.defaultCombo.style.lineWidth
},
// 文本样式配置
labelCfg: {
style: {
fill: '#595959',
fill: Global.comboLabel.style.fill,
fontSize: Global.comboLabel.style.fontSize,
},
},
// 连接点,默认为左右
@ -32,6 +32,9 @@ Shape.registerCombo(
[0, 0.5],
[1, 0.5],
],
stateStyles: {
...Global.comboStateStyles
}
},
shapeType: 'rect',
labelPosition: 'top',

View File

@ -55,6 +55,26 @@ const singleEdge: ShapeOptions = {
* @type {Boolean}
*/
labelAutoRotate: false,
// 自定义边时的配置
options: {
size: Global.defaultEdge.size,
style: {
x: 0,
y: 0,
stroke: Global.defaultEdge.style.stroke,
lineWidth: Global.defaultEdge.style.lineWidth
},
labelCfg: {
style: {
fill: Global.edgeLabel.style.fill,
fontSize: Global.edgeLabel.style.fontSize,
},
},
stateStyles: {
...Global.edgeStateStyles
}
},
/**
* path
* @internal

View File

@ -15,16 +15,20 @@ Shape.registerEdge(
{
options: {
color: Global.defaultEdge.color,
size: Global.defaultEdge.size,
style: {
radius: 0,
offset: 15,
x: 0,
y: 0,
stroke: Global.defaultEdge.style.stroke,
lineWidth: Global.defaultEdge.style.lineWidth
},
// 文本样式配置
labelCfg: {
style: {
fill: Global.edgeLabel.style.fill,
fontSize: Global.edgeLabel.style.fontSize,
},
},
routeCfg: {
@ -33,6 +37,9 @@ Shape.registerEdge(
maximumLoops: 1000,
gridSize: 10, // 指定精度
},
stateStyles: {
...Global.edgeStateStyles
}
},
shapeType: 'polyline',
// 文本位置

View File

@ -41,6 +41,34 @@ export const getColorsWithSubjectColor = (subjectColor, backColor = '#fff', disa
highlightFill: mixColor(backColor, subjectColor, 0.2).rgb().toString(),
disableStroke: mixColor(backColor, disableColor, 0.3).rgb().toString(),
disableFill: mixColor(backColor, disableColor, 0.05).rgb().toString()
disableFill: mixColor(backColor, disableColor, 0.05).rgb().toString(),
edgeMainStroke: disableColor,
edgeActiveStroke: subjectColor,
edgeInactiveStroke: mixColor(backColor, disableColor, 0.2).rgb().toString(),
edgeSelectedStroke: subjectColor,
edgeHighlightStroke: subjectColor,
edgeDisableStroke: mixColor(backColor, disableColor, 0.1).rgb().toString(),
comboMainStroke: mixColor(backColor, disableColor, 0.3).rgb().toString(),
comboMainFill: mixColor(backColor, disableColor, 0.02).rgb().toString(),
comboActiveStroke: subjectColor,
comboActiveFill: lightSubject,
comboInactiveStroke: mixColor(backColor, disableColor, 0.3).rgb().toString(),
comboInactiveFill: mixColor(backColor, disableColor, 0.02).rgb().toString(),
comboSelectedStroke: subjectColor,
comboSelectedFill: mixColor(backColor, disableColor, 0.02).rgb().toString(),
comboHighlightStroke: 'rgb(53, 119, 222)', // TODO: how to generate it ???
comboHighlightFill: mixColor(backColor, disableColor, 0.02).rgb().toString(),
comboDisableStroke: mixColor(backColor, disableColor, 0.2).rgb().toString(),
comboDisableFill: mixColor(backColor, disableColor, 0.05).rgb().toString(),
}
}

View File

@ -51,7 +51,7 @@ describe('graph state controller', () => {
setTimeout(() => {
expect(graphCount).toBe(1);
done();
}, 16);
}, 100);
});
it('state with activate-relations', done => {

View File

@ -1208,12 +1208,12 @@ describe('mapper fn', () => {
expect(keyShape.attr('fillOpacity')).toEqual(1);
graph.setItemState(edge, 'selected', true);
expect(keyShape.attr('stroke')).toEqual('rgb(150, 150, 150)');
expect(keyShape.attr('stroke')).toEqual('rgb(95, 149, 255)');
expect(keyShape.attr('lineWidth')).toEqual(2);
expect(keyShape.attr('fillOpacity')).toEqual(1);
graph.setItemState(edge, 'custom', true);
expect(keyShape.attr('stroke')).toEqual('rgb(150, 150, 150)');
expect(keyShape.attr('stroke')).toEqual('rgb(95, 149, 255)');
expect(keyShape.attr('lineWidth')).toEqual(2);
expect(keyShape.attr('opacity')).toEqual(0.5);
});

View File

@ -1290,7 +1290,7 @@ describe('behaviors', () => {
expect(unrelativeNodeKeyShape.attr('opacity')).toBe(0.1);
const unrelativeEdge = graph.getEdges()[1];
const unrelativeEdgeKeyShape = unrelativeEdge.get('group').get('children')[0];
expect(unrelativeEdgeKeyShape.attr('stroke')).toBe('rgb(150, 150, 150)');
expect(unrelativeEdgeKeyShape.attr('stroke')).toBe('rgb(234, 234, 234)');
expect(unrelativeEdgeKeyShape.attr('opacity')).toBe(0.1);
graph.emit('node:mouseleave', { item });

View File

@ -523,12 +523,13 @@ describe('shape edge test', () => {
const edge = graph.getEdges()[0];
const path = edge.get('group').get('children')[0];
let bbox = path.getBBox();
expect(bbox.minX).toEqual(91.60845891791658);
console.log(bbox);
expect(bbox.minX).toEqual(89.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(191.6084589179166);
expect(bbox.minX).toEqual(189.6084589179166);
});
it('clear', () => {

View File

@ -141,6 +141,7 @@ describe('graph edge states', () => {
shadowBlur: 10,
shadowOffsetX: 10,
shadowOffsetY: 20,
lineWidth: 10
},
},
defaultEdge: {