Skip to content

Commit

Permalink
feat(interaction/link-by-color): element-link 交互反馈增加参数配置 (#3483)
Browse files Browse the repository at this point in the history
* feat(interaction/link-by-color): element-link 交互反馈增加参数配置

- [x] test cases

* fix: 修复 lint 问题
  • Loading branch information
visiky committed Jun 21, 2021
1 parent 5b3535a commit 3ddbbd3
Show file tree
Hide file tree
Showing 3 changed files with 145 additions and 12 deletions.
45 changes: 33 additions & 12 deletions src/interaction/action/element/link-by-color.ts
@@ -1,13 +1,16 @@
import Action from '../base';
import { getCurrentElement, getElementValue, getElementsByField } from '../util';
import Element from '../../../geometry/element/';
import { each } from '@antv/util';
import { deepMix, each, isFunction } from '@antv/util';
import { LooseObject } from '../../../interface';
import { IGroup } from '../../../dependents';
import { IGroup, ShapeAttrs } from '../../../dependents';

type LinkActiveStyle = ShapeAttrs | ((style: ShapeAttrs, Element: Element) => ShapeAttrs);

/**
* Link Elements by color
* @ignore
*
* public 方法是对外可用的反馈交互。使用方式,如:element-link-by-color:link, element-link-by-color:unlink, element-link-by-color:clear
*/
class LinkByColor extends Action {
private linkGroup: IGroup;
Expand Down Expand Up @@ -45,18 +48,21 @@ class LinkByColor extends Action {
return path;
}
// 添加连接的图形
private addLinkShape(group, element: Element, nextElement: Element) {
private addLinkShape(group: IGroup, element: Element, nextElement: Element, activeStyle?: LinkActiveStyle) {
const style = {
opacity: 0.4,
fill: element.shape.attr('fill'),
};
group.addShape({
type: 'path',
attrs: {
opacity: 0.4,
fill: element.shape.attr('fill'),
...deepMix({}, style, isFunction(activeStyle) ? activeStyle(style, element) : activeStyle),
path: this.getLinkPath(element, nextElement),
},
});
}
// 使用图形连接
private linkByElement(element: Element) {
private linkByElement(element: Element, activeStyle?: LinkActiveStyle) {
const view = this.context.view;
const scale = this.getColorScale(view, element);
if (!scale) {
Expand All @@ -72,7 +78,7 @@ class LinkByColor extends Action {
each(elements, (el, index) => {
if (index < count - 1) {
const nextEl = elements[index + 1];
this.addLinkShape(group, el, nextEl);
this.addLinkShape(group, el, nextEl, activeStyle);
}
});
}
Expand All @@ -92,25 +98,40 @@ class LinkByColor extends Action {

/**
* 连接 elements
*
* @usage
* registerInteraction('xxx', {
* start: [
* {
* trigger: 'interval:mouseenter',
* action: 'element-link-by-color:link',
* arg: {
* // style: { fill: 'red' }
* style: (style, element) => ({ fill: 'red' })
* },
* },
* ],
* });
*/
public link() {
public link(args?: { style: LinkActiveStyle }) {
const context = this.context;
if (!this.linkGroup) {
// 不允许被拾取
this.linkGroup = context.view.foregroundGroup.addGroup({
id: 'link-by-color-group',
capture: false,
});
}
const element = getCurrentElement(context);
if (element) {
this.linkByElement(element);
this.linkByElement(element, args?.style);
}
}

/**
* 取消连接 elements
*/
unlink() {
public unlink() {
const element = getCurrentElement(this.context);
if (element) {
this.removeLink(element);
Expand All @@ -120,7 +141,7 @@ class LinkByColor extends Action {
/**
* 清除所有连接
*/
clear() {
public clear() {
if (this.linkGroup) {
this.linkGroup.clear();
}
Expand Down
25 changes: 25 additions & 0 deletions tests/unit/interaction/action/link-by-color-spec.ts
Expand Up @@ -71,12 +71,37 @@ describe('list highlight test', () => {
expect(linkGroup.getCount()).toBe(2);
});

it('custom link active-style', () => {
context.event = {};
link.unlink();
link.clear(); // 事先调用,保证不出错
context.event = {
target: elements[0].shape,
};
link.link();
//@ts-ignore
linkGroup = link.linkGroup;
expect(linkGroup.getCount()).toBe(1);
// @ts-ignore
expect(linkGroup.getChildren()[0].getChildren()[0].attr('fill')).toBe(elements[0].shape.attr('fill'));

link.unlink();
link.clear(); // 事先调用,保证不出错
context.event = {
target: elements[0].shape,
};
link.link({ style: { fill: 'red' } });
// @ts-ignore
expect(linkGroup.getChildren()[0].getChildren()[0].attr('fill')).toBe('red');
});

it('clear', () => {
link.clear();
expect(linkGroup.getCount()).toBe(0);
// @ts-ignore
expect(link.cache).toBeEmpty();
});

it('link null', () => {
context.event = {
target: null,
Expand Down
87 changes: 87 additions & 0 deletions tests/unit/interaction/element-link-spec.ts
@@ -0,0 +1,87 @@
import { Chart, registerInteraction } from '../../../src/index';
import { createDiv } from '../../util/dom';

registerInteraction('element-link', {
start: [{ trigger: 'element:mouseenter', action: 'element-link-by-color:link', arg: { style: { fill: 'red' } } }],
end: [{ trigger: 'element:mouseleave', action: 'element-link-by-color:unlink' }],
});

describe('test element interaction', () => {
const chart = new Chart({
container: createDiv(),
width: 400,
height: 400,
autoFit: false,
});

chart.data([
{ year: '2014', type: 'Sales', sales: 1000 },
{ year: '2015', type: 'Sales', sales: 1170 },
{ year: '2016', type: 'Sales', sales: 660 },
{ year: '2017', type: 'Sales', sales: 1030 },
{ year: '2014', type: 'Expenses', sales: 400 },
{ year: '2015', type: 'Expenses', sales: 460 },
{ year: '2016', type: 'Expenses', sales: 1120 },
{ year: '2017', type: 'Expenses', sales: 540 },
{ year: '2014', type: 'Profit', sales: 300 },
{ year: '2015', type: 'Profit', sales: 300 },
{ year: '2016', type: 'Profit', sales: 300 },
{ year: '2017', type: 'Profit', sales: 350 },
]);
chart.animate(true);
chart.tooltip(false);
chart.interval().position('year*sales').color('type').adjust('stack');
chart.interaction('element-link');

chart.render();
const elements = chart.geometries[0].elements;
const first = elements[0];

let linkGroup;

it('active', () => {
chart.emit('element:mouseenter', {
target: first.shape,
});

linkGroup = chart.foregroundGroup.findById('link-by-color-group');
expect(linkGroup).not.toBeNull();
expect(linkGroup.getCount()).toBe(1);

expect(linkGroup.getChildren()[0].getChildren()[0].attr('fill')).toBe('red');
chart.emit('element:mouseleave', {
target: first.shape,
});
expect(linkGroup.getCount()).toBe(0);
});

it('modify', () => {
chart.interaction('element-link', {
start: [
{ trigger: 'element:mouseenter', action: 'element-link-by-color:link', arg: { style: { fill: 'yellow' } } },
],
});
chart.emit('element:mouseenter', {
target: first.shape,
});
linkGroup = chart.foregroundGroup.findById('link-by-color-group');
expect(linkGroup.getChildren()[0].getChildren()[0].attr('fill')).toBe('yellow');
chart.emit('element:mouseleave', {
target: first.shape,
});
expect(linkGroup.getCount()).toBe(0);
});

it('remove interaction', () => {
chart.removeInteraction('element-link');
chart.emit('element:mouseenter', {
target: first.shape,
});

linkGroup = chart.foregroundGroup.findById('link-by-color-group');
expect(linkGroup).toBeNull();
});
afterAll(() => {
chart.destroy();
});
});

0 comments on commit 3ddbbd3

Please sign in to comment.