diff --git a/src/app/components/graphs.component.html b/src/app/components/graphs.component.html index 389ac28..9d2c8e9 100644 --- a/src/app/components/graphs.component.html +++ b/src/app/components/graphs.component.html @@ -1,5 +1,5 @@ - + diff --git a/src/app/components/graphs.component.ts b/src/app/components/graphs.component.ts index 68e02fd..053306d 100644 --- a/src/app/components/graphs.component.ts +++ b/src/app/components/graphs.component.ts @@ -128,11 +128,13 @@ export class GraphsComponent implements OnChanges, OnInit { private adjustGraph(curve) { return Object.assign(curve, { stroke: this.config.stroke, - nodes: [ - this.genVectorPoint(curve.start.point, curve.start.vector), - ...this.genRandomPoints(this.config.nodes), - this.genVectorPoint(curve.end.point, curve.end.vector) - ] + start: Object.assign(curve.start, { + direction: this.genVectorPoint(curve.start.point, curve.start.vector) + }), + end: Object.assign(curve.end, { + direction: this.genVectorPoint(curve.end.point, curve.end.vector) + }), + nodes: this.genRandomPoints(this.config.nodes) }); } diff --git a/src/app/directives/guilloche.directive.ts b/src/app/directives/guilloche.directive.ts index 6d15be1..bcebe26 100644 --- a/src/app/directives/guilloche.directive.ts +++ b/src/app/directives/guilloche.directive.ts @@ -41,8 +41,11 @@ export class GuillocheDirective implements OnChanges { private canvas: any; private group: any; private bounce: any | null; + private bounces: any | null; private initialNodes: any; private animationInterval: any; + private medianPoint: Point; + private medianIndex: number; @Input() graph: Graph; @Input() matrix: any; @@ -66,12 +69,26 @@ export class GuillocheDirective implements OnChanges { // @todo modify graph here instead of in graphs.component.ts this.group.selectAll('*').remove(); + this.initialNodes = this.graph.nodes.slice(); + this.medianPoint = this.math.medianOfCurve(this.initialNodes); + this.medianIndex = this.math.medianIndex(this.initialNodes); + if (this.graphService.isAnimated) { - const bounceStart = Math.round(Math.random() * 10) / 10; - const bounceAmplitude = Math.round(Math.random() * 500); - this.bounce = this.math.bounce(bounceStart, bounceAmplitude, 2); - this.initialNodes = this.graph.nodes.slice(); - this.animationInterval = setInterval(() => this.animateGraph(), 80); + + this.graph.nodes = this.graph.nodes.slice().map((node, i) => { + return { + x: node.x, + y: node.y, + // ascent: Math.round(Math.random() * 100) / 100 + ascent: this.medianPoint.ascent + i * 0.5 + }; + }); + this.bounces = this.initialNodes.map(node => { + const bounceStart = Math.round(Math.random() * 10) / 10; + const bounceAmplitude = Math.round(Math.random() * 100); + return this.math.bounce(bounceStart, bounceAmplitude, 2); + }); + this.animationInterval = setInterval(() => this.animateGraph(), 120); } else { if (this.animationInterval) { this.bounce = null; @@ -82,52 +99,59 @@ export class GuillocheDirective implements OnChanges { this.guillocheChanged(); this.spreadLines([ this.graph.start.point, + this.graph.start.direction, ...this.graph.nodes, - this.graph.end.point + this.graph.end.point, + this.graph.end.direction, ]); } private animateGraph() { - const medianIndex = this.math.medianIndex(this.initialNodes); - const medianPoint = this.math.medianOfCurve(this.initialNodes); - const bouncedMedian = this.graphService.shiftPoint(medianPoint, medianPoint.ascent, this.bounce.next().value); + // const medianIndex = this.math.medianIndex(this.initialNodes); + // const bouncedMedian = this.graphService.shiftPoint(medianPoint, medianPoint.ascent, this.bounce.next().value); + + // this.graph.nodes.splice(medianIndex, 1, bouncedMedian); - this.graph.nodes.splice(medianIndex, 1, bouncedMedian); this.group.selectAll('*').remove(); + this.spreadLines([ this.graph.start.point, - ...this.graph.nodes, + this.graph.start.direction, + ...this.graph.nodes.map((point, i) => { + return this.graphService.shiftPoint(point, point.ascent, this.bounces[i].next().value); + }), + this.graph.end.direction, this.graph.end.point, ]); - this.debugBounce(bouncedMedian); + // this.debugBounce(bouncedMedian); } private spreadLines(points: Point[]) { const shiftedMedians = []; // Alternatively use median of curve instead of center // const medianPoint = this.math.medianOfCurve(points); - const medianPoint = this.math.centerOfCurve(points); - const medianIndex = this.math.medianIndex(points); - const genshiftedMedians = this.graphService.spreadOrthogonal(medianPoint, this.config.spread.spacing); + // const medianPoint = this.math.centerOfCurve(points); + // const medianIndex = this.math.medianIndex(points); + const genshiftedMedians = this.graphService.spreadOrthogonal(this.medianPoint, this.config.spread.spacing); for (let i = 0; i < this.config.spread.amount; i++) { shiftedMedians.push(genshiftedMedians.next().value); } - if (env.debug) { - [medianPoint, ...shiftedMedians].forEach((point, index) => { - this.group.append('circle') - .attr('cx', point.x) - .attr('cy', point.y) - .attr('r', 10 / index) - .attr('fill-opacity', 0.6) - .attr('fill', 'darkgray'); - }); - } + // if (env.debug) { + // [medianPoint, ...shiftedMedians].forEach((point, index) => { + // this.group.append('circle') + // .attr('cx', point.x) + // .attr('cy', point.y) + // .attr('r', 10 / index) + // .attr('fill-opacity', 0.6) + // .attr('fill', 'darkgray'); + // }); + // } shiftedMedians.forEach(median => { const shiftedGraph = points.slice(); - shiftedGraph.splice(medianIndex, 1, median); + shiftedGraph.splice(this.medianIndex, 1, median); this.drawGraph(shiftedGraph); }); } @@ -143,7 +167,7 @@ export class GuillocheDirective implements OnChanges { .attr('fill', 'none'); if (env.debug) { - this.debugGraph(); + this.debugGraph(points); } } @@ -151,8 +175,8 @@ export class GuillocheDirective implements OnChanges { this.guillocheChange.emit(this.el.nativeElement); } - private debugGraph() { - this.graph.nodes.forEach((point, index) => { + private debugGraph(points: Point[]) { + points.forEach((point, index) => { const circle = this.group.append('g'); circle.append('circle') diff --git a/src/app/models/graph.model.ts b/src/app/models/graph.model.ts index 9869993..b3f9f9d 100644 --- a/src/app/models/graph.model.ts +++ b/src/app/models/graph.model.ts @@ -21,10 +21,12 @@ export interface Graph { color: string; // can be set in enviroment start: { point: Point; + direction?: Point; vector: number; // degree between 0 and 360 }; end: { point: Point; + direction?: Point; vector: number; // degree between 0 and 360 }; stroke: number; // stroke width diff --git a/src/app/services/graph.service.ts b/src/app/services/graph.service.ts index 8c8c596..724b573 100644 --- a/src/app/services/graph.service.ts +++ b/src/app/services/graph.service.ts @@ -66,7 +66,7 @@ export class GraphService { } } - public shiftPoint(point: Point, radians: number, spacing: number) { + public shiftPoint(point: Point, radians: number, spacing: number): Point { return { x: Math.sin(radians * Math.PI) * spacing + point.x, y: Math.cos(radians * Math.PI) * spacing + point.y diff --git a/src/environments/environment.ts b/src/environments/environment.ts index 5deef47..e6c6edf 100644 --- a/src/environments/environment.ts +++ b/src/environments/environment.ts @@ -16,11 +16,11 @@ export const environment = { production: false, - debug: false, + debug: true, guilloche: { colors: { - primary: '#950952', - secondary: '#189B8E' + primary: '#129490', + secondary: '#004FFF' } }, formDefaults: { @@ -31,14 +31,14 @@ export const environment = { vectors: { start: 1, end: 0, - range: 0.4, + range: 0.6, spacing: 7 }, nodes: 5, stroke: 0.7, spread: { - amount: 10, - spacing: 32 + amount: 8, + spacing: 10 } } };