所用技术为: React.js、css3
本效果用的是CSS3 transition 属性

transition 属性设置元素当过渡效果,四个简写属性为:

描述
transition-property 指定CSS属性的name,transition效果
transition-duration transition效果需要指定多少秒或毫秒才能完成
transition-timing-function 指定transition效果的转速曲线
transition-delay 定义transition效果开始的时候

我把0~9的数字全部列出来,排成一列,然后再根据需要展示的数字去对这个数字列进行 定位 ,再利用 transition 过渡效果实现数字切换动画。
如图所示:

首先是布局代码,将0~9的数字排列出来

<div className="number-animation-wrap">
        <div className="number-animation-wrap-hidden">0</div>
        <div className="number-animation" style={style}>
          <div className="number">0</div>
          <div className="number">1</div>
          <div className="number">2</div>
          <div className="number">3</div>
          <div className="number">4</div>
          <div className="number">5</div>
          <div className="number">6</div>
          <div className="number">7</div>
          <div className="number">8</div>
          <div className="number">9</div>

设置样式:
overflow: hidden; 超出隐藏
transition: top 0.2s实现过渡动画

@defaultSize: 16;
.number-animation-wrap {
    position: relative;
    display: inline-block;
    overflow: hidden;
    .number-animation {
        position: absolute;
        left: 0;
        top: 0;
        height: auto;
        transform-origin: 0 0;
        transition: top 0.2s;//过渡属性的名称 过渡动画所需的时间
    .number,.number-animation-wrap-hidden {
        line-height: unit((36/@defaultSize),rem);
        font-size: unit((36/@defaultSize),rem);
        font-weight: bold;
        text-align: center;
    .number-animation-wrap-hidden{
        visibility: hidden;

根据要显示的数字value计算出要偏移的距离,
利用top对布局中的数字列表进行定位,展示对应的数字:

   let style = {
      top: (-1 * value * this.lineHeight / this.defaultSize) + 'rem'

随着value的变化,动态地生成样式并设置到数字列表div上

    <div className="number-animation" style={style}>

我将其封装成了组件,可以很方便的调用,可以根据需要进行组装:

import NumberAnimation from "../../src/numberAnimation";
<div style={{textAlign:"center",fontSize: "36px",fontWeight: "bold"}}>
    <div style={{margin:"2rem 0"}}>
       倒计时 <NumberAnimation value={this.state.number} />
    <div style={{margin:"2rem 0"}}>
            this.state.number2.toFixed(2).toString().replace(".",":").split("").map((numberItem, index) => {
                return (
                    <NumberAnimation key={index} value={numberItem} />
    <div style={{margin:"2rem 0"}}>
            this.state.number4.toString().split("").map((numberItem, index) => {
                return (
                    <NumberAnimation key={index} value={numberItem} />
    <div style={{margin:"2rem 0"}}>
            this.state.number.toString().split("").map((numberItem, index) => {
                return (
                    <NumberAnimation key={index} value={numberItem} />
    <div style={{margin:"2rem 0"}}>
            this.state.number2.toFixed(2).toString().split("").map((numberItem, index) => {
                return (
                    <NumberAnimation key={index} value={numberItem} />
    <div style={{margin:"2rem 0"}}>
            this.state.number3.toFixed(2).toString().split("").map((numberItem, index) => {
                return (
                    <NumberAnimation key={index} value={numberItem} />
        <button onClick={()=>{this.setState({
            number3: Math.random()*Math.random()*100
        })}}> 点击切换数字</button>
//NumberAnimation.js
import React, { Component } from 'react';
import '../../../less/numberAnimation.less'
class NumberAnimation extends Component {
  constructor(props) {
    super(props);
    this.state = {
      height : 36
  render() {
    const { value } = this.props;
    if (isNaN(value)) {//非数字
      if (value == '.') {
        return (
          <div className="number-animation-wrap">
            <div className="number-animation-wrap-hidden">.</div>
            <div className="number-animation">
              <div className="number">{value}</div>
      else {
        return ''
    let height = document.getElementsByClassName("number").length && document.getElementsByClassName("number")[0].offsetHeight;
    if(height != this.state.height){
      this.setState({
        height : height
    let style = {
      top: (-1 * value * this.state.height) + 'px'
    return (
      <div className="number-animation-wrap">
        <div className="number-animation-wrap-hidden">0</div>
        <div className="number-animation" style={style}>
          <div className="number">0</div>
          <div className="number">1</div>
          <div className="number">2</div>
          <div className="number">3</div>
          <div className="number">4</div>
          <div className="number">5</div>
          <div className="number">6</div>
          <div className="number">7</div>
          <div className="number">8</div>
          <div className="number">9</div>
export default NumberAnimation;
//style.less
@defaultSize: 16;
.number-animation-wrap {
    position: relative;
    display: inline-block;
    overflow: hidden;
    .number-animation {
        position: absolute;
        left: 0;
        top: 0;
        height: auto;
        transform-origin: 0 0;
        transition: top 0.2s;//过渡属性的名称 过渡动画所需的时间
    .number,.number-animation-wrap-hidden {
        line-height: unit((36/@defaultSize),rem);
        font-size: unit((36/@defaultSize),rem);
        font-weight: bold;
        text-align: center;
    .number-animation-wrap-hidden{
        visibility: hidden;

调用示例文件

//numberAnimationPage.js
import React, { Component } from "react";
import NumberAnimation from "../../src/numberAnimation";
class NumberAnimationPage extends Component {
    constructor(props) {
        super(props);
        this.state = {
            number: 0,
            number2: 0,
            number3: 0
        this.number = 0;
        this.number2 = 0;
    componentDidMount() {
        setInterval(() => {
            console.log(1)
            this.setState({
                number: this.number++,
                number2: this.number2 += 0.01
        }, 1000)
    render() {
        return (
            <div style={{textAlign:"center"}}>
                <div style={{margin:"2rem 0"}}>
                    <NumberAnimation value={this.state.number} />
                <div style={{margin:"2rem 0"}}>
                        this.state.number.toString().split("").map((numberItem, index) => {
                            return (
                                <NumberAnimation key={index} value={numberItem} />
                <div style={{margin:"2rem 0"}}>
                        this.state.number2.toFixed(2).toString().split("").map((numberItem, index) => {
                            return (
                                <NumberAnimation key={index} value={numberItem} />
                <div style={{margin:"2rem 0"}}>
                        this.state.number3.toFixed(2).toString().split("").map((numberItem, index) => {
                            return (
                                <NumberAnimation key={index} value={numberItem} />
                    <button onClick={()=>{this.setState({
                        number3: Math.random()*Math.random()*100
                    })}}> 点击切换数字</button>
module.exports = NumberAnimationPage;
  • 本组件是以单个数字形式进行展示,可以供使用者灵活组装
  • 组件中过滤了传入值为非数字的情况,支持用于展示整数、小数

大家有什么建议,或者其他的实现思路,欢迎在评论区分享。

路由切换动画 因为项目的需求,需要在路由切换的时候,加入一些比较 zb 的视觉效果,所以研究了一下。把这些学习的过程记录下来,以便以后回顾。同时也希望这些内容能够帮助一些跟我一样的菜鸟,让他们少走些坑。可能我对代码的表述不是很到位,希望大家不要介意。机智的你们一定可以看明白。 参考内容: react 路由动画 react-router Switch 组件 react 动画插件 1.插件依赖 使用的插件是react-transition-group。先简单介绍一下动画插件的使用方式。 CSSTransition这个组件有两个比较主要的属性:key和in。 in:Boolean
用于ReactCSS封装解决方案 为了解决css封装的问题,主要有两种方法,css-modules和css-in-js。 但是,它们两个都有很大的问题。 开发人员的体验不好,这意味着您经常需要编写比实现简单样式所期望的更多的代码。 使用react-scoped-css,您可以编写已知的普通CSS,同时具有CSS封装的优势! 它是如何工作的 将您CSS写入以.scoped.css结尾的文件中(也支持scss和sass ) /* Title.scoped.css */ . title { background : # 999 ; color import React, { Component } from 'react'; class Boss extends Component { constructor(props) { super(props); this.state = { isShow:true this.toTogger=this.toTogger.bind(this) render() { return ( &lt;span class="flip-number" data-num="2"&gt;&lt;/span&gt; &lt;span class="flip-number" data-num="3"&gt;&lt;/span&gt; &lt;span class="flip-number" data-num="4
高阶函数是接受另一个函数作为参数或返回一个函数作为返回值或两者兼有的函数。const firstOrderFunc = () => console.log('hello, i am a first order function'); const higherOrder = (ReturnFirstOrderFunc) => ReturnFirstOrderFu...
自定义 view--Menu 菜单 - Android - 掘金一、前言 第一次写博客,不知道什么姿势才能显示出一副好像很老练的样子。老大让写一个菜单栏控件,借鉴了Idtk自定义view,站在巨人的肩上... 自定义对话框 - Android - 掘金可以自定义风格,还可以用它实现下载可以自定义进入退出动画等 新版本的对话框封... 仿新...
CSS 计数器的妙用:数字递增动效 CSS 计数器是由 CSS 维护的变量,这些变量可根据 CSS 规则增加从而跟踪使用次数。我们可以利用这个特性,根据文档位置来调整内容表现,比如显示列表编号。 最近在公司官网就用到了这个特性: image.png image.png 因为这里的序号只是个装饰,并不强调先后顺序。比起使用真实 DOM 元素显示序号,CSS 计数器更加简洁灵活,万一内容顺序需要调整,序号也不受影响。 有时候我们会看到某些 Dashboard 界面有数字快速滚动的效果,比如招行 App 的账户余
React 组件封装 Hook 可以让我们更方便地在函数组件中复用组件逻辑。下面是一些封装组件为 Hook 的示例代码: 1. 使用 useState 封装计数器组件: ```javascript import { useState } from 'react'; const useCounter = (initialCount = 0, step = 1) => { const [count, setCount] = useState(initialCount); const increment = () => setCount(count + step); const decrement = () => setCount(count - step); return { count, increment, decrement }; export default useCounter; 使用示例: ```javascript import useCounter from './useCounter'; function Counter() { const { count, increment, decrement } = useCounter(); return ( <p>Count: {count}</p> <button onClick={increment}>+</button> <button onClick={decrement}>-</button> 2. 使用 useEffect 封装鼠标位置跟踪组件: ```javascript import { useState, useEffect } from 'react'; const useMousePosition = () => { const [position, setPosition] = useState({ x: 0, y: 0 }); useEffect(() => { const updateMousePosition = (event) => { setPosition({ x: event.clientX, y: event.clientY }); document.addEventListener('mousemove', updateMousePosition); return () => { document.removeEventListener('mousemove', updateMousePosition); }, []); return position; export default useMousePosition; 使用示例: ```javascript import useMousePosition from './useMousePosition'; function MouseTracker() { const { x, y } = useMousePosition(); return ( Mouse position: {x}, {y} 以上是两个简单的示例,通过封装 React 组件为 Hook,可以让我们更好地复用组件逻辑并在函数组件中使用。
解决DevTools failed to load SourceMap: Could not load content for ***.js.map: HTTP error: code 404 问题 喵喵侠w: 最好的做法是,去github找到map文件,放到同名js目录下。