Selection UI, Ref. #16

This commit is contained in:
ziajka 2018-03-13 13:03:27 +01:00
parent 7589c46285
commit ca1a6ad6cd
6 changed files with 80 additions and 34 deletions

View File

@ -2,7 +2,4 @@ svg {
display: block; display: block;
} }
image.over {
fill: #000;
}

View File

@ -0,0 +1,5 @@
import {SVGSelection} from "../../map/models/types";
export interface Tool {
connect(selection: SVGSelection);
}

View File

@ -1,35 +1,45 @@
import {SVGSelection} from "../../../map/models/types"; import {SVGSelection} from "../../../map/models/types";
import {mouse, select} from "d3-selection"; import {mouse, select} from "d3-selection";
import {Context} from "../../../map/models/context";
export class SelectionTool { export class SelectionTool {
private selection: SVGSelection; private selection: SVGSelection;
private path; private path;
public connect(selection: SVGSelection) { public connect(selection: SVGSelection, context: Context) {
const self = this; const self = this;
this.selection = selection; this.selection = selection;
const canvas = this.selection.select<SVGGElement>("g.canvas"); const canvas = this.selection.select<SVGGElement>("g.canvas");
if (!canvas.select<SVGGElement>("g.selection-tool").node()) { if (!canvas.select<SVGGElement>("g.selection-line-tool").node()) {
const g = canvas.append<SVGGElement>('g'); const g = canvas.append<SVGGElement>('g');
g.attr("class", "selection-line-tool"); g.attr("class", "selection-line-tool");
this.path = g.append("path"); this.path = g.append("path");
this.path.attr("class", "selection").attr("visibility", "hidden"); this.path
.attr("class", "selection")
.attr("visibility", "hidden");
} }
const transformation = (p) => {
const transformation_point = context.getZeroZeroTransformationPoint();
return [p[0] - transformation_point.x, p[1] - transformation_point.y];
};
selection.on("mousedown", function() { selection.on("mousedown", function() {
const subject = select(window); const subject = select(window);
const parent = this.parentNode; const parent = this.parentElement;
const start = mouse(parent); const start = transformation(mouse(parent));
self.startSelection(start); self.startSelection(start);
subject
.on("mousemove.selection", function() { subject
self.moveSelection(start, mouse(parent)); .on("mousemove.selection", function() {
}).on("mouseup.selection", function() { self.moveSelection(start, transformation(mouse(parent)));
self.endSelection(start, mouse(parent)); }).on("mouseup.selection", function() {
subject.on("mousemove.selection", null).on("mouseup.selection", null); self.endSelection(start, transformation(mouse(parent)));
}); subject.on("mousemove.selection", null).on("mouseup.selection", null);
});
}); });
} }
@ -38,14 +48,20 @@ export class SelectionTool {
} }
private startSelection(start) { private startSelection(start) {
this.path
.attr("d", this.rect(start[0], start[1], 0, 0))
.attr("visibility", "visible");
} }
private moveSelection(start, move) { private moveSelection(start, move) {
this.path.attr("d", this.rect(start[0], start[1], move[0] - start[0], move[1] - start[1]));
} }
private endSelection(start, end) { private endSelection(start, end) {
this.path.attr("visibility", "hidden");
}
private rect(x: number, y: number, w: number, h: number) {
return "M" + [x, y] + " l" + [w, 0] + " l" + [0, h] + " l" + [-w, 0] + "z";
} }
} }

View File

@ -11,6 +11,7 @@ import { Drawing } from "../models/drawing.model";
import { DrawingsWidget } from "./drawings.widget"; import { DrawingsWidget } from "./drawings.widget";
import { DrawingLineWidget } from "./drawing-line.widget"; import { DrawingLineWidget } from "./drawing-line.widget";
import {SelectionTool} from "../tools/selection-tool"; import {SelectionTool} from "../tools/selection-tool";
import {Tool} from "../tool";
export class GraphLayout implements Widget { export class GraphLayout implements Widget {
private nodes: Node[] = []; private nodes: Node[] = [];
@ -80,24 +81,25 @@ export class GraphLayout implements Widget {
this.nodesWidget.draw(canvas, this.nodes); this.nodesWidget.draw(canvas, this.nodes);
this.drawingsWidget.draw(canvas, this.drawings); this.drawingsWidget.draw(canvas, this.drawings);
this.drawingLineTool.connect(view);
this.selectionTool.connect(view);
const onZoom = function(this: SVGSVGElement) { // this.drawingLineTool.connect(view, context);
const e: D3ZoomEvent<SVGSVGElement, any> = event; this.selectionTool.connect(view, context);
if (self.centerZeroZeroPoint) {
canvas.attr(
'transform',
`translate(${context.getSize().width / 2 + e.transform.x}, ` +
`${context.getSize().height / 2 + e.transform.y}) scale(${e.transform.k})`);
} else {
canvas.attr('transform', e.transform.toString());
}
};
view.call(zoom<SVGSVGElement, any>() // const onZoom = function(this: SVGSVGElement) {
.scaleExtent([1 / 2, 8]) // const e: D3ZoomEvent<SVGSVGElement, any> = event;
.on('zoom', onZoom)); // if (self.centerZeroZeroPoint) {
// canvas.attr(
// 'transform',
// `translate(${context.getSize().width / 2 + e.transform.x}, ` +
// `${context.getSize().height / 2 + e.transform.y}) scale(${e.transform.k})`);
// } else {
// canvas.attr('transform', e.transform.toString());
// }
// };
//
// view.call(zoom<SVGSVGElement, any>()
// .scaleExtent([1 / 2, 8])
// .on('zoom', onZoom));
} }
} }

View File

@ -1,9 +1,11 @@
import {Size} from "../../cartography/shared/models/size.model"; import {Size} from "../../cartography/shared/models/size.model";
import {Selection} from "d3-selection"; import {Selection} from "d3-selection";
import {Point} from "../../cartography/shared/models/point.model";
export class Context { export class Context {
private size: Size; private size: Size;
private root: Selection<SVGSVGElement, any, null, undefined>; private root: Selection<SVGSVGElement, any, null, undefined>;
private centerZeroZeroPoint = true;
constructor(root: Selection<SVGSVGElement, any, null, undefined>) { constructor(root: Selection<SVGSVGElement, any, null, undefined>) {
this.root = root; this.root = root;
@ -16,4 +18,8 @@ export class Context {
public setSize(size: Size): void { public setSize(size: Size): void {
this.size = size; this.size = size;
} }
public getZeroZeroTransformationPoint() {
return new Point(this.getSize().width / 2., this.getSize().height / 2.);
}
} }

View File

@ -46,3 +46,23 @@ g.node text {
svg image:hover, svg image.chosen { svg image:hover, svg image.chosen {
filter: grayscale(100%); filter: grayscale(100%);
} }
.selection-line-tool .selection {
fill: #7ccbe1;
stroke: #66aec2 ;
fill-opacity: 0.3;
stroke-opacity: 0.7;
stroke-width: 1;
stroke-dasharray: 5, 5;
}
g.node text,
.noselect {
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}