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...

相关推荐
Aliex_git11 分钟前
性能优化 - 构建体积优化
前端·javascript·笔记·学习·性能优化
QT 小鲜肉12 分钟前
【Linux命令大全】003.文档编辑之comm命令(实操篇)
linux·运维·服务器·javascript·chrome·笔记
千里马-horse17 分钟前
Rect Native bridging 源码分析--Array.h
javascript·c++·react native·react.js·bridging
xiaoxue..19 分钟前
React 之 自定义 Hooks
前端·javascript·react.js·面试·前端框架
华仔啊20 分钟前
JavaScript 防抖和节流的区别是什么?如何实现?
前端·javascript
Anesthesia丶27 分钟前
React学习笔记
笔记·学习·react.js
想唱rap1 小时前
缓冲区的理解和实现
java·服务器·前端·c++·python
勤奋的小米蜂1 小时前
vscode 自带终端无法正常执行例如npm命令---解决办法
前端·vue.js·vscode·npm
你怎么知道我是队长1 小时前
C语言---作用域
c语言·开发语言·javascript
Wpa.wk1 小时前
接口测试-多层嵌套响应处理-JSONPath使用(Java版)
java·前端·经验分享·python·测试工具·jsonpath