diff options
13 files changed, 189 insertions, 31 deletions
diff --git a/frontend/src/app/_elements/gradient-background/gradient-background.component.css b/frontend/src/app/_elements/gradient-background/gradient-background.component.css new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/frontend/src/app/_elements/gradient-background/gradient-background.component.css diff --git a/frontend/src/app/_elements/gradient-background/gradient-background.component.html b/frontend/src/app/_elements/gradient-background/gradient-background.component.html new file mode 100644 index 00000000..3f30c35e --- /dev/null +++ b/frontend/src/app/_elements/gradient-background/gradient-background.component.html @@ -0,0 +1 @@ +<div #holder style="position: fixed; z-index: -1;" [ngStyle]="{'background': color}"></div>
\ No newline at end of file diff --git a/frontend/src/app/_elements/gradient-background/gradient-background.component.spec.ts b/frontend/src/app/_elements/gradient-background/gradient-background.component.spec.ts new file mode 100644 index 00000000..969c73b7 --- /dev/null +++ b/frontend/src/app/_elements/gradient-background/gradient-background.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { GradientBackgroundComponent } from './gradient-background.component'; + +describe('GradientBackgroundComponent', () => { + let component: GradientBackgroundComponent; + let fixture: ComponentFixture<GradientBackgroundComponent>; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ GradientBackgroundComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(GradientBackgroundComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/frontend/src/app/_elements/gradient-background/gradient-background.component.ts b/frontend/src/app/_elements/gradient-background/gradient-background.component.ts new file mode 100644 index 00000000..1414bc60 --- /dev/null +++ b/frontend/src/app/_elements/gradient-background/gradient-background.component.ts @@ -0,0 +1,47 @@ +import { AfterViewInit, Component, ElementRef, Input, OnInit, ViewChild } from '@angular/core'; + +@Component({ + selector: 'app-gradient-background', + templateUrl: './gradient-background.component.html', + styleUrls: ['./gradient-background.component.css'] +}) +export class GradientBackgroundComponent implements AfterViewInit { + + @ViewChild('holder') holderRef!: ElementRef; + private holder!: HTMLDivElement; + + + @Input() colorHorizontal1 = 'rgba(0, 8, 45, 0.5)'; + @Input() colorHorizontal2 = 'rgba(0, 52, 89, 0.5)'; + + @Input() colorVertical1 = 'rgba(0, 52, 89, 0.5)'; + @Input() colorVertical2 = 'rgba(0, 152, 189, 0.5)'; + + constructor() { } + + color: string = this.gradientHorizontal(); + + private width = 0; + private height = 0; + + gradientHorizontal(): string { + return `linear-gradient(90deg, ${this.colorHorizontal1} 0%, ${this.colorHorizontal2} 50%, ${this.colorHorizontal1} 100%), linear-gradient(0deg, ${this.colorVertical1} 0%, ${this.colorVertical2} 100%)`; + } + + resize() { + this.width = window.innerWidth; + this.height = window.innerHeight; + + this.holder.style.width = this.width + 'px'; + this.holder.style.height = this.height + 'px'; + } + + ngAfterViewInit(): void { + this.holder = <HTMLDivElement>this.holderRef.nativeElement; + + window.addEventListener('resize', () => this.resize()); + this.resize(); + + } + +} diff --git a/frontend/src/app/_elements/reactive-background/reactive-background.component.html b/frontend/src/app/_elements/reactive-background/reactive-background.component.html index 756952fb..c63dd6ac 100644 --- a/frontend/src/app/_elements/reactive-background/reactive-background.component.html +++ b/frontend/src/app/_elements/reactive-background/reactive-background.component.html @@ -1 +1 @@ -<canvas id="bgCanvas" width="200" height="200" style="position: fixed; z-index: -1;"></canvas>
\ No newline at end of file +<canvas #bgCanvas width="200" height="200" style="position: fixed; z-index: -1;"></canvas>
\ No newline at end of file diff --git a/frontend/src/app/_elements/reactive-background/reactive-background.component.ts b/frontend/src/app/_elements/reactive-background/reactive-background.component.ts index 980e3e6f..9d7f5522 100644 --- a/frontend/src/app/_elements/reactive-background/reactive-background.component.ts +++ b/frontend/src/app/_elements/reactive-background/reactive-background.component.ts @@ -1,14 +1,17 @@ -import { Component, Input, OnInit } from '@angular/core'; +import { AfterViewInit, Component, ElementRef, Input, OnInit, ViewChild } from '@angular/core'; @Component({ selector: 'app-reactive-background', templateUrl: './reactive-background.component.html', styleUrls: ['./reactive-background.component.css'] }) -export class ReactiveBackgroundComponent implements OnInit { +export class ReactiveBackgroundComponent implements AfterViewInit { + + @ViewChild('bgCanvas') canvasRef!: ElementRef; @Input() numPoints: number = 450; @Input() speed: number = 0.001; // 0-1 + @Input() scrollSpeed: number = 1; @Input() maxSize: number = 6; @Input() minDistance: number = 0.07; //0-1 @@ -25,8 +28,8 @@ export class ReactiveBackgroundComponent implements OnInit { private height = 200; private ratio = 1; - private canvas?: HTMLCanvasElement; - private ctx?: CanvasRenderingContext2D; + private canvas!: HTMLCanvasElement; + private ctx!: CanvasRenderingContext2D; private time: number = 0; @@ -35,14 +38,22 @@ export class ReactiveBackgroundComponent implements OnInit { private mouseX = 0; private mouseY = 0; - ngOnInit(): void { - + ngAfterViewInit(): void { document.addEventListener('mousemove', (e) => { this.mouseX = e.clientX / this.width; this.mouseY = e.clientY / this.height; }) - this.canvas = (<HTMLCanvasElement>document.getElementById('bgCanvas')); + document.addEventListener('mouseleave', _ => { + this.mouseX = -1; + this.mouseY = -1; + }) + + document.addEventListener('scroll', (e) => { + this.scrollBackground(e); + }) + + this.canvas = (<HTMLCanvasElement>this.canvasRef.nativeElement); const ctx = this.canvas.getContext('2d'); if (ctx) { this.ctx = ctx; @@ -68,17 +79,28 @@ export class ReactiveBackgroundComponent implements OnInit { }, 1000 / 60); } + private lastScrollY: number = 0; + + scrollBackground(e: Event) { + const scrolledAmount = window.scrollY - this.lastScrollY; + this.points.forEach((point) => { + point.y = point.y - (scrolledAmount / this.height) * this.scrollSpeed; + this.keepPointWithinBounds(point); + }) + this.lastScrollY = window.scrollY; + } + drawBackground() { if (!this.ctx || !this.canvas) return; this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height); - this.ctx.fillStyle = this.bgColor; - this.ctx.fillRect(0, 0, this.width, this.height); + //this.ctx.fillStyle = this.bgColor; + //this.ctx.fillRect(0, 0, this.width, this.height); this.points.forEach((point, index) => { + this.updatePoint(point); this.drawLines(point, index); this.drawPoint(point); - this.updatePoint(point); }); //this.drawPoint(new Point(this.mouseX, this.mouseY, 12, 0)); @@ -94,11 +116,12 @@ export class ReactiveBackgroundComponent implements OnInit { const dist = this.distance(p.x, p.y, otherPoint.x, otherPoint.y); if (dist < this.minDistance) { const h = HEX[Math.round((1 - dist / this.minDistance) * 16)] - this.ctx!.strokeStyle = this.lineColor + h + h; - this.ctx!.beginPath(); - this.ctx!.moveTo(p.x * this.width, p.y * this.height); - this.ctx!.lineTo(otherPoint.x * this.width, otherPoint.y * this.height); - this.ctx!.stroke(); + this.ctx.strokeStyle = this.lineColor + h; + this.ctx.lineWidth = this.maxSize / 2; + this.ctx.beginPath(); + this.ctx.moveTo(p.x * this.width, p.y * this.height); + this.ctx.lineTo(otherPoint.x * this.width, otherPoint.y * this.height); + this.ctx.stroke(); } i++; @@ -108,7 +131,7 @@ export class ReactiveBackgroundComponent implements OnInit { drawPoint(p: Point) { this.ctx!.fillStyle = this.pointColor; this.ctx!.beginPath(); - this.ctx!.arc(p.x * this.width, p.y * this.height, p.size, 0, 2 * Math.PI); + this.ctx!.arc(p.x * this.width, p.y * this.height, p.size * this.screenDepth(p.x), 0, 2 * Math.PI); this.ctx!.fill(); } @@ -140,22 +163,33 @@ export class ReactiveBackgroundComponent implements OnInit { p.x -= ((mx - p.x) / distToCursor) / 500; p.y -= ((my - p.y) / distToCursor) / 500; - const grd = this.ctx!.createLinearGradient(p.x * this.width, p.y * this.height, mx * this.width, my * this.height); - grd.addColorStop(0, this.cursorLineColor + 'ff'); + const grd = this.ctx.createLinearGradient(p.x * this.width, p.y * this.height, mx * this.width, my * this.height); + const alpha = HEX[Math.round(p.size / this.maxSize * (HEX.length - 1))]; + grd.addColorStop(0, this.cursorLineColor + alpha); grd.addColorStop(1, this.cursorLineColor + '00'); - this.ctx!.strokeStyle = grd; - this.ctx!.beginPath(); - this.ctx!.moveTo(p.x * this.width, p.y * this.height); - this.ctx!.lineTo(mx * this.width, my * this.height); - this.ctx!.stroke(); + this.ctx.strokeStyle = grd; + this.ctx.beginPath(); + this.ctx.moveTo(p.x * this.width, p.y * this.height); + this.ctx.lineTo(mx * this.width, my * this.height); + this.ctx.stroke(); } - p.x %= 1; - p.y %= 1; + this.keepPointWithinBounds(p); + } + + keepPointWithinBounds(p: Point) { + p.x = p.x % 1.0; + p.y = p.y % 1.0; + p.x = ((1 - Math.sign(p.x)) / 2) + p.x; + p.y = ((1 - Math.sign(p.y)) / 2) + p.y; } distance(x1: number, y1: number, x2: number, y2: number): number { - return Math.sqrt(((x2 - x1) ** 2) + ((y2 / this.ratio - y1 / this.ratio) ** 2)); + return Math.sqrt(((x2 - x1) ** 2) + ((y2 / this.ratio - y1 / this.ratio) ** 2) / this.screenDepth(x1)) * this.ratio; + } + + screenDepth(x: number): number { + return (1.5 - Math.sin(x * Math.PI)); } } @@ -168,4 +202,4 @@ class Point { ) { } } -const HEX = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'];
\ No newline at end of file +const HEX = ['00', '11', '22', '33', '44', '55', '66', '77', '88', '99', 'aa', 'bb', 'cc', 'dd', 'ee', 'ff'];
\ No newline at end of file diff --git a/frontend/src/app/_pages/playground/playground.component.css b/frontend/src/app/_pages/playground/playground.component.css new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/frontend/src/app/_pages/playground/playground.component.css diff --git a/frontend/src/app/_pages/playground/playground.component.html b/frontend/src/app/_pages/playground/playground.component.html new file mode 100644 index 00000000..5622cd83 --- /dev/null +++ b/frontend/src/app/_pages/playground/playground.component.html @@ -0,0 +1 @@ +<div style="height: 5000px;">
\ No newline at end of file diff --git a/frontend/src/app/_pages/playground/playground.component.spec.ts b/frontend/src/app/_pages/playground/playground.component.spec.ts new file mode 100644 index 00000000..bf66b27e --- /dev/null +++ b/frontend/src/app/_pages/playground/playground.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { PlaygroundComponent } from './playground.component'; + +describe('PlaygroundComponent', () => { + let component: PlaygroundComponent; + let fixture: ComponentFixture<PlaygroundComponent>; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ PlaygroundComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(PlaygroundComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/frontend/src/app/_pages/playground/playground.component.ts b/frontend/src/app/_pages/playground/playground.component.ts new file mode 100644 index 00000000..007a455e --- /dev/null +++ b/frontend/src/app/_pages/playground/playground.component.ts @@ -0,0 +1,15 @@ +import { Component, OnInit } from '@angular/core'; + +@Component({ + selector: 'app-playground', + templateUrl: './playground.component.html', + styleUrls: ['./playground.component.css'] +}) +export class PlaygroundComponent implements OnInit { + + constructor() { } + + ngOnInit(): void { + } + +} diff --git a/frontend/src/app/app-routing.module.ts b/frontend/src/app/app-routing.module.ts index e22f7a88..8aadb8bf 100644 --- a/frontend/src/app/app-routing.module.ts +++ b/frontend/src/app/app-routing.module.ts @@ -14,6 +14,7 @@ import { PredictComponent } from './_pages/predict/predict.component'; import { FilterDatasetsComponent } from './_pages/filter-datasets/filter-datasets.component'; import { ExperimentComponent } from './experiment/experiment.component'; import { TrainingComponent } from './training/training.component'; +import { PlaygroundComponent } from './_pages/playground/playground.component'; const routes: Routes = [ { path: '', component: HomeComponent, data: { title: 'Početna strana' } }, @@ -28,6 +29,7 @@ const routes: Routes = [ { path: 'browse-datasets', component: FilterDatasetsComponent, data: { title: 'Javni izvori podataka' } }, { path: 'browse-predictors', component: BrowsePredictorsComponent, data: { title: 'Javni trenirani modeli' } }, { path: 'predict/:id', component: PredictComponent, data: { title: 'Predvidi vrednosti' } }, + { path: 'playground', component: PlaygroundComponent, data: { title: 'Zabava' } } ]; @NgModule({ diff --git a/frontend/src/app/app.component.html b/frontend/src/app/app.component.html index daf93cc1..1bd207e1 100644 --- a/frontend/src/app/app.component.html +++ b/frontend/src/app/app.component.html @@ -1,5 +1,9 @@ -<app-reactive-background [bgColor]="'#003459'" [lineColor]="'#00a8e8'" [pointColor]="'#cfeffb'" - [cursorLineColor]="'#888888'" [numPoints]="300"> +<app-gradient-background></app-gradient-background> +<app-reactive-background [speed]="0.0005" [scrollSpeed]="0.25" [minDistance]="0.1" [maxSize]="4" [cursorDistance]="0.07" [lineColor]="'#00a8e8'" [pointColor]="'rgba(0, 188, 252, 0.33)'" [cursorLineColor]="'#00a8e8'" [numPoints]="200"> +</app-reactive-background> +<app-reactive-background [speed]="0.0008" [scrollSpeed]="0.5" [minDistance]="0.12" [maxSize]="6" [cursorDistance]="0.09" [lineColor]="'#00a8e8'" [pointColor]="'rgba(0, 188, 252, 0.66)'" [cursorLineColor]="'#00a8e8'" [numPoints]="100"> +</app-reactive-background> +<app-reactive-background [speed]="0.001" [scrollSpeed]="1" [minDistance]="0.14" [maxSize]="8" [cursorDistance]="0.12" [lineColor]="'#00a8e8'" [pointColor]="'rgba(0, 188, 252, 1)'" [cursorLineColor]="'#00a8e8'" [numPoints]="50"> </app-reactive-background> <app-navbar></app-navbar> <div class="container h-100"> diff --git a/frontend/src/app/app.module.ts b/frontend/src/app/app.module.ts index c4f89ad8..26417373 100644 --- a/frontend/src/app/app.module.ts +++ b/frontend/src/app/app.module.ts @@ -48,6 +48,8 @@ import { TrainingComponent } from './training/training.component'; import { ItemExperimentComponent } from './_elements/item-experiment/item-experiment.component'; import { YesNoDialogComponent } from './_modals/yes-no-dialog/yes-no-dialog.component'; import { Configuration } from './configuration.service'; +import { PlaygroundComponent } from './_pages/playground/playground.component'; +import { GradientBackgroundComponent } from './_elements/gradient-background/gradient-background.component'; export function initializeApp(appConfig: Configuration) { return () => appConfig.load(); @@ -87,7 +89,9 @@ export function initializeApp(appConfig: Configuration) { GraphComponent, TrainingComponent, ItemExperimentComponent, - YesNoDialogComponent + YesNoDialogComponent, + PlaygroundComponent, + GradientBackgroundComponent ], imports: [ BrowserModule, |