2
0

feat(graohsComponent): added vector configuration

This commit is contained in:
2018-05-23 21:55:52 +02:00
parent b1e6faab99
commit 2d635148b8
9 changed files with 186 additions and 149 deletions

View File

@@ -10,87 +10,68 @@
<app-graphs [config]="config"></app-graphs> <app-graphs [config]="config"></app-graphs>
<ul *ngIf="false"> <aside class="col-sm-4 col-lg-3 col-xl-3">
<li>
<label>
<div>Points</div>
<input type="number" name="points" [(ngModel)]="canvasParam.points" max="10" min="0" step="1">
</label>
</li>
<li>
<label>
<div>Margin X</div>
<input type="number" name="marginX" [(ngModel)]="canvasParam.margin.x" max="1" min="0" step="0.1">
</label>
</li>
<li>
<label>
<div>Margin Y</div>
<input type="number" name="marginY" [(ngModel)]="canvasParam.margin.y" max="1" min="0" step="0.1">
</label>
</li>
<li>
<label>
<div>Stroke Width</div>
<input type="number" name="strokeWidth" [(ngModel)]="canvasParam.stroke.width" max="10" min="0" step="0.1">
</label>
</li>
<li>
<label>
<div>Spread lines</div>
<input type="number" name="spread" [(ngModel)]="canvasParam.spread" max="20" min="5" step="1">
</label>
</li>
<li>
<label>
<div>Show Grid?</div>
<input type="checkbox" name="showGrid" [(ngModel)]="canvasParam.showGrid">
</label>
</li>
</ul>
<aside>
<form [formGroup]="configForm" (ngSubmit)="updateGraphs()" novalidate> <form [formGroup]="configForm" (ngSubmit)="updateGraphs()" novalidate>
<div class="pb-5">
<h5>Seitenverhältnis</h5>
<hr>
<div class="form-group"> <div class="form-group">
<label class="form-control-label"> <label class="form-control-label">
Breite <small>(bspw. 42, -12, 3.2)</small> Breite
</label> </label>
<input type="number" class="form-control" formControlName="width"> <input type="number" class="form-control" formControlName="width">
</div> </div>
<div class="form-group"> <div class="form-group">
<label class="form-control-label"> <label class="form-control-label">
Höhe <small>(bspw. 42, -12, 3.2)</small> Höhe
</label> </label>
<input type="number" class="form-control" formControlName="height"> <input type="number" class="form-control" formControlName="height">
</div> </div>
<div class="form-group"> <div class="form-group">
<label class="form-control-label"> <label class="form-control-label">
Duktus <small>(Strichstärke)</small> Linienstärke
</label> </label>
<input type="number" class="form-control" formControlName="stroke" min="0.1" max="10" step="0.1"> <input type="number" class="form-control" formControlName="stroke" min="0.1" max="10" step="0.1">
</div> </div>
</div>
<div class="pb-5">
<h5>Vektoren</h5>
<hr>
<ng-container formGroupName="vectors">
<div class="form-group"> <div class="form-group">
<label class="form-control-label"> <label class="form-control-label">
Anfangsvektor Anfangsvektor
</label> </label>
<select class="form-control" formControlName="directionStart"> <select class="form-control" formControlName="start">
<option value="0">Oben</option> <option value="1">Oben</option>
<option value="90">Rechts</option> <option value="0.5">Rechts</option>
<option value="180">Unten</option> <option value="0">Unten</option>
<option value="270">Links</option> <option value="1.5">Links</option>
</select> </select>
</div> </div>
<div class="form-group"> <div class="form-group">
<label class="form-control-label"> <label class="form-control-label">
Endvektor Endvektor
</label> </label>
<select class="form-control" formControlName="directionEnd"> <select class="form-control" formControlName="end">
<option value="0">Oben</option> <option value="1">Oben</option>
<option value="90">Rechts</option> <option value="0.5">Rechts</option>
<option value="180">Unten</option> <option value="0">Unten</option>
<option value="270">Links</option> <option value="1.5">Links</option>
</select> </select>
</div> </div>
<div class="form-group">
<label class="form-control-label">
Vektordehnung
</label>
<input type="number" class="form-control" formControlName="range" min="0" max="1" step="0.1">
</div>
</ng-container>
</div>
<h5 class="mt-2">Ausdehnung</h5>
<!-- <hr>
<small>Anzahl der Schwingungen mittels Knotenpunkten bestimmen und die Skalierung auf der Leinwand einstellen.</small> -->
<hr>
<div class="form-group"> <div class="form-group">
<label class="form-control-label"> <label class="form-control-label">
Skalierung Skalierung

View File

@@ -5,6 +5,7 @@
top: 0; top: 0;
left: 0; left: 0;
overflow: hidden; overflow: hidden;
opacity: 0.2;
} }
ul { ul {
@@ -44,5 +45,5 @@ aside {
justify-content: center; justify-content: center;
margin: 0; margin: 0;
padding: 3rem; padding: 3rem;
background: rgba(251, 252, 253, 0.8); background: rgba(251, 252, 253, 0.9);
} }

View File

@@ -18,9 +18,9 @@ export class AppComponent implements OnInit {
public configForm: FormGroup; public configForm: FormGroup;
@HostListener('mousewheel', ['$event']) @HostListener('mousewheel', ['$event'])
private onWheelUp(event) { private onMousewheel(event) {
const delta = Math.sign(event.deltaY); const delta = Math.sign(event.deltaY);
const step = 0.01; const step = env.controls.wheelStep;
this.config = {...this.configForm.value}; this.config = {...this.configForm.value};
@@ -36,13 +36,11 @@ export class AppComponent implements OnInit {
this.config.scale -= step; this.config.scale -= step;
} }
this.config.scale = Math.round(this.config.scale * 100) / 100; this.config.scale = Math.round(this.config.scale / step) * step;
this.configForm.reset({...this.config}); this.configForm.reset({...this.config});
this.updateGraphs(); this.updateGraphs();
} }
constructor() { constructor() {
this.canvasParam = { this.canvasParam = {
colors: { colors: {
@@ -67,6 +65,10 @@ export class AppComponent implements OnInit {
ngOnInit() { ngOnInit() {
this.configForm.reset({...this.config}); this.configForm.reset({...this.config});
// this.configForm.valueChanges.subscribe(val => {
// console.log('form changes(appComponent)', this.config);
// });
} }
public updateGraphs() { public updateGraphs() {

View File

@@ -20,6 +20,7 @@ export class GraphsComponent implements AfterViewInit, OnChanges {
public graphs: Graph[]; public graphs: Graph[];
public canvas: any | null; public canvas: any | null;
public matrix: any | null;
@Input() config: any; @Input() config: any;
@@ -51,50 +52,43 @@ export class GraphsComponent implements AfterViewInit, OnChanges {
private init() { private init() {
this.updateCanvas(); this.updateCanvas();
this.updateMatrix();
this.updateGraphs(); this.updateGraphs();
} }
private updateGraphs(): void { private updateGraphs(): void {
const matrix = this.matrix; this.graphs = [this.adjustGraph('start'), this.adjustGraph('end')];
console.log('graphs component (updateGraphs):', this.graphs);
this.graphs = [...[this.adjustGraph('start'), this.adjustGraph('end')]];
} }
private adjustGraph(from: string) { private adjustGraph(from: string) {
const matrix = this.matrix;
const to = this.flipflop(from); const to = this.flipflop(from);
const startPoint = { x: this.matrix[from].x, y: this.matrix[from].y };
const endPoint = { x: this.matrix[to].x, y: this.matrix[to].y };
console.error(from, '->', to);
return { return {
id: `${from}-to-${to}`,
start: { start: {
coords: { x: matrix[from].x, y: matrix[from].y }, coords: startPoint,
direction: this.config.directionStart, direction: this.config.vectors[from],
color: env.guilloche.colors[from] color: env.guilloche.colors.start
}, end: { }, end: {
coords: { x: matrix[to].x, y: matrix[to].y }, coords: endPoint,
direction: this.config.directionEnd, direction: this.config.vectors[to],
color: env.guilloche.colors[to] color: env.guilloche.colors.end
}, },
stroke: this.config.stroke, stroke: this.config.stroke,
nodes: [] nodes: [
this.vectorPoint(startPoint, this.config.vectors[from]),
this.vectorPoint(endPoint, this.config.vectors[to])
]
}; };
// {
// start: {
// coords: { x: matrix.end.x, y: matrix.end.y },
// direction: this.config.directionEnd,
// color: env.guilloche.colors.start
// }, end: {
// coords: { x: matrix.start.x, y: matrix.start.y },
// direction: this.config.directionStart,
// color: env.guilloche.colors.end
// },
// stroke: this.config.stroke,
// nodes: []
// }
} }
private flipflop(direction: string) { private flipflop(x: string) {
return (direction === 'start') ? 'end' : 'start'; return (x === 'start') ? 'end' : 'start';
} }
private updateCanvas(): void { private updateCanvas(): void {
@@ -109,15 +103,17 @@ export class GraphsComponent implements AfterViewInit, OnChanges {
}; };
} }
private get matrix() { private updateMatrix() {
const totalArea = Math.abs(this.canvas.clientWidth * this.canvas.clientHeight); const totalArea = Math.abs(this.canvas.clientWidth * this.canvas.clientHeight);
const totalCenter = this.centerPoint(this.canvas.clientWidth, this.canvas.clientHeight); const totalCenter = this.centerPoint(this.canvas.clientWidth, this.canvas.clientHeight);
const baseArea = Math.abs(this.config.width * this.config.height); const baseArea = Math.abs(this.config.width * this.config.height);
const baseScale = Math.pow(totalArea / baseArea * this.config.scale, 0.5); const baseScale = Math.pow(totalArea / baseArea * this.config.scale, 0.5);
const baseCenter = this.centerPoint( baseScale * this.config.width, baseScale * this.config.height); const baseWidthScaled = baseScale * this.config.width;
const baseHeightScaled = baseScale * this.config.height;
const baseCenter = this.centerPoint(baseWidthScaled, baseHeightScaled);
return { this.matrix = {
start: { start: {
x: totalCenter.x - baseCenter.x, x: totalCenter.x - baseCenter.x,
y: totalCenter.y + baseCenter.y y: totalCenter.y + baseCenter.y
@@ -125,7 +121,29 @@ export class GraphsComponent implements AfterViewInit, OnChanges {
end: { end: {
x: totalCenter.x + baseCenter.x, x: totalCenter.x + baseCenter.x,
y: totalCenter.y - baseCenter.y y: totalCenter.y - baseCenter.y
} },
width: baseWidthScaled,
height: baseHeightScaled
}; };
} }
private vectorPoint(point: Point, direction: number) {
const range = this.Δ(this.matrix.start, this.matrix.end) * this.config.vectors.range;
console.log('graphs component(vectorPoint)', point, direction);
return {
x: range * Math.sin(Math.PI * direction) + point.x,
y: range * Math.cos(Math.PI * direction) + point.y
};
}
/**
* Calculate distance between to points with coordinates.
* @param a
* @param b
*/
private Δ(a: Point, b: Point) {
return Math.pow(Math.pow(a.x - b.x, 2) + Math.pow(a.y - b.y, 2), 0.5);
}
} }

View File

@@ -5,6 +5,7 @@ import * as Shape from 'd3-shape';
import * as Random from 'd3-random'; import * as Random from 'd3-random';
import * as Drag from 'd3-drag'; import * as Drag from 'd3-drag';
import { environment as env } from './../../environments/environment';
import { Config } from './../models/config.model'; import { Config } from './../models/config.model';
import { Point } from './../models/point.model'; import { Point } from './../models/point.model';
import { Param } from './../models/param.model'; import { Param } from './../models/param.model';
@@ -27,16 +28,16 @@ export class GuillocheDirective implements OnChanges {
) { ) {
this.group = Selection.select(el.nativeElement); this.group = Selection.select(el.nativeElement);
this.canvas = Selection.select(this.canvasService.get); this.canvas = Selection.select(this.canvasService.get);
this.gradientId = 'linear';
} }
ngOnChanges(changes: SimpleChanges) { ngOnChanges(changes: SimpleChanges) {
console.log('guilloche directive (changes)', changes.graph.currentValue); console.log('guilloche directive (changes)', changes.graph.currentValue);
this.defineGradient();
this.drawGraph(); this.drawGraph();
} }
private drawGraph(): void { private defineGradient(): void {
console.log('guilloche directive(drawGraph)', this.graph); this.gradientId = `gradient-${this.graph.id}`;
const defs = this.group.append('defs'); const defs = this.group.append('defs');
const grad = defs.append('linearGradient') const grad = defs.append('linearGradient')
@@ -47,19 +48,21 @@ export class GuillocheDirective implements OnChanges {
grad.append('stop') grad.append('stop')
.attr('stop-color', this.graph.end.color) .attr('stop-color', this.graph.end.color)
.attr('offset', '100%'); .attr('offset', '100%');
}
private drawGraph(): void {
const points = [this.graph.start.coords, ...this.graph.nodes, this.graph.end.coords];
this.group.append('path') this.group.append('path')
.attr('d', Shape.line() .attr('d', Shape.line()
.x(p => p.x) .x(p => p.x)
.y(p => p.y) .y(p => p.y)
.curve(Shape.curveBasis)([ .curve(Shape.curveBasis)(points))
this.graph.start.coords,
this.graph.end.coords
]))
.attr('stroke', `url(#${this.gradientId})`) .attr('stroke', `url(#${this.gradientId})`)
.attr('stroke-width', this.graph.stroke) .attr('stroke-width', this.graph.stroke)
.attr('fill', 'none'); .attr('fill', 'none');
if (!env.production) {
this.group.append('circle') this.group.append('circle')
.attr('cx', this.graph.start.coords.x) .attr('cx', this.graph.start.coords.x)
.attr('cy', this.graph.start.coords.y) .attr('cy', this.graph.start.coords.y)
@@ -75,5 +78,18 @@ export class GuillocheDirective implements OnChanges {
.attr('stroke-width', 1) .attr('stroke-width', 1)
.attr('fill-opacity', 0) .attr('fill-opacity', 0)
.attr('stroke', this.graph.end.color); .attr('stroke', this.graph.end.color);
this.graph.nodes.forEach(point => {
this.group.append('circle')
.attr('cx', point.x)
.attr('cy', point.y)
.attr('r', 5)
.attr('stroke-width', 1)
.attr('fill-opacity', 0)
.attr('stroke', 'darkgray');
});
}
console.log('guilloche directive(drawGraph)', this.graph);
} }
} }

View File

@@ -5,14 +5,20 @@ const fb = new FormBuilder();
export let ConfigForm: FormGroup = fb.group({ export let ConfigForm: FormGroup = fb.group({
width: fb.control('', Validators.required), width: fb.control('', Validators.required),
height: fb.control('', Validators.required), height: fb.control('', Validators.required),
directionStart: fb.control('', Validators.compose([ vectors: fb.group({
start: fb.control('', Validators.compose([
Validators.min(0), Validators.min(0),
Validators.max(360) Validators.max(2)
])), ])),
directionEnd: fb.control('', Validators.compose([ end: fb.control('', Validators.compose([
Validators.min(0), Validators.min(0),
Validators.max(360) Validators.max(2)
])), ])),
range: fb.control('', Validators.compose([
Validators.min(0),
Validators.max(1)
]))
}),
nodes: fb.control('', Validators.compose([ nodes: fb.control('', Validators.compose([
Validators.min(1), Validators.min(1),
Validators.max(10) Validators.max(10)

View File

@@ -1,6 +1,7 @@
import { Point } from './point.model'; import { Point } from './point.model';
export interface Graph { export interface Graph {
id: string;
start: { start: {
coords: Point; coords: Point;
direction: number; // degree between 0 and 360 direction: number; // degree between 0 and 360

View File

@@ -6,11 +6,17 @@ export const environment = {
end: '#5eb1bd' end: '#5eb1bd'
} }
}, },
controls: {
wheelStep: 0.01
},
formDefaults: { formDefaults: {
width: 9, width: 9,
height: 16, height: 16,
directionStart: 0, vectors: {
directionEnd: 180, start: 1,
end: 0,
range: 0.3
},
nodes: 3, nodes: 3,
stroke: 1, stroke: 1,
scale: 0.3 scale: 0.3

View File

@@ -10,14 +10,20 @@ export const environment = {
end: '#0067cc' end: '#0067cc'
} }
}, },
controls: {
wheelStep: 0.01
},
formDefaults: { formDefaults: {
width: 9, width: 9,
height: 16, height: 16,
directionStart: 0, vectors: {
directionEnd: 180, start: 1,
end: 0,
range: 0.3
},
nodes: 3, nodes: 3,
stroke: 1, stroke: 1,
scale: 0.3 scale: 0.1
} }
}; };