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;
}
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 {mouse, select} from "d3-selection";
import {Context} from "../../../map/models/context";
export class SelectionTool {
private selection: SVGSelection;
private path;
public connect(selection: SVGSelection) {
public connect(selection: SVGSelection, context: Context) {
const self = this;
this.selection = selection;
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');
g.attr("class", "selection-line-tool");
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() {
const subject = select(window);
const parent = this.parentNode;
const parent = this.parentElement;
const start = mouse(parent);
self.startSelection(start);
subject
.on("mousemove.selection", function() {
self.moveSelection(start, mouse(parent));
}).on("mouseup.selection", function() {
self.endSelection(start, mouse(parent));
subject.on("mousemove.selection", null).on("mouseup.selection", null);
});
const start = transformation(mouse(parent));
self.startSelection(start);
subject
.on("mousemove.selection", function() {
self.moveSelection(start, transformation(mouse(parent)));
}).on("mouseup.selection", function() {
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) {
this.path
.attr("d", this.rect(start[0], start[1], 0, 0))
.attr("visibility", "visible");
}
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) {
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 { DrawingLineWidget } from "./drawing-line.widget";
import {SelectionTool} from "../tools/selection-tool";
import {Tool} from "../tool";
export class GraphLayout implements Widget {
private nodes: Node[] = [];
@ -80,24 +81,25 @@ export class GraphLayout implements Widget {
this.nodesWidget.draw(canvas, this.nodes);
this.drawingsWidget.draw(canvas, this.drawings);
this.drawingLineTool.connect(view);
this.selectionTool.connect(view);
const onZoom = function(this: SVGSVGElement) {
const e: D3ZoomEvent<SVGSVGElement, any> = event;
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());
}
};
// this.drawingLineTool.connect(view, context);
this.selectionTool.connect(view, context);
view.call(zoom<SVGSVGElement, any>()
.scaleExtent([1 / 2, 8])
.on('zoom', onZoom));
// const onZoom = function(this: SVGSVGElement) {
// const e: D3ZoomEvent<SVGSVGElement, any> = event;
// 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 {Selection} from "d3-selection";
import {Point} from "../../cartography/shared/models/point.model";
export class Context {
private size: Size;
private root: Selection<SVGSVGElement, any, null, undefined>;
private centerZeroZeroPoint = true;
constructor(root: Selection<SVGSVGElement, any, null, undefined>) {
this.root = root;
@ -16,4 +18,8 @@ export class Context {
public setSize(size: Size): void {
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 {
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;
}