I didn't like some transitions and animations so now they work a lot better. Should probably be refactored at some point

merge-notes
isark 2 years ago
parent b101524105
commit 35e2ba31b4

@ -5,3 +5,4 @@
<color-picker [initialColor]="'#00000010'" (color)="planColor = $event">Click me for color picker!</color-picker> <color-picker [initialColor]="'#00000010'" (color)="planColor = $event">Click me for color picker!</color-picker>
</div> </div>

@ -1,5 +1,6 @@
import { APP_INITIALIZER, NgModule } from "@angular/core"; import { APP_INITIALIZER, NgModule } from "@angular/core";
import { BrowserModule } from "@angular/platform-browser"; import { BrowserModule} from "@angular/platform-browser";
import { BrowserAnimationsModule } from "@angular/platform-browser/animations";
import { AppComponent } from "./app.component"; import { AppComponent } from "./app.component";
import { FormsModule } from "@angular/forms"; import { FormsModule } from "@angular/forms";
@ -8,7 +9,6 @@ import { PlanDisplayModule } from "./plan-display/plan-display.module";
import { ConfigService } from "./services/config.service"; import { ConfigService } from "./services/config.service";
import { ColorPickerComponent } from './color-picker/color-picker.component'; import { ColorPickerComponent } from './color-picker/color-picker.component';
import { MatButtonModule } from "@angular/material/button"; import { MatButtonModule } from "@angular/material/button";
import { CarouselComponent } from './carousel/carousel.component';
export function initializeApp(configService: ConfigService) { export function initializeApp(configService: ConfigService) {
return (): Promise<any> => { return (): Promise<any> => {
@ -26,6 +26,7 @@ export function initializeApp(configService: ConfigService) {
FormsModule, FormsModule,
PlanDisplayModule, PlanDisplayModule,
MatButtonModule, MatButtonModule,
BrowserAnimationsModule,
], ],
providers: [ providers: [
{ {

@ -1,18 +1,19 @@
<ng-container *ngIf="template && slides"> <ng-container *ngIf="template && slides">
<div class="carousel"> <div class="carousel">
<div class="window" [style.translate]="translation()" #carouselWindow [style.grid-template-columns]="templateColumns()"> <div class="window" [style.translate]="translation()" #carouselWindow
[@direction]="{value: this.animation, params: {directionTime: directionTime}}" [ngStyle]="style()" (@direction.done)="onAnimationEnd($event)" (@direction.start)="onAnimationStart($event)">
<span hidden>current: {{current}}</span> <span hidden>current: {{current}}</span>
<ng-container *ngFor="let visible of visibleSlides"> <ng-container *ngFor="let visible of visibleSlides">
<div class="slide" #slideElement [attr.data-slideIndex]="visible.index" [style.grid-column-start]="visible.index + 1">
<div [class]="vertical ? 'slide-vertical' : 'slide'" #slideElement
[attr.data-slideIndex]="visible.index"
[ngStyle]="vertical ? {'grid-row-start':visible.index + 1} : {'grid-column-start':visible.index + 1}">
<ng-container *ngTemplateOutlet="template!; context: { $implicit: slides[visible.index] }"> <ng-container *ngTemplateOutlet="template!; context: { $implicit: slides[visible.index] }">
</ng-container> </ng-container>
</div> </div>
</ng-container> </ng-container>
</div> </div>
</div> </div>
<div class="controls">
<button (click)="prev()">&lt;=prev</button>
<button (click)="next()">next&gt;</button>
</div>
</ng-container> </ng-container>

@ -14,19 +14,30 @@
grid-template-rows: 1; grid-template-rows: 1;
} }
.controls { .slide-vertical {
position: absolute; background-color: green;
top: 10%; grid-template-columns: 1;
} }
.window { .window {
transition: 1s;
display: grid; display: grid;
grid-template-columns: repeat(3, 1fr);
grid-auto-flow: column;
width: 100%; width: 100%;
height: 100%;
} }
// .window {
// grid-template-columns: repeat(3, 1fr);
// grid-auto-flow: column;
// }
// .window-vertical {
// grid-template-rows: repeat(3, 1fr);
// grid-auto-flow: row;
// }
.current { .current {
background-color: magenta; background-color: magenta;
} }

@ -1,3 +1,5 @@
import { animate, keyframes, state, style, transition, trigger } from '@angular/animations';
import { NgStyle } from '@angular/common';
import { AfterViewInit, ChangeDetectorRef, Component, ContentChild, ElementRef, EventEmitter, Input, OnInit, Output, QueryList, TemplateRef, ViewChild, ViewChildren } from '@angular/core'; import { AfterViewInit, ChangeDetectorRef, Component, ContentChild, ElementRef, EventEmitter, Input, OnInit, Output, QueryList, TemplateRef, ViewChild, ViewChildren } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser'; import { BrowserModule } from '@angular/platform-browser';
import { Subject, debounceTime } from 'rxjs'; import { Subject, debounceTime } from 'rxjs';
@ -11,6 +13,23 @@ import { Subject, debounceTime } from 'rxjs';
BrowserModule BrowserModule
], ],
animations: [ animations: [
trigger('direction', [
state('vertical', style({
'grid-auto-flow': 'row',
})),
state('horizontal', style({
'grid-auto-flow': 'column',
})),
state('hidden', style({
opacity: 0,
})),
state('unhidden', style({
opacity: 1,
})),
transition('* => hidden', animate(`{{directionTime}}ms`)),
transition('hidden => unhidden', animate(`{{directionTime}}ms`)),
transition('unhidden => *', animate(0)),
])
] ]
}) })
export class CarouselComponent implements OnInit, AfterViewInit { export class CarouselComponent implements OnInit, AfterViewInit {
@ -27,6 +46,10 @@ export class CarouselComponent implements OnInit, AfterViewInit {
intersectionObserver?: IntersectionObserver; intersectionObserver?: IntersectionObserver;
visibleSlides?: IntersectingSlide[]; visibleSlides?: IntersectingSlide[];
increasing: boolean = true; increasing: boolean = true;
vertical: boolean = true;
angularAnimating: boolean = false;
animation: string = 'vertical';
directionTime: number = 0;
private debouncedOnchange: Subject<void> = new Subject<void>(); private debouncedOnchange: Subject<void> = new Subject<void>();
@ -141,7 +164,6 @@ export class CarouselComponent implements OnInit, AfterViewInit {
{ {
const intersecting = this.visibleSlides?.filter(e => e.currentlyIntersecting).sort((e1, e2) => e1.index - e2.index); const intersecting = this.visibleSlides?.filter(e => e.currentlyIntersecting).sort((e1, e2) => e1.index - e2.index);
const lowestIntersecting = intersecting![0]; const lowestIntersecting = intersecting![0];
console.log("lowest intersecting: ", lowestIntersecting?.index);
this.visibleSlides = this.visibleSlides?.filter(e => e.index + 2 >= lowestIntersecting!.index && e.index >= this.current - 2); this.visibleSlides = this.visibleSlides?.filter(e => e.index + 2 >= lowestIntersecting!.index && e.index >= this.current - 2);
} }
@ -149,47 +171,71 @@ export class CarouselComponent implements OnInit, AfterViewInit {
const intersecting = this.visibleSlides?.filter(e => e.currentlyIntersecting).sort((e1, e2) => e1.index - e2.index).reverse(); const intersecting = this.visibleSlides?.filter(e => e.currentlyIntersecting).sort((e1, e2) => e1.index - e2.index).reverse();
const highestIntersecting = intersecting![0] const highestIntersecting = intersecting![0]
console.log("highest intersecting: ", highestIntersecting?.index);
this.visibleSlides = this.visibleSlides?.filter(e => e.index - 2 <= highestIntersecting!.index && e.index <= this.current + 2); this.visibleSlides = this.visibleSlides?.filter(e => e.index - 2 <= highestIntersecting!.index && e.index <= this.current + 2);
} }
} }
translation() { translation() {
let num = (this.current - 1) * (-1 / 3) * 100; let num = (this.current - 1) * (-1 / 3) * 100;
if (this.vertical) {
return `0 ${num}%`
} else {
return `${num}% 0` return `${num}% 0`
} }
}
left(index: number) { templateValue() {
if (this.window.nativeElement) { const len = this.slides?.length;
const width = this.window.nativeElement.clientWidth; return `repeat(${len}, minmax(calc(100% / 3), 1fr))`;
const slideWidth = width / 3.0;
const slideLeft = Math.round(index * slideWidth);
return `${slideLeft}px !important`;
} }
return 0; // .window {
// grid-template-columns: repeat(3, 1fr);
// grid-auto-flow: column;
// }
// .window-vertical {
// grid-template-rows: repeat(3, 1fr);
// grid-auto-flow: row;
// }
style() {
let style: any = {
};
// let num = (index) * 33.333333; if (this.vertical) {
// return `${num}%` style['grid-template-rows'] = this.templateValue();
} else {
style['grid-template-columns'] = this.templateValue();
} }
width(index: number) { if (!this.angularAnimating) {
if (this.window.nativeElement) { style.transition = '500ms';
const width = this.window.nativeElement.clientWidth; }
const slideWidth = Math.round(width / 3.0);
return `${slideWidth}px !important`; return style;
} }
let num = 33.33333333; onAnimationEnd(event: any) {
return `${num}% !important` if (event.toState == 'hidden') {
this.vertical = !this.vertical;
this.animation = 'unhidden';
}
else if (event.toState == 'unhidden') {
this.animation = this.vertical ? 'vertical' : 'horizontal';
} else {
this.angularAnimating = false;
}
}
onAnimationStart(event: any) {
this.angularAnimating = true;
} }
templateColumns() { changeDirection() {
const len = this.slides?.length; this.animation = 'hidden';
const value = `repeat(${len}, minmax(calc(100% / 3), 1fr))`;
return value;
} }
} }
interface IntersectingSlide { interface IntersectingSlide {

@ -4,7 +4,7 @@
#targetRef> #targetRef>
<ng-container *ngIf="plan"> <ng-container *ngIf="plan">
<carousel [slides]="slides" (afterInitSelf)="registerCarousel($event)"> <carousel [slides]="slides" (afterInitSelf)="registerCarousel($event)" #caro>
<ng-template let-slide> <ng-template let-slide>
{{slide}} {{slide}}
</ng-template> </ng-template>
@ -13,6 +13,16 @@
</ng-container> </ng-container>
</div> </div>
<div *ngIf="carouselComponent" class="controls">
<button (click)="carouselComponent.prev()">&lt;=prev</button>
<button (click)="carouselComponent.next()">next&gt;</button>
<button (click)="carouselComponent.changeDirection()">toggle direction</button>
<div class="slidecontainer">
Direction change time: {{carouselComponent.directionTime}}<br>
<input type="range" min="0" max="1000" [(ngModel)]="carouselComponent.directionTime" class="slider" id="myRange">
</div>
</div>
<ngx-moveable [target]="targetRef" [draggable]="draggable" [resizable]="true" (drag)="onDrag($event)" <ngx-moveable [target]="targetRef" [draggable]="draggable" [resizable]="true" (drag)="onDrag($event)"
(resize)="onResize($event)" (dragEnd)="onDragEnd($event)" (resizeEnd)="onResizeEnd($event)"></ngx-moveable> (resize)="onResize($event)" (dragEnd)="onDragEnd($event)" (resizeEnd)="onResizeEnd($event)"></ngx-moveable>
</ng-container> </ng-container>

@ -11,3 +11,8 @@
flex: 1 1 auto; flex: 1 1 auto;
} }
} }
.controls {
position: absolute;
top: 0;
}

@ -3,6 +3,7 @@ import { CommonModule } from '@angular/common';
import { NgxMoveableComponent } from 'ngx-moveable'; import { NgxMoveableComponent } from 'ngx-moveable';
import { PlanDisplayComponent } from './plan-display.component'; import { PlanDisplayComponent } from './plan-display.component';
import { CarouselComponent } from '../carousel/carousel.component'; import { CarouselComponent } from '../carousel/carousel.component';
import { FormsModule } from '@angular/forms';
@NgModule({ @NgModule({
@ -12,7 +13,8 @@ import { CarouselComponent } from '../carousel/carousel.component';
imports: [ imports: [
CommonModule, CommonModule,
NgxMoveableComponent, NgxMoveableComponent,
CarouselComponent CarouselComponent,
FormsModule
], ],
exports: [ exports: [
PlanDisplayComponent PlanDisplayComponent

Loading…
Cancel
Save