简体   繁体   English

Angular 在对话框中打开时,mat-slider 动画从 100 到 0

[英]Angular mat-slider animate from 100 to 0 when opening in the dialog

I have the angular component that is opened in the dialog.我有在对话框中打开的 angular 组件。 My mat-slide is defined as below:我的 mat-slide 定义如下:

<mat-slider min="0" max="100" [value]="progressBarValue" (change)="changeProgress($event)"></mat-slider>

But when the dialog is opened, the mat slider progress value is animated from 100 to 0, Even though i already set the progressBarValue=0 in the constructor.但是当对话框打开时,mat slider 进度值从 100 变为 0,即使我已经在构造函数中设置了 progressBarValue=0。

I don't know why.我不知道为什么。 My other components showing the same in the template doesn't have such kind of issue.我在模板中显示相同内容的其他组件没有此类问题。

Does anybody met this kind of behavior?有人遇到过这种行为吗? 在此处输入图像描述

I want this to be at 0 without animation from 100 to 0. Please see to the end of the gif.我希望它在 0 没有 animation 从 100 到 0。请看 gif 的末尾。

I minimize the source code as below, still has the same issue我把源代码最小化如下,还是有同样的问题

import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-insert',
  templateUrl: './insert.html',
  styleUrls: ['./insert.scss']
})
export class InsertComponent implements OnInit {

    progressBarValue: number;

    constructor() {
        this.progressBarValue = 0;
    }

    ngOnInit() {
    }

}

In the component html在组件 html

<mat-slider min="0" max="100" [value]="progressBarValue"></mat-slider>

In another component to launch the above component in the dialog在另一个组件中启动上述组件的对话框

        const dialog = {
           currentTime: 0
        };
        const dialogRef = this.dialog.open(InsertComponent, {
            panelClass: 'app-dialog',
            data: dialog,
            autoFocus: false
        });
        dialogRef.afterClosed().subscribe((currentTime) => {
        });

If someone knows why this happens, please let me know.如果有人知道为什么会这样,请告诉我。 Thanks a lot.非常感谢。

The attribute directive ngStyle in combination with the assigned functions, which are used on several different elements of the mat-slider, trigger CSS transformations every time the value of the slider changes:属性指令ngStyle与分配的函数结合使用,这些函数用于 mat-slider 的几个不同元素,每次滑块的值发生变化时都会触发 CSS 转换:

<!-- slider html template excerpt -->
<div class="mat-slider-wrapper" #sliderWrapper>
  <div class="mat-slider-track-wrapper">
    <div class="mat-slider-track-background" [ngStyle]="_trackBackgroundStyles"></div>
    <div class="mat-slider-track-fill" [ngStyle]="_trackFillStyles"></div>
  </div>
  ...
</div>
// slider component excerpt
get _trackBackgroundStyles(): { [key: string]: string } {
    const axis = this.vertical ? 'Y' : 'X';
    const scale = this.vertical ? `1, ${1 - this.percent}, 1` : `${1 - this.percent}, 1, 1`;
    const sign = this._shouldInvertMouseCoords() ? '-' : '';

    return {
      // scale3d avoids some rendering issues in Chrome. See #12071.
      transform: `translate${axis}(${sign}${this._thumbGap}px) scale3d(${scale})`
    };
  }
...

(see full source: MatSlider html source and MatSlider ts source ). (请参阅完整源代码: MatSlider html 源代码MatSlider ts 源代码)。

Due to the way how a component is instantiated and injected into the dialog, a transformation is triggered here during the initialization process.由于组件实例化和注入对话框的方式,在初始化过程中会在此处触发转换。 So in order to achieve your desired behaviour the CSS animations need to be (temporarily) disabled.因此,为了实现您想要的行为,需要(暂时)禁用 CSS 动画。

A (probably very hacky but working) solution is to disable the animation by adding a class to the mat-slider which will remove the transition and remove that class after the initialization completed:一个(可能非常笨拙但有效)的解决方案是通过向mat-slider添加一个类来禁用动画,这将删除过渡并在初始化完成后删除该类:

<!-- insert.component.html -->
<mat-slider [ngClass]="{'disableAnimation':isAnimationDisabled}" min="0" max="100" [(ngModel)]="progressBarValue" (change)="changeProgress($event)"></mat-slider>
/* insert.component.css */
::ng-deep .disableAnimation *{
 transition: none !important;
}
// insert.component.ts
...

@Component({
  ...
})
export class InsertComponent implements AfterViewInit {
  ...  
  isAnimationDisabled: boolean = true;

  ...

  ngAfterViewInit() {
    setTimeout(() => {
      this.isAnimationDisabled = false;
    })
  }
}

Since the initialization process is completed very very quickly in this example you need to use setTimeout, otherwise you'll get an ExpressionChangedAfterItHasBeenCheckedError.因为在这个例子中初始化过程完成得非常快,所以你需要使用 setTimeout,否则你会得到一个 ExpressionChangedAfterItHasBeenCheckedError。 To prevent that you could also change the ChangeDetectionStrategy to OnPush and manually trigger the change detection once the initialization is finished.为了防止这种情况,您还可以将 ChangeDetectionStrategy 更改为 OnPush 并在初始化完成后手动触发更改检测。

I've create a Stackblitz for you to play with.我已经创建了一个Stackblitz供你玩。

To specifically target just the slide animation on the mat-sliders on initialization you can just override the transition for that piece of css.要在初始化时专门针对 mat-slider 上的幻灯片动画,您可以只覆盖那段 css 的过渡。

.mat-slider {
     .mat-slider-thumb-container {
         transition: none;
     }
}

Placed in your component or global stylesheet.放置在您的组件或全局样式表中。

using EventEmitter we can solve this issue使用 EventEmitter 我们可以解决这个问题

HTML File: HTML 档案:

  <div class="price-slider-wrapper" lines="none">
       <ng5-slider color="primary" [(value)]="minPrice" [(highValue)]="maxPrice" 
                      (userChange)="priceSliderChange($event)"
             [options]="premoptions" (click)="$event.stopPropagation();"  [manualRefresh]="manualRefresh">
      </ng5-slider>
 </div> 

TS file: TS文件:

  public manualRefresh = new EventEmitter<void>();
 priceMenuOpen:boolean = false;

  openPriceSlider(){
        this.priceMenuOpen = true;
        setTimeout(() => {
            this.manualRefresh.emit();
        }, 200);
    }

on menu click event called openPriceSlider() function:在名为 openPriceSlider() 的菜单单击事件上 function:

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM