As shown in figureRecently, dear product students, I raised a requirement: add a revolving gold coin in a corner of the page to attract users to participate in the activity ~ as soon as possible ~

Get this demand, the first reaction GIF + A tag, simple and crude + convenient. There is a problem about the implementation, UI sister has not done the design, the schedule needs to be x days ~ how to do? There is no hard work to do, only to solve the difficulties of the workers!

Easy to link. How about rotating gold? Rotating gold = Rotating + gold. Animation + @keyframes: Animation + @keyframes

.coin {

  transform-style: preserve-3d;

  animation: rotate3d 3s linear infinite;

}



@keyframes rotate3d {

  0% {

    transform: perspective(1000px) rotateY(0deg); 100%} {transform: perspective(1000px) rotateY(360deg); }}Copy the code

What about the gold coins? If you erase all the patterns on the coin’s surface, the coin is a very short cylinder and we need a front + back + curved side. So heads plus tails is easy

$coin-thickness: 4px;

$coin-front: "https://tosv.byted.org/obj/maat/img/d2FuZ3NoaXpoZW4uNzUzMA/file_178a58ae02711.png";

$coin-back: "https://tosv.byted.org/obj/maat/img/d2FuZ3NoaXpoZW4uNzUzMA/file_178a58ae0276.png";



.coin__front {

  background-image: url($coin-front);

  background-size: cover;

  transform: translateZ($coin-thickness / 2);

}

.coin__back {

  background-image: url($coin-back);

  background-size: cover;

  transform: translateZ(-$coin-thickness / 2) rotateY(180deg);

}
Copy the code

How do I draw the side? I haven’t found a single curved property except border-radius. Is this the end of my DIY gold?

Of course not!! Respect me a cup of wisdom of the Chinese nation ~ as early as thousands of years ago, Zu Chongzhi told us ~ can not achieve a perfect circle, so let it approximate circle! Several years of experience in the front-end industry tell me that as long as I can deceive the user’s vision, what is true!! There you are — polyprism.

The scheme is there, but the trouble is, how many edges can be painted to deceive the user’s vision? How much CSS +div should I write by hand? Don’t panic. When in less handles n loops, and the whole map in the front frame generates div

const n = 80

<div className={styles.coin__edge}>

  {Array(n).fill(1).map((value, key) => (<div key={key} />))}

</div>
Copy the code

Translate + Rotate is used to position these divs ~

// Multi-prism size (diameter)

$coin-diameter: 320px;

// Multi-prism height

$coin-thickness: 40px;

/ / color

$coin-color: rgb(255.223.95);

// The number of edges of multiple prisms

$edge-faces: 100;

// The height of each edge is π * diameter/number of edges

$edge-face-length: 3.14 * $coin-diameter / $edge-faces;



.coin__edge{>div {

    position: absolute;

    height: $edge-face-length;

    width: $coin-thickness;

  }

  @for $i from 1 through $edge-faces {

    div:nth-child(#{$i}) {

      background: $coin-color;

      transformSince the default div is drawn in the upper left corner, you need to move it to the center translateY($coin-diameter / 2 - $edge-face-length / 2)

        translateX($coin-diameter / 2 - $coin-thickness / 2// Rotate rotateY(90deg// Adjust the Angle of each slice rotateX(360deg / $edge-faces * $i + 90// Move to the edge of the translateZ($coin-diameter / 2); }}}Copy the code

The default position to drawMoved to the center

div:nth-child(#{$i}) {

  transformSince the default div is drawn in the upper left corner, you need to move it to the center translateY($coin-diameter / 2 - $edge-face-length / 2)

        translateX($coin-diameter / 2 - $coin-thickness / 2)}Copy the code

Horizontal rotation

div:nth-child(#{$i}) {

  transformSince the default div is drawn in the upper left corner, you need to move it to the center translateY($coin-diameter / 2 - $edge-face-length / 2)

        translateX($coin-diameter / 2 - $coin-thickness / 2// Rotate rotateY(90deg)}Copy the code

Adjust the Angle of each piece

div:nth-child(#{$i}) {

  transformSince the default div is drawn in the upper left corner, you need to move it to the center translateY($coin-diameter / 2 - $edge-face-length / 2)

        translateX($coin-diameter / 2 - $coin-thickness / 2// Rotate rotateY(90deg// Adjust the Angle of each slice rotateX(360deg / $edge-faces * $i + 90// Move to the edge of the translateZ($coin-diameter / 2);

}
Copy the code

Move at most prismatic edges

div:nth-child(#{$i}) {

  transformSince the default div is drawn in the upper left corner, you need to move it to the center translateY($coin-diameter / 2 - $edge-face-length / 2)

        translateX($coin-diameter / 2 - $coin-thickness / 2// Rotate rotateY(90deg// Adjust the Angle of each slice rotateX(360deg / $edge-faces * $i + 90// Move to the edge of the translateZ($coin-diameter / 2);

}
Copy the code

Final effect:Perfect solution ~

Finally, the complete code is attached

Skeleton:

const CoinTrans = () = > {

  return <div class="coin">

    <div className="coin__front"></div>

    <div className="coin__back"></div>

    <div className="coin__edge">

      {Array(100).fill(1).map((item,key)=> <div key={key} />)}

    </div>{/ * * / shadow}<div className="coin__shadow"></div>

  </div>

}
Copy the code
$coin-diameter: 320px;

$coin-thickness: 40px;

$coin-color: rgb(255.223.95);

$coin-front: "https://tosv.byted.org/obj/maat/img/d2FuZ3NoaXpoZW4uNzUzMA/file_178a58ae02711.png";

$coin-back: "https://tosv.byted.org/obj/maat/img/d2FuZ3NoaXpoZW4uNzUzMA/file_178a58ae0276.png";

$edge-faces: 100;

$edge-face-length: 3.14 * $coin-diameter / $edge-faces;

$turn-time: 8s;



.coin {

  position: relative;

  width: $coin-diameter;

  height: $coin-diameter;

  margin: 0 auto;

  transform-style: preserve-3d;

  animation: rotate3d $turn-time linear infinite;

  transition: all 0.3 s;

}



.coin__front..coin__back {

  position: absolute;

  width: $coin-diameter;

  height: $coin-diameter;

  border-radius: 50%;

  overflow: hidden;

  background-color: $coin-color;

  color: # 000;

  font-size: $coin-diameter * 0.6; // Gold surface flash buling~~ &:after {content:"";

    position: absolute;

    left: -$coin-diameter / 2;

    bottom: 100%;

    display: block;

    height: $coin-diameter / 1.5;

    width: $coin-diameter * 2;

    background: #fff;

    opacity: 0.3;

    animation: shine linear $turn-time / 2infinite; }}.coin__front {

  background-image: url($coin-front);

  background-size: cover;

  transform: translateZ($coin-thickness / 2);

}

.coin__back {

  background-image: url($coin-back);

  background-size: cover;

  transform: translateZ(-$coin-thickness / 2) rotateY(180deg);

}



.coin__edge{>div {

    position: absolute;

    height: $edge-face-length;

    width: $coin-thickness;

  }

  @for $i from 1 through $edge-faces {

    div:nth-child(# {$i{})background: $coin-color; // Another move logic //transform: translateY($coin-diameter / 2 - $edge-face-length / 2) / /translateX($coin-diameter / 2 - $coin-thickness / 2) / /rotateZ(360deg / $edge-faces * $i + 90) / /translateX($coin-diameter / 2) / /rotateY(90deg);

      // rotateZ(360deg / $edge-faces * $i + 90)

      transform: translateY($coin-diameter / 2 - $edge-face-length / 2)

        translateX($coin-diameter / 2 - $coin-thickness / 2)

        rotateY(90deg)

        rotateX(360deg / $edge-faces * $i + 90)

        translateZ($coin-diameter / 2); }} // Shadow CSS.coin__shadow {

  position: absolute;

  width: $coin-diameter;

  height: $coin-thickness;

  border-radius: 50%;

  background: # 000;

  box-shadow: 0 0 $coin-thickness * 5 $coin-thickness * 5 # 000;

  opacity: 0.125;

  transform: rotateX(90deg) translateZ(-$coin-diameter * 1.1) scale(0.5);

}



@keyframes rotate3d {

  0% {

    transform: perspective(1000px) rotateY(0deg);

  }



  100% {

    transform: perspective(1000px) rotateY(360deg); }}@keyframes shine {

  0%.15% {

    transform: translateY($coin-diameter * 2) rotate(-40deg);

  }

  50% {

    transform: translateY(-$coin-diameter) rotate(-40deg); }}Copy the code

Data platform front-end team, responsible for the research and development of big data-related products such as Fengshen, TEA, Libra and Dorado. We have a strong passion in front-end technology. In addition to research and development related to data products, we have a lot of exploration and accumulation in data visualization, mass data processing optimization, Web Excel, WebIDE, private deployment and engineering tools. If you are interested, please feel free to contact us. Any suggestions and feedback on the product can also find us directly for feedback ~