Graphically select nodes

This commit is contained in:
ziajka 2018-03-15 15:19:50 +01:00
parent f7ec7ea7df
commit 3192ce4376
4 changed files with 60 additions and 6 deletions

View File

@ -2,6 +2,7 @@ import {SelectionTool} from "./selection-tool";
import {select} from "d3-selection";
import {Context} from "../../../map/models/context";
import {SVGSelection} from "../../../map/models/types";
import {Node} from "../models/node.model";
describe('SelectionTool', () => {
@ -19,6 +20,25 @@ describe('SelectionTool', () => {
.attr('width', 1000)
.attr('height', 1000);
const node_1 = new Node();
node_1.name = "Node 1";
node_1.x = 150;
node_1.y = 150;
const node_2 = new Node();
node_2.name = "Node 2";
node_2.x = 300;
node_2.y = 300;
svg.selectAll<SVGGElement, any>('g.node')
.data([node_1, node_2], (n: Node) => {
return n.node_id;
})
.enter()
.append<SVGGElement>('g')
.attr('class', 'node selectable');
svg.append<SVGGElement>('g').attr('class', 'canvas');
context = new Context();
@ -62,12 +82,30 @@ describe('SelectionTool', () => {
describe('SelectionTool can handle end of selection', () => {
beforeEach(() => {
svg.node().dispatchEvent(new MouseEvent('mousedown', {clientX: 100, clientY: 100}));
window.dispatchEvent(new MouseEvent('mousemove', {clientX: 300, clientY: 300}));
window.dispatchEvent(new MouseEvent('mouseup', {clientX: 300, clientY: 300}));
window.dispatchEvent(new MouseEvent('mousemove', {clientX: 200, clientY: 200}));
window.dispatchEvent(new MouseEvent('mouseup', {clientX: 200, clientY: 200}));
});
it('path should be hidden', () => {
expect(path_selection.attr('visibility')).toEqual('hidden');
expect(path_selection.attr('visibility')).toEqual('hidden');
});
it('node should be selected', () => {
expect(svg.selectAll('.selected').size()).toEqual(1);
expect(svg.select('.selected').datum().name).toEqual("Node 1");
});
});
describe('SelectionTool can handle end of selection in reverse direction', () => {
beforeEach(() => {
svg.node().dispatchEvent(new MouseEvent('mousedown', {clientX: 200, clientY: 200}));
window.dispatchEvent(new MouseEvent('mousemove', {clientX: 100, clientY: 100}));
window.dispatchEvent(new MouseEvent('mouseup', {clientX: 100, clientY: 100}));
});
it('node should be selected', () => {
expect()
expect(svg.select('.selected').datum().name).toEqual("Node 1");
});
});
@ -82,4 +120,5 @@ describe('SelectionTool', () => {
});
});
});

View File

@ -1,6 +1,8 @@
import {SVGSelection} from "../../../map/models/types";
import {mouse, select} from "d3-selection";
import {Context} from "../../../map/models/context";
import {Node} from "../models/node.model";
export class SelectionTool {
private selection: SVGSelection;
@ -30,7 +32,20 @@ export class SelectionTool {
subject
.on("mousemove.selection", function() {
self.moveSelection(start, transformation(mouse(parent)));
const end = transformation(mouse(parent));
self.moveSelection(start, end);
const x = Math.min(start[0], end[0]);
const y = Math.min(start[1], end[1]);
const width = Math.abs(start[0] - end[0]);
const height = Math.abs(start[1] - end[1]);
self.selection
.selectAll('.selectable')
.classed('selected', (node: Node, i) => {
return (x <= node.x && node.x < (x + width) && y <= node.y && node.y < (y + height));
});
}).on("mouseup.selection", function() {
self.endSelection(start, transformation(mouse(parent)));
subject

View File

@ -90,7 +90,7 @@ export class NodesWidget implements Widget {
const node_enter = node
.enter()
.append<SVGGElement>('g')
.attr('class', 'node');
.attr('class', 'node selectable');
node_enter
.append<SVGImageElement>('image')

View File

@ -43,7 +43,7 @@ g.node text {
}
svg image:hover, svg image.chosen {
svg image:hover, svg image.chosen, .selectable.selected {
filter: grayscale(100%);
}