Angular实现数字向上滚动效果组件

大屏中数据刷新要求像电表一样滚动更新效果。 由于大屏中使用较多,选择封装为一个可复用组件。主要思想: 将宿主组件传入的值,分解为独立的数字和小数点,每个数字Dom由宿主css样式决定宽度,并生成一个子级的滑块,通过数字的大小设置transition进行滚动。效果如下:
在这里插入图片描述

html部分:
为了满足数字滚动时先滚动一圈,然后在滚动到对应值的需求(避免0值无动画),numberSlider滑块中重复了一遍0~9。

<span class="data_updateable">
    <span *ngFor="let item of valueList;" [ngSwitch]="item" class="dataWrapper">
            <span *ngSwitchCase="'.'" class="dot">{
    
    {
    
    item}}</span>
            <span *ngSwitchDefault class="numberItem">
                <!-- 占位 宽度自适应 -->
                <span style="visibility: hidden">{
    
    {
    
    item}}</span>
                <span class="numberSlider" [@dataUpdate] ='item'>01234567890123456789</span>
            </span>
    </span>
</span>

ts部分:
将宿主传入的值生成数组, 由ngFor遍历生成对应Dom

import {
    
     Component, OnInit, OnChanges, Input} from '@angular/core';
import {
    
     AnimationDataUpdate } from '@/animations/animation-dataUpdate';

@Component({
    
    
    selector: 'app-data-updateable',
    templateUrl: './data-updateable.component.html',
    styleUrls: ['./data-updateable.component.less'],
    animations: [AnimationDataUpdate]
})
export class DataUpdateableComponent implements OnInit, OnChanges {
    
    
    @Input() value: number;
    public valueList: string[] = [];
    
    constructor( ) {
    
     }

    ngOnInit() {
    
    
    }
    
    ngOnChanges() {
    
    
        if (this.value) {
    
    
            this.valueList = this.value.toString().split('');
        }
    }
}

css部分:
numberSlider滑块中文本排列方式为writing-mode: vertical-rl; 竖直排列,便于滚动处理

.data_updateable {
    
    
    display: flex;
    height: 100%;
    flex-direction: row;
    justify-content: flex-end;
    user-select: none;
    .dataWrapper {
    
    
        display: flex;
        align-items: center;
        height: 100%;
        .dot {
    
    
            display: inline-block;
            height: 100%;
            line-height: 100%;
            vertical-align: top;
        }
        .numberItem {
    
    
            position: relative;
            display: inline-block;
            height: 100%;
            overflow: hidden;
            .numberSlider {
    
    
                position: absolute;
                writing-mode: vertical-rl;
                text-orientation: upright;
                top: -2px;
                left: 50%;
                transform: translate(-50%, 0);
                transition: transform 2s ease-in-out;
            }
        }
    }
}

dataUpdate中的动画部分
设定每个值的滚动距离(每个值先滚动一圈,然后在滚动到对应的值)

import {
    
     trigger, state, transition, animate, style, } from '@angular/animations';

export const AnimationDataUpdate = trigger('dataUpdate', [
    state('0', style({
    
    
        transform: 'translate(-50%, -50%)'
    })),
    state('1', style({
    
    
        transform: 'translate(-50%, -55%)'
    })),
    state('2', style({
    
    
        transform: 'translate(-50%, -60%)'
    })),
    state('3', style({
    
    
        transform: 'translate(-50%, -65%)'
    })),
    state('4', style({
    
    
        transform: 'translate(-50%, -70%)'
    })),
    state('5', style({
    
    
        transform: 'translate(-50%, -75%)'
    })),
    state('6', style({
    
    
        transform: 'translate(-50%, -80%)'
    })),
    state('7', style({
    
    
        transform: 'translate(-50%, -85%)'
    })),
    state('8', style({
    
    
        transform: 'translate(-50%, -90%)'
    })),
    state('9', style({
    
    
        transform: 'translate(-50%, -95%)'
    })),
])

最后在宿主中调用方式
number为传入组件的值

<app-data-updateable [value]="number"></app-data-updateable> 

因为前台需要30s更新一次数据,而数据库中10min中才发生变化,所以每次数据更新不是根据当前值进行滚动,而是从0重新开始,避免10分钟数据都没有变化。若需每次数字不从0重新渲染,则需要Dom不重绘。

猜你喜欢

转载自blog.csdn.net/PGD_607/article/details/105160401
今日推荐