140行代码实现时钟翻牌器

前言

时钟翻牌器效果大家或多或少都有见过,有了解过的人应该知道他的大致实现原理,理解简单,代码不简单。本文从另一个角度出发,用140行代码实现时钟翻牌器,并且你也可以扩展出不同的用法。

先来看一下效果

结尾有完整代码地址

正文

实现的原理:将翻牌的效果一分为二,第一步是翻牌,第二步是变数字,在翻页动作快要结束的时候变化数字就能达到翻牌器的效果。

实现翻牌效果

  1. 第一步实现两卡片贴合在一起翻转

核心代码很简单:

卡片1从0到-180deg,卡片2从180deg到0deg

tsx 复制代码
  /** 上一次的数字下标 */
  const [lastNumInd, setLastNumInd] = useState<NumItem>(order === 'asc' ? value : ((9 - value) as NumItem));
  /** 当前的数字下标 */
  const [currentNumInd, setCurrentNumInd] = useState<NumItem>(order === 'asc' ? value : ((9 - value) as NumItem));

  const baseStyle = useMemo(() => {
    return {
      transition: 'transform 0.5s linear',
      transform: `rotateX(0deg)`,
    };
  }, []);

  /** 预备滚动样式*/
  const preScrollStyle = useMemo(() => {
    return {
      transition: 'transform 0.5s linear',
      transform: `rotateX(-180deg)`,
    };
  }, []);

  /** 滚动样式*/
  const scrollStyle = useMemo(() => {
    return {
      transform: `rotateX(180deg)`,
    };
  }, []);


  return (
      <Frame>
        {Array.from({ length: 10 }).map((num, index) => {
          return (
            <Card
              key={index}
              style={currentNumInd == index ? baseStyle : lastNumInd === index ? preScrollStyle : scrollStyle}
            >
              {order === 'asc' ? index : 9 - index}
            </Card>
          );
        })}
      </Frame>
  );

还有在卡片样式中添加一个很重要的样式代码,将背面面对我们的元素隐藏起来

css 复制代码
  //元素的背面在 3D 变换中是否可见。
  backface-visibility:hidden;

接下来将最外层元素的背景设置为跟卡片一样的颜色,这样在翻转的时候背景就有颜色了。到这里基本就已经完成了。

变化数字

在第一步的结尾可以看到,显示的数字总是少一半,接下来我们只要把那一半的数字补上就行了。

再加一个额外的卡片,前一半时间显示原数字,后一半时间显示要变化的数字。这样完整的效果就出来了。

核心代码

tsx 复制代码
  const changeNum = (newValue: NumItem) => {
    let pref = currentNumInd;
    let result = newValue;
    setLastNumInd(pref);
    setCurrentNumInd((order === 'asc' ? result : 9 - result) as NumItem);
    //毫秒级时间戳
    let startTime = dayjs().valueOf();
    let time: any = null;
    const fn = () => {
      let endTime = dayjs().valueOf();
      let diffTime = endTime - startTime;
      if (diffTime >= 280) {
        setResultNum(result);
        cancelAnimationFrame(time);
        return;
      }
      time = requestAnimationFrame(fn);
    };
    fn();
  };

  return (
    <>
      <Frame>
        {/* 真正的屏幕上的数字 */}
        <Card>{resultNum}</Card>
        {/* 只为模拟9个数字卡片 */}
        {Array.from({ length: 10 }).map((num, index) => {
          return (
            <Card
              key={index}
               style={currentNumInd == index ? baseStyle : lastNumInd === index ? preScrollStyle : scrollStyle}
            >
              {order === 'asc' ? index : 9 - index}
            </Card>
          );
        })}
      </Frame>
    </>
  );

一共140行代码,轻松拿下。

额外扩展

我这边就扩展了递减

tsx 复制代码
export type NumItem = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9;
interface Props {
  /** 正序还是倒序*/
  order?: 'asc' | 'desc'; //asc:正序,desc:倒序
  value: NumItem;
}
  1. 递增
  1. 递减
  1. 设置步长

这个不用通过Props设置,直接设置传入的value就可以了

封装为时钟翻牌器

页面多显示几个翻牌器,对应时分秒的十位和个位。然后对时间进行监听,设置对应的值即可,远程地址里也有代码。

结语

感兴趣的可以去试试

远程仓库地址: gitee.com/lin-zhiteng...

相关推荐
我爱加班、、15 分钟前
Chrome安装最新vue-devtool插件
javascript·vue.js·chrome·vue-devtool
weixin_4738947727 分钟前
前端服务器部署分类总结
前端·网络·性能优化
LuckyLay1 小时前
React百日学习计划-Grok3
前端·学习·react.js
澄江静如练_1 小时前
小程序 存存上下滑动的页面
前端·javascript·vue.js
互联网搬砖老肖1 小时前
Web 架构之会话保持深度解析
前端·架构
m0_513962531 小时前
vue-ganttastic甘特图label标签横向滚动固定方法
javascript·vue.js·甘特图
菜鸟una1 小时前
【taro3 + vue3 + webpack4】在微信小程序中的请求封装及使用
前端·vue.js·微信小程序·小程序·typescript·taro
hao_04131 小时前
elpis-core: 基于 Koa 实现 web 服务引擎架构设计解析
前端
码农黛兮_462 小时前
HTML、CSS 和 JavaScript 基础知识点
javascript·css·html
狂野小青年2 小时前
npm 报错 gyp verb `which` failed Error: not found: python2 解决方案
前端·npm·node.js