rudimental animation running for median point
This commit is contained in:
@@ -14,7 +14,7 @@
|
|||||||
* Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
* Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { ElementRef, HostListener, Output, EventEmitter, Input, Directive, OnChanges, OnInit, SimpleChanges } from '@angular/core';
|
import { ElementRef, HostListener, Output, EventEmitter, Input, Directive, OnChanges, SimpleChanges } from '@angular/core';
|
||||||
import * as Selection from 'd3-selection';
|
import * as Selection from 'd3-selection';
|
||||||
import * as Shape from 'd3-shape';
|
import * as Shape from 'd3-shape';
|
||||||
import * as Random from 'd3-random';
|
import * as Random from 'd3-random';
|
||||||
@@ -36,13 +36,13 @@ import { AnimationService } from './../services/animation.service';
|
|||||||
@Directive({
|
@Directive({
|
||||||
selector: '[guilloche]'
|
selector: '[guilloche]'
|
||||||
})
|
})
|
||||||
export class GuillocheDirective implements OnChanges, OnInit {
|
export class GuillocheDirective implements OnChanges {
|
||||||
|
|
||||||
private canvas: any;
|
private canvas: any;
|
||||||
private group: any;
|
private group: any;
|
||||||
|
private bounce: any | null;
|
||||||
|
private initialNodes: any;
|
||||||
private animationInterval: any;
|
private animationInterval: any;
|
||||||
private x: any;
|
|
||||||
private y: any;
|
|
||||||
|
|
||||||
@Input() graph: Graph;
|
@Input() graph: Graph;
|
||||||
@Input() matrix: any;
|
@Input() matrix: any;
|
||||||
@@ -62,78 +62,42 @@ export class GuillocheDirective implements OnChanges, OnInit {
|
|||||||
this.canvas = Selection.select(this.canvasService.get);
|
this.canvas = Selection.select(this.canvasService.get);
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit() {
|
|
||||||
// console.log('guilloche:init');
|
|
||||||
// Timer.timer(function(elapsed) {
|
|
||||||
// let t = (elapsed % 3000) / 3000;
|
|
||||||
// console.log(t);
|
|
||||||
// // dot1.attr("cx", x(t)).attr("cy", y(ease(t)));
|
|
||||||
// // dot2.attr("cy", y(ease(t)));
|
|
||||||
// });
|
|
||||||
|
|
||||||
// console.log(Ease.easeLinear(0.5));
|
|
||||||
// const t = Timer.timer(function(elapsed) {
|
|
||||||
// if (elapsed > 200) {
|
|
||||||
// t.stop();
|
|
||||||
// }
|
|
||||||
// }, 1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
ngOnChanges(changes: SimpleChanges) {
|
ngOnChanges(changes: SimpleChanges) {
|
||||||
// @todo modify graph here instead of in graphs.component.ts
|
// @todo modify graph here instead of in graphs.component.ts
|
||||||
this.group.selectAll('*').remove();
|
this.group.selectAll('*').remove();
|
||||||
|
|
||||||
// console.log('guilloche:changes', changes);
|
|
||||||
|
|
||||||
if (this.graphService.isAnimated) {
|
if (this.graphService.isAnimated) {
|
||||||
console.log('is animated');
|
this.bounce = this.math.bounce(0, 600, 3);
|
||||||
// this.graphService.startAnimation();
|
this.initialNodes = this.graph.nodes.slice();
|
||||||
this.animationInterval = setInterval(() => this.animateGraph(), this.config.spread.spacing);
|
this.animationInterval = setInterval(() => this.animateGraph(), 100);
|
||||||
} else {
|
} else {
|
||||||
if (this.animationInterval) {
|
if (this.animationInterval) {
|
||||||
console.log('not animated');
|
this.bounce = null;
|
||||||
// this.graphService.stopAnimation();
|
|
||||||
clearInterval(this.animationInterval);
|
clearInterval(this.animationInterval);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const points = [
|
this.guillocheChanged();
|
||||||
|
this.spreadLines([
|
||||||
this.graph.start.point,
|
this.graph.start.point,
|
||||||
...this.graph.nodes,
|
...this.graph.nodes,
|
||||||
this.graph.end.point
|
this.graph.end.point
|
||||||
];
|
]);
|
||||||
this.spreadLines(points);
|
|
||||||
this.guillocheChanged();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private animateGraph() {
|
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);
|
||||||
|
|
||||||
|
this.graph.nodes.splice(medianIndex, 1, bouncedMedian);
|
||||||
this.group.selectAll('*').remove();
|
this.group.selectAll('*').remove();
|
||||||
this.graph = this.animationService.animate(this.graph);
|
this.spreadLines([
|
||||||
const points = [
|
|
||||||
this.graph.start.point,
|
this.graph.start.point,
|
||||||
...this.graph.nodes,
|
...this.graph.nodes,
|
||||||
this.graph.end.point
|
this.graph.end.point,
|
||||||
];
|
]);
|
||||||
this.spreadLines(points);
|
this.debugBounce(bouncedMedian);
|
||||||
}
|
|
||||||
|
|
||||||
public guillocheChanged() {
|
|
||||||
this.guillocheChange.emit(this.el.nativeElement);
|
|
||||||
}
|
|
||||||
|
|
||||||
private drawGraph(points: Point[]): void {
|
|
||||||
this.group.append('path')
|
|
||||||
.attr('d', Shape.line()
|
|
||||||
.x(p => p.x)
|
|
||||||
.y(p => p.y)
|
|
||||||
.curve(Shape.curveBasis)(points))
|
|
||||||
.attr('stroke', this.graph.color)
|
|
||||||
.attr('stroke-width', this.graph.stroke)
|
|
||||||
.attr('fill', 'none');
|
|
||||||
|
|
||||||
if (env.grid) {
|
|
||||||
this.showGrid();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private spreadLines(points: Point[]) {
|
private spreadLines(points: Point[]) {
|
||||||
@@ -146,7 +110,7 @@ export class GuillocheDirective implements OnChanges, OnInit {
|
|||||||
shiftedMedians.push(genshiftedMedians.next().value);
|
shiftedMedians.push(genshiftedMedians.next().value);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (env.grid) {
|
if (env.debug) {
|
||||||
[medianPoint, ...shiftedMedians].forEach((point, index) => {
|
[medianPoint, ...shiftedMedians].forEach((point, index) => {
|
||||||
this.group.append('circle')
|
this.group.append('circle')
|
||||||
.attr('cx', point.x)
|
.attr('cx', point.x)
|
||||||
@@ -164,7 +128,26 @@ export class GuillocheDirective implements OnChanges, OnInit {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private showGrid() {
|
private drawGraph(points: Point[]): void {
|
||||||
|
this.group.append('path')
|
||||||
|
.attr('d', Shape.line()
|
||||||
|
.x(p => p.x)
|
||||||
|
.y(p => p.y)
|
||||||
|
.curve(Shape.curveBasis)(points))
|
||||||
|
.attr('stroke', this.graph.color)
|
||||||
|
.attr('stroke-width', this.graph.stroke)
|
||||||
|
.attr('fill', 'none');
|
||||||
|
|
||||||
|
if (env.debug) {
|
||||||
|
this.debugGraph();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public guillocheChanged() {
|
||||||
|
this.guillocheChange.emit(this.el.nativeElement);
|
||||||
|
}
|
||||||
|
|
||||||
|
private debugGraph() {
|
||||||
this.graph.nodes.forEach((point, index) => {
|
this.graph.nodes.forEach((point, index) => {
|
||||||
const circle = this.group.append('g');
|
const circle = this.group.append('g');
|
||||||
|
|
||||||
@@ -184,4 +167,15 @@ export class GuillocheDirective implements OnChanges, OnInit {
|
|||||||
.text(index);
|
.text(index);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private debugBounce(point: Point): void {
|
||||||
|
if (env.debug) {
|
||||||
|
this.group.append('circle')
|
||||||
|
.attr('cx', point.x)
|
||||||
|
.attr('cy', point.y)
|
||||||
|
.attr('r', 2)
|
||||||
|
.attr('fill-opacity', 0.4)
|
||||||
|
.attr('fill', 'darkgray');
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -88,6 +88,16 @@ export class MathService {
|
|||||||
return Object.assign(this.centerOfPoints(p1, p2), { ascent: radians });
|
return Object.assign(this.centerOfPoints(p1, p2), { ascent: radians });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public medianOfCurve(curve: Point[]) {
|
||||||
|
const genMedian = this.medianPoint(curve);
|
||||||
|
const p1 = genMedian.next().value;
|
||||||
|
const p2 = genMedian.next().value;
|
||||||
|
const p3 = genMedian.next().value;
|
||||||
|
const radians = this.angleRadians(p2, p3);
|
||||||
|
|
||||||
|
return Object.assign(p1, { ascent: radians });
|
||||||
|
}
|
||||||
|
|
||||||
public angleRadians(p1: Point, p2: Point) {
|
public angleRadians(p1: Point, p2: Point) {
|
||||||
return Math.atan2(p2.y - p1.y, p2.x - p1.x);
|
return Math.atan2(p2.y - p1.y, p2.x - p1.x);
|
||||||
}
|
}
|
||||||
@@ -112,6 +122,33 @@ export class MathService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generator for sine bounce
|
||||||
|
*
|
||||||
|
* @param start 0 indicates to initiate with positive numbers, 1 indicates to
|
||||||
|
* start with negative numbers first
|
||||||
|
* @param amplitude default to 1 indicates the amplitude in positive as well
|
||||||
|
* in negative range
|
||||||
|
* @param decimals amount of decimal places
|
||||||
|
*/
|
||||||
|
|
||||||
|
public *bounce(
|
||||||
|
start: number = 0,
|
||||||
|
amplitude: number = 1,
|
||||||
|
decimals: number = 1
|
||||||
|
) {
|
||||||
|
const power = Math.pow(10, decimals);
|
||||||
|
const step = 1 / (power);
|
||||||
|
let index = start;
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
const radians = Math.PI * step * index;
|
||||||
|
yield Math.round((Math.sin(radians) * amplitude) * power) / power;
|
||||||
|
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public *flipSign() {
|
public *flipSign() {
|
||||||
let sign = 1;
|
let sign = 1;
|
||||||
|
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
export const environment = {
|
export const environment = {
|
||||||
production: true,
|
production: true,
|
||||||
|
grid: false,
|
||||||
guilloche: {
|
guilloche: {
|
||||||
colors: {
|
colors: {
|
||||||
primary: '#F8485E',
|
primary: '#F8485E',
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
export const environment = {
|
export const environment = {
|
||||||
production: false,
|
production: false,
|
||||||
grid: true,
|
debug: false,
|
||||||
guilloche: {
|
guilloche: {
|
||||||
colors: {
|
colors: {
|
||||||
primary: '#950952',
|
primary: '#950952',
|
||||||
@@ -37,7 +37,7 @@ export const environment = {
|
|||||||
nodes: 5,
|
nodes: 5,
|
||||||
stroke: 0.7,
|
stroke: 0.7,
|
||||||
spread: {
|
spread: {
|
||||||
amount: 36,
|
amount: 10,
|
||||||
spacing: 32
|
spacing: 32
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user