CSS翻牌器

翻牌器

先封装一个类:

export default class Flipper {
    isFlipping = false;
    flipNode: Element;
    frontNode: HTMLElement | null;
    backNode: HTMLElement | null;
    duration = 600;

    constructor(node: Element, currentTime: string, nextTime: string) {
        this.flipNode = node;
        this.frontNode = node.querySelector('.front');
        this.backNode = node.querySelector('.back');
        this.setFrontTime(currentTime);
        this.setBackTime(nextTime);
    }

    setFrontTime(time: string) {
        this.frontNode!.dataset.number = time;
    }

    setBackTime(time: string) {
        this.backNode!.dataset.number = time;
    }

    flipDown(currentTime: string, nextTime: string) {
        if (this.isFlipping) {
            return false;
        }
        this.isFlipping = true;
        this.setFrontTime(currentTime);
        this.setBackTime(nextTime);
        this.flipNode.classList.add('running');
        setTimeout(() => {
            this.flipNode.classList.remove('running');
            this.isFlipping = false;
            this.setFrontTime(nextTime);
        }, this.duration);
    }
}

源代码如下:

<template>
    <div class="clock">
        <div v-for="(item, index) in [...formatter].length" :key="index" class="flip">
            <div class="digital front" data-number="0"></div>
            <div class="digital back" data-number="1"></div>
        </div>
    </div>
</template>

<script lang="ts">
import { onMounted, watch, toRefs, ref } from 'vue';
// 引用上面的类
import Flipper from '@/logic/flipper';

export default {
    name: 'CardFlipper',
    props: {
        dayVolumeOfBusiness: {
            type: String || Number,
            default: '00000000',
        },
    },
    setup(props: any) {
        const { dayVolumeOfBusiness } = toRefs(props);
        const formatter = ref('NNNNNNNN');
        watch(dayVolumeOfBusiness, (newProps) => {
            if (newProps) {
                dayVolumeOfBusiness.value = newProps;
                initFlipper();
            }
        });

        const initFlipper = async () => {
            let flips = document.querySelectorAll('.flip');
            let result = [];
            // 判断返回的字数是否有[...formatter.value].length个,否则就需要补充0
            if (dayVolumeOfBusiness.value.toString().length < [...formatter.value].length) {
                const data = dayVolumeOfBusiness.value.split('').reverse();
                for (let i = 0; i < [...formatter.value].length; i += 1) {
                    if (!data[i]) data[i] = '0';
                }
                result = data.reverse().join('');
            } else {
                result = dayVolumeOfBusiness.value;
            }
            const nowTimeStr = result;
            const nextTimeStr = result;
            let flippers = Array.from(flips).map(
                (flip, i) => new Flipper(flip, nowTimeStr[i], nextTimeStr[i])
            );
            for (let i = 0; i < flippers.length; i++) {
                flippers[i].flipDown(nowTimeStr[i], nextTimeStr[i]);
            }
        };

        onMounted(() => {
            initFlipper();
        });
        return {
            formatter,
        };
    },
};
</script>

<style lang="scss" scoped>
body {
    display: flex;
    justify-content: center;
    align-items: center;
    height: 100vh;
}

.clock {
    display: flex;

    .flip {
        position: relative;
        width: 36px;
        height: 47px;
        margin: 0 8px;
        font-size: 46px;
        line-height: 47px;
        text-align: center;

        // basic
        .digital {
            &::before,
            &::after {
                position: absolute;
                content: attr(data-number);
                left: 0;
                right: 0;
                color: rgb(255 197 91 / 100%);
                background: url(@/assets/img/flipper.png) no-repeat;
                overflow: hidden;
                perspective: 160px;
                font-family: DIN-Medium;
            }

            &::before {
                top: 0;
                bottom: 50%;
                border-radius: 0 0 6px 6px;
            }

            &::after {
                top: 50%;
                bottom: 0;
                line-height: 0;
                border-radius: 6px 6px 0 0;
            }
        }

        // stack
        .back::before,
        .front::after {
            z-index: 1;
        }

        .front::before {
            z-index: 3;
        }

        .back::before {
            opacity: 0;
            transition: all 0.6s;
        }

        // animation
        .back::after {
            transform-origin: center top;
            transform: rotateX(0.5turn);
            opacity: 0;
            z-index: 2;
        }

        &.running {
            .front::before {
                transform-origin: center bottom;
                animation: front-flip-down 0.6s ease-in-out;
                box-shadow: 0 -2px 6px rgb(255 255 255 / 30%);
                backface-visibility: hidden;
            }

            .back::before {
                opacity: 1;
            }

            .back::after {
                animation: back-flip-down 0.6s ease-in-out;
            }
        }
    }
}

@keyframes front-flip-down {
    to {
        transform: rotateX(0.5turn);
    }
}

@keyframes back-flip-down {
    to {
        transform: rotateX(0);
        opacity: 1;
    }
}
</style>

效果如下:
在这里插入图片描述

参考链接

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
CSS实现翻牌效果动画可以使用CSS 3D转换和CSS动画来实现。以下是实现的步骤: 1. 创建一个容,用于包含翻转的两个面。 2. 给容添加一个透视效果,使其能够呈现出三维效果。 ``` .container { perspective: 1000px; } ``` 3. 创建两个面,分别用于显示正面和背面的内容,并将它们放置在容中。 ``` <div class="container"> <div class="card"> <div class="front">正面</div> <div class="back">背面</div> </div> </div> ``` 4. 使用CSS 3D转换将背面旋转180度,并设置初始状态为不可见。 ``` .card { transform-style: preserve-3d; transition: all 0.5s ease; } .back { transform: rotateY(180deg); display: none; } ``` 5. 使用CSS动画在容的鼠标悬停事件时触发翻转效果,并切换正反面的可见状态。 ``` .container:hover .card { transform: rotateY(180deg); } .container:hover .card .front { display: none; } .container:hover .card .back { display: block; } ``` 完整的代码如下: ``` <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>翻牌效果动画</title> <style> .container { perspective: 1000px; width: 200px; height: 200px; } .card { position: relative; width: 100%; height: 100%; transform-style: preserve-3d; transition: all 0.5s ease; } .front, .back { position: absolute; top: 0; left: 0; width: 100%; height: 100%; backface-visibility: hidden; } .front { background-color: #e74c3c; color: #fff; } .back { background-color: #2ecc71; color: #fff; transform: rotateY(180deg); display: none; } .container:hover .card { transform: rotateY(180deg); } .container:hover .card .front { display: none; } .container:hover .card .back { display: block; } </style> </head> <body> <div class="container"> <div class="card"> <div class="front">正面</div> <div class="back">背面</div> </div> </div> </body> </html> ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值