added download button
This commit is contained in:
@@ -30,7 +30,7 @@
|
||||
"scripts": {
|
||||
"ng": "ng",
|
||||
"start": "ng serve",
|
||||
"build": "ng build",
|
||||
"build": "ng build --prod",
|
||||
"test": "ng test",
|
||||
"lint": "ng lint",
|
||||
"e2e": "ng e2e"
|
||||
|
||||
@@ -1,102 +1,104 @@
|
||||
<app-graphs [config]="config"></app-graphs>
|
||||
<app-graphs [config]="config" (svgChange)="prepareSvgExport($event)"></app-graphs>
|
||||
|
||||
<aside class="col-sm-4 col-lg-3 col-xl-3">
|
||||
<form [formGroup]="configForm" (ngSubmit)="updateGraphs()" novalidate>
|
||||
<div class="pb-5">
|
||||
<h5>Grundfläche</h5>
|
||||
<hr>
|
||||
<div class="form-group">
|
||||
<label class="form-control-label">
|
||||
Breite
|
||||
</label>
|
||||
<input type="number" class="form-control" formControlName="width">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-control-label">
|
||||
Höhe
|
||||
</label>
|
||||
<input type="number" class="form-control" formControlName="height">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-control-label">
|
||||
Skalierung
|
||||
</label>
|
||||
<input type="number" class="form-control" formControlName="scale" min="0" max="1" step="0.01">
|
||||
</div>
|
||||
</div>
|
||||
<div class="pb-5">
|
||||
<h5>Vektorfläche</h5>
|
||||
<hr/>
|
||||
<div class="form-group">
|
||||
<label class="form-control-label">
|
||||
Skalierung
|
||||
</label>
|
||||
<input type="number" class="form-control" formControlName="overlap" min="0" max="30" step="0.1">
|
||||
</div>
|
||||
<ng-container formGroupName="vectors">
|
||||
<div class="aside-inner">
|
||||
<form [formGroup]="configForm" (ngSubmit)="updateGraphs()" novalidate>
|
||||
<div class="pb-5">
|
||||
<h5>Grundfläche</h5>
|
||||
<hr>
|
||||
<div class="form-group">
|
||||
<label class="form-control-label">
|
||||
Anfangsvektor
|
||||
Breite
|
||||
</label>
|
||||
<select class="form-control" formControlName="start">
|
||||
<option value="1">Oben</option>
|
||||
<option value="0.5">Rechts</option>
|
||||
<option value="0">Unten</option>
|
||||
<option value="1.5">Links</option>
|
||||
</select>
|
||||
<input type="number" class="form-control" formControlName="width">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-control-label">
|
||||
Endvektor
|
||||
Höhe
|
||||
</label>
|
||||
<select class="form-control" formControlName="end">
|
||||
<option value="1">Oben</option>
|
||||
<option value="0.5">Rechts</option>
|
||||
<option value="0">Unten</option>
|
||||
<option value="1.5">Links</option>
|
||||
</select>
|
||||
<input type="number" class="form-control" formControlName="height">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-control-label">
|
||||
Skalierung
|
||||
</label>
|
||||
<input type="number" class="form-control" formControlName="scale" min="0" max="1" step="0.01">
|
||||
</div>
|
||||
</div>
|
||||
<div class="pb-5">
|
||||
<h5>Vektorfläche</h5>
|
||||
<hr/>
|
||||
<div class="form-group">
|
||||
<label class="form-control-label">
|
||||
Skalierung
|
||||
</label>
|
||||
<input type="number" class="form-control" formControlName="overlap" min="0" max="30" step="0.1">
|
||||
</div>
|
||||
<ng-container formGroupName="vectors">
|
||||
<div class="form-group">
|
||||
<label class="form-control-label">
|
||||
Anfangsvektor
|
||||
</label>
|
||||
<select class="form-control" formControlName="start">
|
||||
<option value="1">Oben</option>
|
||||
<option value="0.5">Rechts</option>
|
||||
<option value="0">Unten</option>
|
||||
<option value="1.5">Links</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-control-label">
|
||||
Endvektor
|
||||
</label>
|
||||
<select class="form-control" formControlName="end">
|
||||
<option value="1">Oben</option>
|
||||
<option value="0.5">Rechts</option>
|
||||
<option value="0">Unten</option>
|
||||
<option value="1.5">Links</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="form-control-label">
|
||||
Dehnung
|
||||
</label>
|
||||
<input type="number" class="form-control" formControlName="range" min="0" max="1" step="0.1">
|
||||
</div>
|
||||
</ng-container>
|
||||
</div>
|
||||
<h5 class="mt-2">Graph</h5>
|
||||
<!-- <hr>
|
||||
<small>Anzahl der Schwingungen mittels Knotenpunkten bestimmen und die Skalierung auf der Leinwand einstellen.</small> -->
|
||||
<hr>
|
||||
<div class="form-group mb-4">
|
||||
<label class="form-control-label">
|
||||
Knotenpunkte
|
||||
</label>
|
||||
<input type="number" class="form-control" formControlName="nodes" min="1" max="10">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-control-label">
|
||||
Linienstärke
|
||||
</label>
|
||||
<input type="number" class="form-control" formControlName="stroke" min="0.1" max="10" step="0.1">
|
||||
</div>
|
||||
<div class="form-group mb-4">
|
||||
<label class="form-control-label">
|
||||
Linienabstand
|
||||
</label>
|
||||
<input type="number" class="form-control" formControlName="space" min="0" max="10" step="0.1">
|
||||
</div>
|
||||
<div class="form-group mb-4">
|
||||
<label class="form-control-label">
|
||||
Aufspleißen
|
||||
</label>
|
||||
<input type="number" class="form-control" formControlName="spread" min="0" max="40">
|
||||
</div>
|
||||
<div class="dropdown-divider mb-4"></div>
|
||||
<button type="submit" class="btn btn-lg btn-primary btn-block" [disabled]="configForm.invalid">Aktualisieren</button>
|
||||
<div class="form-group">
|
||||
<label class="form-control-label">
|
||||
Dehnung
|
||||
</label>
|
||||
<input type="number" class="form-control" formControlName="range" min="0" max="1" step="0.1">
|
||||
</div>
|
||||
</ng-container>
|
||||
</div>
|
||||
<h5 class="mt-2">Graph</h5>
|
||||
<!-- <hr>
|
||||
<small>Anzahl der Schwingungen mittels Knotenpunkten bestimmen und die Skalierung auf der Leinwand einstellen.</small> -->
|
||||
<hr>
|
||||
<div class="form-group mb-4">
|
||||
<label class="form-control-label">
|
||||
Knotenpunkte
|
||||
</label>
|
||||
<input type="number" class="form-control" formControlName="nodes" min="1" max="10">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-control-label">
|
||||
Linienstärke
|
||||
</label>
|
||||
<input type="number" class="form-control" formControlName="stroke" min="0.1" max="10" step="0.1">
|
||||
</div>
|
||||
<div class="form-group mb-4">
|
||||
<label class="form-control-label">
|
||||
Linienabstand
|
||||
</label>
|
||||
<input type="number" class="form-control" formControlName="space" min="0" max="10" step="0.1">
|
||||
</div>
|
||||
<div class="form-group mb-4">
|
||||
<label class="form-control-label">
|
||||
Aufspleißen
|
||||
</label>
|
||||
<input type="number" class="form-control" formControlName="spread" min="0" max="40">
|
||||
</div>
|
||||
<div class="dropdown-divider mb-4"></div>
|
||||
<button type="submit" class="btn btn-lg btn-primary btn-block" [disabled]="configForm.invalid">Aktualisieren</button>
|
||||
</form>
|
||||
<div class="dropdown-divider"></div>
|
||||
<!-- <button (click)="exportSvg()" class="btn btn-secondary btn-block" [disabled]="configForm.invalid">Download</button> -->
|
||||
</form>
|
||||
<button class="btn btn-secondary btn-block" (click)="exportSvg()">Download</button>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
|
||||
@@ -62,7 +62,7 @@ aside {
|
||||
margin: 0;
|
||||
background: rgba(251, 252, 253, 0.9);
|
||||
|
||||
form {
|
||||
.aside-inner {
|
||||
overflow: auto;
|
||||
padding: 3rem;
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
import { ConfigForm } from './forms/config.form';
|
||||
import { Component, OnInit, HostListener } from '@angular/core';
|
||||
import { FormGroup } from '@angular/forms';
|
||||
import { DomSanitizer, SafeResourceUrl } from '@angular/platform-browser';
|
||||
|
||||
import { environment as env } from '../environments/environment';
|
||||
import { Param } from './models/param.model';
|
||||
@@ -32,9 +33,9 @@ export class AppComponent implements OnInit {
|
||||
public canvasParam: Param;
|
||||
public config: any | null;
|
||||
public configForm: FormGroup;
|
||||
public scaleOnWheel: boolean;
|
||||
public url: any;
|
||||
|
||||
constructor() {
|
||||
constructor(private sanitizer: DomSanitizer) {
|
||||
this.config = env.formDefaults;
|
||||
this.configForm = ConfigForm;
|
||||
}
|
||||
@@ -47,7 +48,21 @@ export class AppComponent implements OnInit {
|
||||
this.config = {...this.configForm.value};
|
||||
}
|
||||
|
||||
public prepareSvgExport(svg) {
|
||||
const blob = new Blob(
|
||||
[svg.nativeElement.outerHTML],
|
||||
{type: 'image/svg+xml;charset=utf-8'}
|
||||
);
|
||||
this.url = URL.createObjectURL(blob);
|
||||
}
|
||||
|
||||
public exportSvg() {
|
||||
alert('Feature coming');
|
||||
const link = document.createElement('a');
|
||||
|
||||
link.href = this.url;
|
||||
link.download = 'guilloche.svg';
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
document.body.removeChild(link);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
<svg #svg width="100%" height="100%">
|
||||
<g guilloche *ngFor="let graph of graphs" [graph]="graph" [matrix]="matrix" [config]="config"></g>
|
||||
<g guilloche *ngFor="let graph of graphs" [graph]="graph" [matrix]="matrix" [config]="config" (guillocheChange)="prepareGuillocheExport($event)"></g>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 147 B After Width: | Height: | Size: 198 B |
@@ -14,7 +14,7 @@
|
||||
* Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
import { ViewChildren, QueryList, Component, ViewChild, Input, SimpleChanges, OnChanges, HostListener } from '@angular/core';
|
||||
import { ViewChild, QueryList, Component, Input, Output, SimpleChanges, OnChanges, HostListener, EventEmitter } from '@angular/core';
|
||||
import * as Selection from 'd3-selection';
|
||||
import * as Shape from 'd3-shape';
|
||||
import * as Random from 'd3-random';
|
||||
@@ -38,12 +38,13 @@ export class GraphsComponent implements OnChanges {
|
||||
public matrix: any | null;
|
||||
|
||||
private genShiftPoint: any | null;
|
||||
private genLoadedAllGraphs: any | null;
|
||||
|
||||
@Input() config: any;
|
||||
|
||||
@ViewChild('svg') svgElementRef;
|
||||
@ViewChild(GuillocheDirective) guillocheViewChild: GuillocheDirective;
|
||||
@ViewChildren(GuillocheDirective) guillocheViewChildren: QueryList<GuillocheDirective>;
|
||||
|
||||
@Output() svgChange = new EventEmitter();
|
||||
|
||||
@HostListener('window:resize', ['$event'])
|
||||
private onResize(event) {
|
||||
@@ -53,6 +54,7 @@ export class GraphsComponent implements OnChanges {
|
||||
constructor(
|
||||
private canvasService: CanvasService
|
||||
) {
|
||||
this.genLoadedAllGraphs = this.countLoadedGraphs();
|
||||
}
|
||||
|
||||
ngOnChanges(changes: SimpleChanges) {
|
||||
@@ -65,6 +67,28 @@ export class GraphsComponent implements OnChanges {
|
||||
this.updateGraphs();
|
||||
}
|
||||
|
||||
public prepareGuillocheExport(guillocheElement) {
|
||||
const item = this.genLoadedAllGraphs.next().value;
|
||||
console.log(item);
|
||||
if (item) {
|
||||
this.svgChange.emit(this.svgElementRef);
|
||||
}
|
||||
}
|
||||
|
||||
private *countLoadedGraphs() {
|
||||
let cycles = 1;
|
||||
|
||||
while (true) {
|
||||
if (cycles < this.graphs.length) {
|
||||
yield false;
|
||||
cycles++;
|
||||
} else {
|
||||
yield true;
|
||||
cycles = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private updateGraphs(): void {
|
||||
const genShiftStart = this.shiftPoint(this.matrix.start, this.config.vectors.start);
|
||||
const genShiftEnd = this.shiftPoint(this.matrix.end, this.config.vectors.end);
|
||||
|
||||
@@ -39,6 +39,8 @@ export class GuillocheDirective implements OnChanges {
|
||||
@Input() matrix: any;
|
||||
@Input() config: any;
|
||||
|
||||
@Output() guillocheChange = new EventEmitter();
|
||||
|
||||
constructor(
|
||||
private canvasService: CanvasService,
|
||||
private el: ElementRef
|
||||
@@ -54,6 +56,11 @@ export class GuillocheDirective implements OnChanges {
|
||||
this.graph.end.point
|
||||
];
|
||||
this.spreadLines(points);
|
||||
this.guillocheChanged();
|
||||
}
|
||||
|
||||
public guillocheChanged() {
|
||||
this.guillocheChange.emit(this.el.nativeElement);
|
||||
}
|
||||
|
||||
private drawGraph(points: Point[]): void {
|
||||
@@ -77,7 +84,6 @@ export class GuillocheDirective implements OnChanges {
|
||||
const closestCenter = this.getClosestCenter(pointMiddle);
|
||||
const radius = this.Δ(pointMiddle, closestCenter);
|
||||
const spreadPoints = [];
|
||||
const group = this.canvas.append('g').attr('id', 'spread-points');
|
||||
const pies = 80;
|
||||
|
||||
for (let i = 0; i < pies; i++) {
|
||||
@@ -100,7 +106,6 @@ export class GuillocheDirective implements OnChanges {
|
||||
return index === this.config.spread - 1;
|
||||
});
|
||||
|
||||
group.lower();
|
||||
}
|
||||
|
||||
private getClosestCenter(point: Point) {
|
||||
|
||||
Reference in New Issue
Block a user