nativescript-angular icon indicating copy to clipboard operation
nativescript-angular copied to clipboard

Animation freeze then router change with clearHistory: true

Open 3DtuningProduction opened this issue 5 years ago • 1 comments

I have NativeScript Angular application And have Animation Endless rotation of points in a circle

import { AfterViewInit, Component, ElementRef, Input, OnDestroy, OnInit, ViewChild } from '@angular/core';
import { Label } from '@nativescript/core/ui/label'; 
import { AbsoluteLayout } from '@nativescript/core/ui/layouts/absolute-layout';
import { GridLayout } from '@nativescript/core/ui/layouts/grid-layout';
import * as application from 'tns-core-modules/application';
import { Color } from 'tns-core-modules/color';
import { Page } from 'tns-core-modules/ui/page';
import { DeviceService, FooterService, LoggerService } from '../../services';
import { AnimationDefinition } from '@nativescript/core/ui/animation';
import * as animationModule from '@nativescript/core/ui/animation';
import { RouterExtensions } from 'nativescript-angular/router';

@Component({
    selector: 'app-body-wrapper',
    templateUrl: './body-wrapper.component.html',
    styleUrls: ['./body-wrapper.component.scss'] 
})
export class BodyWrapperComponent implements OnInit, OnDestroy, AfterViewInit {
public static circleStep: number = 200;
public static circleStartRadius: number = 640;
public static circleSizes: number[] = [32, 22, 12];
public static circleColors: string[] = ['#fb9c00', '#003aa1', '#ffffff'];

@Input('pageTitle') public readonly pageTitle: string;
@Input('footerStatus') public readonly footerStatus: boolean;
@Input('animation') public readonly animation: boolean;

@ViewChild('mainWrapper', { static: true }) public readonly mainWrapper: ElementRef;
@ViewChild('animateLayout', { static: true }) public readonly animateLayout: ElementRef;


private _pageWrapper: AbsoluteLayout;
private _allAnimations: any = {};
private _allInterface: Label[] = [];

constructor(
    private readonly _page: Page,
    private readonly _deviceService: DeviceService,
    private readonly _footerService: FooterService,
    private readonly _loggerService: LoggerService,
    private readonly _router: RouterExtensions
) {
    // this._page.actionBarHidden = true;
    if (!this._deviceService.device.isIOS) {
        const window: any = application.android.startActivity.getWindow();
        window.setStatusBarColor(new Color('#f88600').android);
    }

    if (this._deviceService.device.deviceType !== 'Tablet') {
        BodyWrapperComponent.circleStep = 100;
        BodyWrapperComponent.circleStartRadius = 320;
        BodyWrapperComponent.circleSizes = [16, 11, 6];
    }
}


public ngOnDestroy(): void {
    if (this._allAnimations) {
        for (const key in this._allAnimations) {
            for (const key2 in this._allAnimations[key]) {
                if ((this._allAnimations[key][key2] as animationModule.Animation).isPlaying)
                this._allAnimations[key][key2].cancel();
                this._allAnimations[key][key2] = null;
            }
        }
    }

    if (this._pageWrapper) {
        for (let i: number = 0; i < this._pageWrapper.getChildrenCount(); i++) {
            this._pageWrapper.removeChild(this._pageWrapper.getChildAt(i));
        }
    }

    for (let item of this._allInterface) {
        item = null;
    }
}

public ngAfterViewInit(): void {
    if (this.animation) {
        setTimeout(() => {
            this._pageWrapper = this.animateLayout.nativeElement;
            for (let i: number = 0; i < 4; i++) {
                this._createWrapper(i);
            }
        }, 1000)

    }
}

private _randomIntFromInterval(min: number, max: number): number {
    return Math.floor(Math.random() * (max - min + 1) + min);
}

private _createWrapper(index: number): void {
    // console.log('fire->call', index);
    let height: number = (this.mainWrapper.nativeElement as GridLayout).getMeasuredHeight() / this._deviceService.device.screen.mainScreen.scale;
    if (height === 0) {
        height = this._deviceService.device.screen.mainScreen.heightDIPs
    }
    let offset: number = 0;
    if (this._deviceService.device.isIOS) {
        offset = application.ios.window.safeAreaInsets.top;
    }
    const section: Label = new Label();
    section.borderColor = '#003aa1';
    section.borderWidth = 1;
    section.width = BodyWrapperComponent.circleStep * (index + 1) + BodyWrapperComponent.circleStartRadius;
    section.height = BodyWrapperComponent.circleStep * (index + 1) + BodyWrapperComponent.circleStartRadius;
    section.borderRadius = BodyWrapperComponent.circleStep * (index + 1) + BodyWrapperComponent.circleStartRadius;
    section.top = height / 2 - section.height / 2 - offset;
    section.left = this._deviceService.device.screen.mainScreen.widthDIPs / 2 - section.width / 2;
    this._pageWrapper.addChild(section);
    this._allInterface.push(section);
    for (let i: number = 0; i < 3; i++) {
        this._createCircle(i, index);
    }
}

private _createCircle(circleIndex: number, wrapperIndex: number): void {
    let offset: number = 0;
    if (this._deviceService.device.isIOS) {
        offset = application.ios.window.safeAreaInsets.top;
    }
    let height: number = (this.mainWrapper.nativeElement as GridLayout).getMeasuredHeight() / this._deviceService.device.screen.mainScreen.scale;
    if (height === 0) {
        height = this._deviceService.device.screen.mainScreen.heightDIPs
    }
    const angle: number = this._randomIntFromInterval(0, 360);
    const radius: number = (BodyWrapperComponent.circleStep * (wrapperIndex + 1) + BodyWrapperComponent.circleStartRadius) / 2;
    const circlePosition: { x: number; y: number } = this._getPosition(radius, angle);
    const startPosition: { x: number; y: number } = {
        x: this._deviceService.device.screen.mainScreen.widthDIPs / 2,
        y: height / 2 - offset
    };
    const circleSize: number = BodyWrapperComponent.circleSizes[circleIndex];

    const circle: Label = new Label();
    circle.width = circleSize;
    circle.height = circleSize;
    circle.borderRadius = circleSize;
    circle.backgroundColor = BodyWrapperComponent.circleColors[circleIndex];
    circle.translateX = startPosition.x + circlePosition.x - circleSize / 2;
    circle.translateY = startPosition.y + circlePosition.y - circleSize / 2;
    circle.opacity = 0;
    this._pageWrapper.addChild(circle);
    this._animateCircle(circle, angle, circleIndex, wrapperIndex, this._randomIntFromInterval(10, 200));
    this._allInterface.push(circle);
}

private _getPosition(radius: number, angle: number): { x: number; y: number } {
    return {
        x: radius * Math.cos((angle * Math.PI) / 180),
        y: radius * Math.sin((angle * Math.PI) / 180)
    };
}

private _animateCircle(circle: Label, angle: number, circleIndex: number, wrapperIndex: number, duration: number): void {
    let newAngle: number = angle + 0.5;
    if (newAngle > 360) {
        newAngle = 0;
    }

    let height: number = (this.mainWrapper.nativeElement as GridLayout).getMeasuredHeight() / this._deviceService.device.screen.mainScreen.scale;
    if (height === 0) {
        height = this._deviceService.device.screen.mainScreen.heightDIPs
    }
    let offset: number = 0;
    if (this._deviceService.device.isIOS) {
        offset = application.ios.window.safeAreaInsets.top;
    }
    const radius: number = (BodyWrapperComponent.circleStep * (wrapperIndex + 1) + BodyWrapperComponent.circleStartRadius) / 2;
    const startPosition: { x: number; y: number } = {
        x: this._deviceService.device.screen.mainScreen.widthDIPs / 2,
        y: height / 2 - offset
    };

    const circleSize: number = BodyWrapperComponent.circleSizes[circleIndex];
    const circlePosition: { x: number; y: number } = this._getPosition(radius, angle);

    const animateSettings: AnimationDefinition = {
        translate: {
            x: startPosition.x + circlePosition.x - circleSize / 2,
            y: startPosition.y + circlePosition.y - circleSize / 2
        },
        iterations: 1,
        duration,
        target: circle
    }

    if (circle.opacity === 0) {
        animateSettings.opacity = 1;
    }

    if (!this._allAnimations[wrapperIndex]) {
        this._allAnimations[wrapperIndex] = {};
    }

    if (this._allAnimations[wrapperIndex][circleIndex]) {
        (this._allAnimations[wrapperIndex][circleIndex] as animationModule.Animation).cancel();
        (this._allAnimations[wrapperIndex][circleIndex] as animationModule.Animation) = null;
    }
    // Animation

    (this._allAnimations[wrapperIndex][circleIndex] as animationModule.Animation) = new animationModule.Animation([animateSettings]);
    (this._allAnimations[wrapperIndex][circleIndex] as animationModule.Animation).play().then(() => {
        this._animateCircle(circle, newAngle, circleIndex, wrapperIndex, duration);
    }).catch(() => {
        this._loggerService.log('stop');
    });
}
}

On page change - the application hangs

  this._router.navigate ([item.url], {
         clearHistory: true,
         transition: {
             name: 'slideLeft'
         }
     });

But if you remove clearHistory: true then everything is fine

But if you remove the history clearing, this will not be a good result of the application.

How can this problem be corrected?

Thank you in advance

3DtuningProduction avatar Jul 28 '20 20:07 3DtuningProduction

3DtuningProduction how are you? do you solve this?.

if you reply to me I will be grateful to you and I can send money by PayPal.

Nexeuz avatar May 21 '22 01:05 Nexeuz