The reason is that both our App native and H5 have similar content card lists, and H5 version is older. The product manager put forward the requirement that H5 should be updated to keep consistent with the STYLE of App. It was supposed to be just a basic style adjustment, but I was so enthusiastic that I copied the details of the favorite animation (what a real and good programmer I am!).

Well, the effect is such an effect, like the need to take away the code ~

Split action

The most difficult thing is that I only have star pictures and no animation design draft, so I can only observe them by naked eyes. I clicked the “Favorites” button on the app more than a hundred times, and split the action in my mind while clicking

  • Fill in the stars and zoom in
  • There are four dots around it that spread out as the star magnifies
  • The circle diffused from the center appears later than the zoom animation
  • The star zooms in and shrinks back to its original position, and the dots around it spread to the maximum and disappear.

To determine the structure

First of all, you need two images, a wireframe and a fill, but of course you can change it to SVG, composite Sprite, etc.

Analyzing the animation elements, I’m going to use a div element to place the stars, and use pseudo-elements ::before and :: After to implement four dots and transparent circles, respectively, as follows.

<div id="star">
   ::before
   ::after
</div>
Copy the code

Give the div body a width and height, and fill the background with a star image. Click to switch the background image. Translucent circles are easier to do, that is, absolute positioning + rounded corners + RGBA background color. Four dots is a bit more complicated. First write a small dot and use box-shadow to copy the four circles. Try to adjust the four circles to the right size and position.

#star{
  position: relative;
  display: inline-block;
  width: 30px;
  height: 30px;
  background-image: url(star.png);
  background-repeat: no-repeat;
  background-size: 100%;
}
#star::before{
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  bottom: 0;
  border-radius: 50%;
  background: rgba(254.208.1.0.1);
}
#star::after{
  content: "";
  position: absolute;
  left: 50%;
  top: 50%;
  width: 10%;
  height: 10%;
  transform: translate(-50%, -50%);
  border-radius: 50%;
  background: transparent;
  box-shadow: 15px -15px 0 #fed001.15px 15px 0 #fed001,
    -15px -15px 0 #fed001, -15px 15px 0 #fed001;
}
Copy the code

Add animation

The process of animation design is based on the split action, roughly planning the key frame, and then repeatedly debugging parameters, to get a satisfactory effect. So let’s just put the code here

/ * * /
@keyframes banuce {
  0% {
    transform: scale(0.8);
  }
  100% {
    transform: scale(1.35); }}/* Zoom plus transparency changes */
@keyframes circle {
  0% {
    transform: scale(0.2);
    opacity: 0.8;
  }
  100% {
    transform: scale(1.5);
    opacity: 1; }}/ *. Use opacity to control the hidden display of elements */
@keyframes show {
  0% {
    opacity: 1; }}/* The whole star is enlarged, and the reverse playback once, to achieve the pop-up retraction effect */
#star{
  animation: banuce 0.2 s ease 0s 2 alternate;
}
/* Add extra diffusion effect to semi-transparent ring, add a bit of delay. * /
#star::before{
  opacity: 0;
  animation: circle 0.3 s ease 0.02 s 1 alternate;
}
/* Both pseudo-elements are given an initial transparency of 0, so that they disappear after their animation is complete */
#star::after{
  opacity: 0;
  animation: show 0.2 s steps(1,end) 0s 1;
}
Copy the code

Add click events

Unpack the animation style into a class.fill that adds classes to the element when clicked to achieve the state change. Now put in the full code

<! DOCTYPEhtml>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="Width = device - width, initial - scale = 1.0">
  <title>Document</title>
  <style>
    @keyframes banuce {
      0% {
        transform: scale(0.8);
      }
      100% {
        transform: scale(1.35); }}@keyframes circle {
      0% {
        transform: scale(0.2);
        opacity: 0.8;
      }
      100% {
        transform: scale(1.5);
        opacity: 1; }}@keyframes show {
      0% {
        opacity: 1; }}.wrap {
      width: 100vw;
      height: 100vh;
      display: flex;
      justify-content: center;
      align-items: center;
    }
    #star {
      display: inline-block;
      width: 30px;
      height: 30px;
      background-image: url(star.png);
      background-repeat: no-repeat;
      background-size: 100%;
      background-position: center;
    }
    .fill {
      position: relative;
      animation: banuce 0.2 s ease 0s 2 alternate;
      background-image: url(star_fill.png) ! important;
    }
    .fill::before {
      opacity: 0;
      content: ' ';
      position: absolute;
      left: 50%;
      top: 50%;
      width: 10%;
      height: 10%;
      transform: translate(-50%, -50%);
      border-radius: 50%;
      background: transparent;
      box-shadow: 15px -15px 0 #fed001.15px 15px 0 #fed001,
        -15px -15px 0 #fed001, -15px 15px 0 #fed001;
      animation: show 0.2 s steps(1, end) 0s 1;
    }
    .fill::after {
      opacity: 0;
      content: ' ';
      position: absolute;
      left: 0;
      right: 0;
      top: 0;
      bottom: 0;
      animation: circle 0.3 s ease 0.02 s 1 alternate;
      border-radius: 50%;
      background: rgba(254.208.1.0.1);
    }
  </style>
</head>
<body>
  <div class="wrap">
    <div id="star"></div>
  </div>
  <script>
    window.onload = () = > {
      const starEl = document.getElementById('star');
      starEl.addEventListener('click'.(e) = >{
        starEl.className = 'fill';
        setTimeout(() = >{
          starEl.className = ' ';
        }, 1000)})}</script>
</body>
</html>
Copy the code

Let’s do one more in slow motion, double the time and see what happens

– end