带动画的事件时间线

IT技术 javascript css reactjs
2021-03-20 13:45:53

我试图构建的是一个带有一些动画的垂直时间线组件。我尝试的动画是从第一个圆圈开始,无论哪个项目状态为真,垂直线将从上到下绘制,同时当线穿过它时,完成的步骤将从圆形变为完成的复选标记。

我如何才能实现上述动画,到目前为止我已经尝试过但不知道如何实现上述动画。

我究竟想达到这个

沙盒

任何帮助表示赞赏。

3个回答

我已经修改了您的沙箱以使其正常工作:https : //codesandbox.io/s/animable-timeline-reactjs-tiofz

  1. 对于动画,我使用了以下 CSS:


    为了动画实际时间线,我们将从第一个条目中删除垂直条,并且只会有一个选中的圆圈。从第二个条目开始,我们将有一个垂直条和选中的圆圈。为了使它们保持一致,它们已向上移动。为了显示进度,条形将填充,然后将检查圆圈。

  2. 转换App为有状态组件,以便我们可以维护动画状态。在构造函数中,为每个条目增加idstartAnim以及checked状态。在这里,我们将设置startAnim标志以在相应的 TimelineConnector 上启动动画。checked用于控制对圆圈的勾选。

  3. TimelineConnector如果this.props.startAnim为 true,设置类中为 green-progress 还添加了onAnimationEnd处理程序作为{() => this.props.onAnimDone(this.props.id)}. 这告诉 App 组件动画是在这个组件上完成的id

  4. TimelineDot用于props.event.checked设置检查状态。

  5. In App 添加了一个生命周期钩子componentDidMount,当所有组件被添加到实际 DOM 时,它会被调用。在钩子中,您选中第一个圆圈并在第一个 TimelineConnector 上开始动画。

  6. 当 TimelineConnector 完成动画时,它会startNextAnim在应用程序中调用在该方法中,您首先完成最后一个条目的复选标记。如果条目有 ,则开始下一个动画status:true


我们可以为每个动画添加延迟并立即运行它们。但是父级控制每个组件,每个组件在动画完成时通知,使得更新代码更加灵活。您可以根据状态为每个条目设置不同的动画。

我们可以使用 react-spring 动画库,但事情会变得复杂。CSS 动画是最简单的解决方案。
感谢您提供详细信息,我将完成此操作,如果有任何信息,我会更新,感谢您的帮助和信息:)
2021-05-07 13:45:53
@ onkar,对此stackoverflow.com/questions/70157795/ 有任何帮助...
2021-05-08 13:45:53

你可以试试这个

/* timeline css */
@keyframes fill-color {
  0% {
    height: 0;
  }
  100% {
    height: 100%;
  }
}

@keyframes fill-color1 {
  0% {
    height: 0;
  }
  100% {
    height: 50%;
  }
}
@keyframes scaleup {
  0% {
    transform: scale(0);
  }
  100% {
    transform: scale(1);
  }
}

@keyframes fade {
  0% {
    color: rgba(black, 0.4);
  }
  100% {
    color: rgba(black, 1);
  }
}
body {
  margin: 0;
  padding: 0;
}
.timeline {
  padding: 0;
  list-style: none;
  margin: 32px;
  overflow: hidden;
  position: relative;
}
.details {
  margin-left: 48px;
  border-bottom: 1px solid #f2f2f2;
  min-height: 85px;
  display: flex;
  justify-content: center;
  flex-direction: column;
}
.list,
.list-content {
  position: relative;
  width: 100%;
}
.list-content::before,
.list-content::after {
  content: "";
  display: block;
  position: absolute;
  left: 0;
  transition: 0.2s all linear;
  width: 0.714rem;
  height: 0.714rem;
  border-radius: 50%;
  background-color: gray;
  top: 50%;
  z-index: 3;
  margin-left: 0.35rem;
  margin-top: rem(-8px);
}

.list-content::after {
  z-index: 2;
}
.list {
  position: relative;
  width: 100%;
}

.list.active .list-content:before {
  transform: scale(0);
  width: 17px;
  height: 17px;
  border: 2px solid white;
  background-color: red;
  background-image: url("https://upload.wikimedia.org/wikipedia/commons/thumb/2/27/White_check.svg/2048px-White_check.svg.png");
  background-position: center;
  background-repeat: no-repeat;
  background-size: 9px 7px;
  margin-left: 0;
  margin-top: -8px;
  animation: scaleup 0.4s forwards;
}
.list:before,
.list:after {
  content: "";
  display: block;
  position: absolute;
  left: 0;
  transition: 0.2s all linear;
  width: 0.214rem;
  margin-left: 0.6rem;
}
.list:before {
  background: #f2f2f2;
  height: 100%;
}
.list:after {
  background: red;
  height: 0;
  z-index: 1;
}
.list:before {
  top: -50%;
}
.list.active:after {
  top: 0;
  animation: fill-color 0.4s forwards;
}
.list:last-child:after {
  display: none;
}
.list:last-child.active:after {
  display: block;
  bottom: 50%;
  animation: fill-color1 0.4s forwards;
}
.list:last-child .details {
  border-bottom: none;
}
.list:first-child:before {
  display: none;
}
.list:first-child.active:after {
  animation: fill-color1 0.4s forwards;
  top: 50%;
}
.list:first-child.active:after {
  animation-delay: 1s;
}
.list:first-child.active .list-content:before {
  animation-delay: 0.5s;
}

.list:nth-child(2).active:after {
  animation-delay: 2s;
}
.list:nth-child(2).active .list-content:before {
  animation-delay: 2s;
}

.list:nth-child(3).active:after {
  animation-delay: 3s;
}
.list:nth-child(3).active .list-content:before {
  animation-delay: 3s;
}

.list:nth-child(4).active:after {
  animation-delay: 4s;
}
.list:nth-child(4).active .list-content:before {
  animation-delay: 4.15s;
}
<body>
    <ul class="timeline">
        <li class="list active">
            <div class="list-content">
                <div class="details">
                 <h4 class="status-title">Step 1</h4>
                </div>
            </div>
        </li>
        <li class="list active">
            <div class="list-content">
                <div class="details">
                 <h4 class="status-title">Step 2</h4>
                </div>
            </div>
        </li>
        <li class="list active">
            <div class="list-content">
                <div class="details">
                 <h4 class="status-title">Step 3</h4>
                </div>
            </div>
        </li>
        <li class="list active">
            <div class="list-content">
                <div class="details">
                 <h4 class="status-title">Step 4</h4>
                </div>
            </div>
        </li>
    </ul>
</body>

你也可以检查沙箱

在这里,我active在所有li元素中添加了类,但是如果您想激活两个步骤,则只应用前两个 li(即该类是有条件的)

可以为背景设置动画。请检查下面的示例

.bg {
  min-height: 300px;
  width: 10px;
  background: linear-gradient(0, red, red) no-repeat;
  background-size: 100% 0;
  animation: gradient 15s ease infinite;
}

@keyframes gradient {
    0% {
        background-size: 100% 0;
    }
    100% {
        background-size: 100% 100%;
    }
}
<div class="bg"></div>

您的 TimelineConnector 可以更新为包含该 CSS 类。

当然,你可以为动画添加一个额外的参数,作为从你的 React 脚本中定义的 CSS 变量,它的数量为 item * timeout,类似于:animation: gradient 15s ease infinite var(--timeout);
2021-04-23 13:45:53
谢谢,在这里我已经尝试使线条动画化,但问题是我不知道如何按照 gif 中所示的方式进行动画制作,因为根据数据仅完成了三个动画,所以应该如何绘制线条直到完成步骤那是我无法前进的地方
2021-04-24 13:45:53
要在元素范围内定义 CSS 变量,您可以使用这样的方法: element.style.setProperty('--timeout', '0.5s');
2021-05-02 13:45:53
抱歉,我可能是新手,如果您能提供帮助,您能否像 Gif 一样分享您能够解决的代码和框
2021-05-03 13:45:53
它可以通过项目和一组不同的超时进行循环。示例:codepen.io/alekskorovin/pen/ExvJOrz
2021-05-14 13:45:53