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不重绘。

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值