-
Notifications
You must be signed in to change notification settings - Fork 607
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix(interaction): 添加 venn图 selected 和 active 的交互 (#2871)
* fix(interaction): 添加venn图的selected和active的交互 * test(venn): 添加 venn 图交互的单测和文档 * refactor(venn): 规范 venn interaction 的写法 Co-authored-by: 酥云 <[email protected]>
- Loading branch information
Showing
8 changed files
with
298 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,151 @@ | ||
import { IGroup } from '@antv/g-base'; | ||
import InteractionContext from '@antv/g2/lib/interaction/context'; | ||
import { Venn } from '../../../../src'; | ||
import { VennElementActive, VennElementSelected } from '../../../../src/plots/venn/interaction/action'; | ||
import { createDiv } from '../../../utils/dom'; | ||
|
||
describe('venn', () => { | ||
const data = [ | ||
{ sets: ['A'], size: 12, label: 'A' }, | ||
{ sets: ['B'], size: 12, label: 'B' }, | ||
{ sets: ['A', 'B'], size: 2, label: 'A&B' }, | ||
]; | ||
|
||
const plot = new Venn(createDiv(), { | ||
data, | ||
width: 400, | ||
height: 500, | ||
setsField: 'sets', | ||
sizeField: 'size', | ||
legend: false, | ||
pointStyle: { | ||
lineWidth: 0, | ||
stroke: 'black', | ||
}, | ||
}); | ||
plot.render(); | ||
|
||
it('venn: active', () => { | ||
plot.update({ | ||
state: { | ||
active: { | ||
style: { | ||
lineWidth: 1, | ||
}, | ||
}, | ||
}, | ||
interactions: [{ type: 'venn-element-active', enable: true }], | ||
}); | ||
|
||
const context = new InteractionContext(plot.chart); | ||
const vennElementActive = new VennElementActive(context); | ||
|
||
// 模拟 active | ||
context.event = { | ||
data: { | ||
data: plot.chart.getData()[0], | ||
}, | ||
}; | ||
vennElementActive.active(); | ||
|
||
const elements = plot.chart.geometries[0].elements; | ||
|
||
expect(plot.getStates().length).toBe(1); | ||
expect(plot.getStates()[0].state).toBe('active'); | ||
expect(elements[0].getStates()[0]).toBe('active'); | ||
expect((elements[0].shape as IGroup).getChildren()[0].attr('lineWidth')).toBe(1); | ||
|
||
vennElementActive.reset(); | ||
expect(plot.getStates().length).toBe(0); | ||
|
||
// 模拟 第二次 active | ||
context.event = { | ||
data: { | ||
data: plot.chart.getData()[1], | ||
}, | ||
}; | ||
vennElementActive.active(); | ||
|
||
expect(plot.getStates().length).toBe(1); | ||
expect(plot.getStates()[0].state).toBe('active'); | ||
// 第一个元素 样式恢复 | ||
expect(elements[0].getStates()[0]).toBeUndefined(); | ||
expect((elements[0].shape as IGroup).getChildren()[0].attr('lineWidth')).toBe(0); | ||
|
||
// 第二个元素 有样式 | ||
expect(elements[1].getStates()[0]).toBe('active'); | ||
expect((elements[1].shape as IGroup).getChildren()[0].attr('lineWidth')).toBe(1); | ||
|
||
vennElementActive.reset(); | ||
expect(plot.getStates().length).toBe(0); | ||
|
||
vennElementActive.destroy(); | ||
}); | ||
|
||
it('venn: selected', () => { | ||
plot.update({ | ||
state: { | ||
selected: { | ||
style: { | ||
lineWidth: 2, | ||
}, | ||
}, | ||
}, | ||
interactions: [ | ||
{ type: 'venn-element-active', enable: false }, | ||
{ type: 'venn-element-selected', enable: true }, | ||
], | ||
}); | ||
|
||
const context = new InteractionContext(plot.chart); | ||
const vennElementSelected = new VennElementSelected(context); | ||
|
||
// 模拟 selected | ||
context.event = { | ||
data: { | ||
data: plot.chart.getData()[0], | ||
}, | ||
}; | ||
vennElementSelected.toggle(); | ||
|
||
const elements = plot.chart.geometries[0].elements; | ||
|
||
// 第一个元素 点击 有样式 | ||
expect(plot.getStates().length).toBe(1); | ||
expect(plot.getStates()[0].state).toBe('selected'); | ||
expect(elements[0].getStates()[0]).toBe('selected'); | ||
expect((elements[0].shape as IGroup).getChildren()[0].attr('lineWidth')).toBe(2); | ||
|
||
// 再次点击 取消 selected | ||
vennElementSelected.toggle(); | ||
expect(plot.getStates().length).toBe(0); | ||
expect(elements[0].getStates()[0]).toBeUndefined(); | ||
expect((elements[0].shape as IGroup).getChildren()[0].attr('lineWidth')).toBe(0); | ||
|
||
// 模拟第二个元素的 selected | ||
context.event = { | ||
data: { | ||
data: plot.chart.getData()[1], | ||
}, | ||
}; | ||
vennElementSelected.toggle(); | ||
|
||
expect(plot.getStates().length).toBe(1); | ||
expect(plot.getStates()[0].state).toBe('selected'); | ||
expect(elements[1].getStates()[0]).toBe('selected'); | ||
expect((elements[1].shape as IGroup).getChildren()[0].attr('lineWidth')).toBe(2); | ||
|
||
// 所有元素的 selected state 为 false | ||
vennElementSelected.reset(); | ||
expect(plot.getStates().length).toBe(0); | ||
expect(elements[0].getStates().length).toBe(0); | ||
expect(elements[1].getStates().length).toBe(0); | ||
expect(elements[2].getStates().length).toBe(0); | ||
|
||
vennElementSelected.destroy(); | ||
}); | ||
|
||
afterAll(() => { | ||
plot.destroy(); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
import { Venn } from '@antv/g2plot'; | ||
|
||
const plot = new Venn('container', { | ||
data: [ | ||
{ sets: ['A'], size: 12, label: 'A' }, | ||
{ sets: ['B'], size: 12, label: 'B' }, | ||
{ sets: ['C'], size: 12, label: 'C' }, | ||
{ sets: ['A', 'B'], size: 2, label: 'A&B' }, | ||
{ sets: ['A', 'C'], size: 2, label: 'A&C' }, | ||
{ sets: ['B', 'C'], size: 2, label: 'B&C' }, | ||
{ sets: ['A', 'B', 'C'], size: 1 }, | ||
], | ||
setsField: 'sets', | ||
sizeField: 'size', | ||
pointStyle: { fillOpacity: 0.8 }, | ||
padding: [0, 10], | ||
state: { | ||
active: { | ||
style: { | ||
fillOpacity: 1, | ||
stroke: 'black', | ||
lineWidth: 1, | ||
}, | ||
}, | ||
selected: { | ||
style: { | ||
stroke: 'black', | ||
lineWidth: 2, | ||
}, | ||
}, | ||
}, | ||
interactions: [ | ||
{ type: 'venn-element-active', enable: true }, | ||
{ type: 'venn-element-selected', enable: true }, | ||
], | ||
}); | ||
plot.render(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
import { InteractionAction } from '@antv/g2'; | ||
|
||
class VennElementState extends InteractionAction { | ||
/** tofront: 同步所有元素的位置 */ | ||
protected syncElementsPos() { | ||
const elements = this.context.view.geometries[0].elements; | ||
elements.forEach((elem) => { | ||
elem.shape.toFront(); | ||
}); | ||
} | ||
} | ||
|
||
export class VennElementActive extends VennElementState { | ||
/** hover */ | ||
public active() { | ||
const { data } = this.context.event.data; | ||
const elements = this.context.view.geometries[0].elements; | ||
|
||
elements.forEach((elem) => { | ||
const activeState = data === elem.getData(); | ||
elem.setState('active', activeState); | ||
}); | ||
// tofront: 同步所有元素的位置 | ||
this.syncElementsPos(); | ||
} | ||
|
||
/** 重置 */ | ||
public reset() { | ||
const elements = this.context.view.geometries[0].elements; | ||
|
||
elements.forEach((elem) => { | ||
// 所有元素的 state 统一 false | ||
elem.setState('active', false); | ||
}); | ||
// tofront: 同步所有元素的位置 | ||
this.syncElementsPos(); | ||
} | ||
} | ||
|
||
export class VennElementSelected extends VennElementState { | ||
/** 切换 */ | ||
public toggle() { | ||
const { data } = this.context.event.data; | ||
const elements = this.context.view.geometries[0].elements; | ||
|
||
elements.forEach((elem) => { | ||
if (data === elem.getData()) { | ||
const selectedState = elem.getStates().includes('selected'); | ||
elem.setState('selected', !selectedState); | ||
} | ||
}); | ||
// tofront: 同步所有元素的位置 | ||
this.syncElementsPos(); | ||
} | ||
|
||
/** 重置 */ | ||
public reset() { | ||
const elements = this.context.view.geometries[0].elements; | ||
|
||
elements.forEach((elem) => { | ||
// 所有元素的 state 统一 false | ||
elem.setState('selected', false); | ||
}); | ||
// tofront: 同步所有元素的位置 | ||
this.syncElementsPos(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
import { registerInteraction, registerAction } from '@antv/g2'; | ||
import { VennElementActive, VennElementSelected } from './action'; | ||
|
||
registerAction('venn-element-active', VennElementActive); | ||
registerAction('venn-element-selected', VennElementSelected); | ||
|
||
// 移动到 venn elment 上的 active | ||
registerInteraction('venn-element-active', { | ||
start: [{ trigger: 'element:mouseenter', action: 'venn-element-active:active' }], | ||
end: [{ trigger: 'element:mouseleave', action: 'venn-element-active:reset' }], | ||
}); | ||
|
||
// 点击 venn element (可多选) | ||
registerInteraction('venn-element-selected', { | ||
start: [{ trigger: 'element:click', action: 'venn-element-selected:toggle' }], | ||
rollback: [{ trigger: 'dblclick', action: ['venn-element-selected:reset'] }], | ||
}); |