CSS
----图标3D
环绕旋转,近大远小效果 transform: scaleY(0.25);
,将图片效果转为椭圆 <div class="entry-box">
<div class="entry-box-content">
<div class="content-circle">
<div
class="circle"
></div>
</div>
</div>
</div>
.entry-box {
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
&-content {
width: 50vw;
height: 50vw;
position: absolute;
top: calc(50% - 25vw);
left: 25vw;
z-index: 1;
.content-circle {
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
transform: scaleY(0.25);//将背景圆设置为3D效果
.circle {
width: 100%;
height: 100%;
border-radius: 50%;
background: url("../../assets/bgImg/circular5.png") no-repeat center center;
background-size: 100% 100%;
}
}
}
}
.circle {
width: 100%;
height: 100%;
border-radius: 50%;
background: url("../../assets/bgImg/circular5.png") no-repeat center center;
background-size: 100% 100%;
animation: centerRotate 15s linear infinite;
}
@keyframes centerRotate {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
import icon1 from "@/assets/iconImg/GEO终端.png";
import icon2 from "@/assets/iconImg/MF终端.png";
import icon3 from "@/assets/iconImg/pad.png";
import icon4 from "@/assets/iconImg/手机.png";
import icon5 from "@/assets/iconImg/显示器.png";
import icon6 from "@/assets/iconImg/服务器.png";
import icon7 from "@/assets/iconImg/笔记本.png";
import icon8 from "@/assets/iconImg/视频终端.png";
const IconList = [
{ id: 1, iconImg: icon1 },
{ id: 2, iconImg: icon2 },
{ id: 3, iconImg: icon3 },
{ id: 4, iconImg: icon4 },
{ id: 5, iconImg: icon5 },
{ id: 6, iconImg: icon6 },
{ id: 7, iconImg: icon7 },
{ id: 8, iconImg: icon8 },
];
<div
:class="['icon', 'icon' + item.id]"
v-for="item in IconList"
:key="item.id"
>
<img :src="item.iconImg" alt="" />
</div>
<div
:class="['icon', 'icon' + item.id]"
v-for="item in IconList"
:key="item.id"
>
<img :src="item.iconImg" alt="" />
</div>
.icon {
width: 6vw;
height: 6vw;
position: absolute;
display: flex;
justify-content: center;
align-items: center;
img {
width: 120%;
}
img:hover {
width: 140%;
}
}
.icon1 {
top: 24vw;
left: 22vw;
animation: turnX 8s cubic-bezier(0.36, 0, 0.64, 1) -4s infinite alternate,
turnY 8s cubic-bezier(0.36, 0, 0.64, 1) 0s infinite alternate,
turn-self 16s cubic-bezier(0.36, 0, 0.64, 1) 0s infinite alternate;
}
.icon2 {
top: 22.25vw;
left: 11.25vw;
animation: turnX 8s cubic-bezier(0.36, 0, 0.64, 1) -6s infinite alternate,
turnY 8s cubic-bezier(0.36, 0, 0.64, 1) -2s infinite alternate,
turn-self 16s cubic-bezier(0.36, 0, 0.64, 1) -2s infinite alternate;
}
.icon3 {
top: 19vw;
left: 3vw;
animation: turnX 8s cubic-bezier(0.36, 0, 0.64, 1) -8s infinite alternate,
turnY 8s cubic-bezier(0.36, 0, 0.64, 1) -4s infinite alternate,
turn-self 16s cubic-bezier(0.36, 0, 0.64, 1) -4s infinite alternate;
}
.icon4 {
top: 15.25vw;
left: 11.25vw;
animation: turnX 8s cubic-bezier(0.36, 0, 0.64, 1) -10s infinite alternate,
turnY 8s cubic-bezier(0.36, 0, 0.64, 1) -6s infinite alternate,
turn-self 16s cubic-bezier(0.36, 0, 0.64, 1)-6s infinite alternate;
}
.icon5 {
top: 14.5vw;
left: 22vw;
animation: turnX 8s cubic-bezier(0.36, 0, 0.64, 1) -12s infinite alternate,
turnY 8s cubic-bezier(0.36, 0, 0.64, 1) -8s infinite alternate,
turn-self 16s cubic-bezier(0.36, 0, 0.64, 1) -8s infinite alternate;
}
.icon6 {
top: 15.25vw;
right: 11.25vw;
animation: turnX 8s cubic-bezier(0.36, 0, 0.64, 1) -14s infinite alternate,
turnY 8s cubic-bezier(0.36, 0, 0.64, 1) -10s infinite alternate,
turn-self 16s cubic-bezier(0.36, 0, 0.64, 1) -10s infinite alternate;
}
.icon7 {
top: 19vw;
left: 41vw;
animation: turnX 8s cubic-bezier(0.36, 0, 0.64, 1) -16s infinite alternate,
turnY 8s cubic-bezier(0.36, 0, 0.64, 1) -12s infinite alternate,
turn-self 16s cubic-bezier(0.36, 0, 0.64, 1) -12s infinite alternate;
}
.icon8 {
top: 22.25vw;
right: 11.25vw;
animation: turnX 8s cubic-bezier(0.36, 0, 0.64, 1) -18s infinite alternate,
turnY 8s cubic-bezier(0.36, 0, 0.64, 1) -14s infinite alternate,
turn-self 16s cubic-bezier(0.36, 0, 0.64, 1) -14s infinite alternate;
}
1、第一个icon初始值:
turn-self :duration为 turnX和turnY之和
turnX:delay 为turn-self duration一半
turnY,turn-self :delay 为 0
2、每个delay 每次递减的值为 turn-self的duration/icon的数量 例子:16/8 = 2,每次递减2;
3、cubic-bezier,css3贝塞尔曲线 一条表示进度变化快慢的速度曲线
/* icon自身的大小缩放 */
@keyframes turn-self {
0% {
transform: scale(0.7);
}
50% {
transform: scale(1);
}
100% {
transform: scale(0.7);
}
}
/* icon横向运动变化,x轴的范围 */
@keyframes turnX {
0% {
left: 3vw;
}
100% {
left: 41vw;
}
}
/*icon纵向运动变化,Y轴的范围 */
@keyframes turnY {
0% {
top: 14.5vw;
}
100% {
top: 24vw;
}
}
效果图:
<div
:class="['icon', 'icon' + item.id]"
v-for="item in IconList"
:key="item.id"
:style="`animation-play-state: ${animationPlayState};`"
@mouseover="mouseOver"
@mouseleave="mouseleave"
>
let animationPlayState = ref<string>("");
function mouseOver() {
animationPlayState.value = "paused";
}
function mouseleave() {
animationPlayState.value = "running";
}
<template>
<div class="entry">
<div class="entry-box">
<div class="entry-box-content">
<div class="content-circle">
<div
class="circle"
:style="`animation-play-state: ${animationPlayState};`"
></div>
</div>
<div
:class="['icon', 'icon' + item.id]"
v-for="item in IconList"
:key="item.id"
:style="`animation-play-state: ${animationPlayState}; --item:${-(
item.id + 1
)}; --icon:${-(item.id - 1)}`"
@mouseover="mouseOver"
@mouseleave="mouseleave"
>
<img :src="item.iconImg" alt="" />
</div>
</div>
</div>
</div>
</template>
<script lang="ts" setup>
import icon1 from "@/assets/iconImg/GEO终端.png";
import icon2 from "@/assets/iconImg/MF终端.png";
import icon3 from "@/assets/iconImg/pad.png";
import icon4 from "@/assets/iconImg/手机.png";
import icon5 from "@/assets/iconImg/显示器.png";
import icon6 from "@/assets/iconImg/服务器.png";
import icon7 from "@/assets/iconImg/笔记本.png";
import icon8 from "@/assets/iconImg/视频终端.png";
const IconList = [
{ id: 1, iconImg: icon1 },
{ id: 2, iconImg: icon2 },
{ id: 3, iconImg: icon3 },
{ id: 4, iconImg: icon4 },
{ id: 5, iconImg: icon5 },
{ id: 6, iconImg: icon6 },
{ id: 7, iconImg: icon7 },
{ id: 8, iconImg: icon8 },
];
let animationPlayState = ref<string>("");
function mouseOver() {
animationPlayState.value = "paused";
}
function mouseleave() {
animationPlayState.value = "running";
}
</script>
<style lang="scss" scoped>
.entry {
width: 100%;
height: 100%;
display: flex;
position: relative;
.entry-box {
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
&-content {
width: 50vw;
height: 50vw;
position: absolute;
top: calc(50% - 25vw);
left:25vw;
z-index: 1;
.content-circle {
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
transform: scaleY(0.25);
.circle {
width: 100%;
height: 100%;
border-radius: 50%;
background: url("../../assets/bgImg/circular5.png") no-repeat center center;
background-size: 100% 100%;
animation: centerRotate 15s linear infinite;
}
}
.icon {
width: 6vw;
height: 6vw;
position: absolute;
display: flex;
justify-content: center;
align-items: center;
img {
width: 120%;
}
img:hover {
width: 140%;
}
}
.icon1 {
top: 24vw;
left: 22vw;
animation: turnX 8s cubic-bezier(0.36, 0, 0.64, 1) -4s infinite alternate,
turnY 8s cubic-bezier(0.36, 0, 0.64, 1) 0s infinite alternate,
turn-self 16s cubic-bezier(0.36, 0, 0.64, 1) 0s infinite alternate;
}
.icon2 {
top: 22.25vw;
left: 11.25vw;
animation: turnX 8s cubic-bezier(0.36, 0, 0.64, 1) -6s infinite alternate,
turnY 8s cubic-bezier(0.36, 0, 0.64, 1) -2s infinite alternate,
turn-self 16s cubic-bezier(0.36, 0, 0.64, 1) -2s infinite alternate;
}
.icon3 {
top: 19vw;
left: 3vw;
animation: turnX 8s cubic-bezier(0.36, 0, 0.64, 1) -8s infinite alternate,
turnY 8s cubic-bezier(0.36, 0, 0.64, 1) -4s infinite alternate,
turn-self 16s cubic-bezier(0.36, 0, 0.64, 1) -4s infinite alternate;
}
.icon4 {
top: 15.25vw;
left: 11.25vw;
animation: turnX 8s cubic-bezier(0.36, 0, 0.64, 1) -10s infinite alternate,
turnY 8s cubic-bezier(0.36, 0, 0.64, 1) -6s infinite alternate,
turn-self 16s cubic-bezier(0.36, 0, 0.64, 1)-6s infinite alternate;
}
.icon5 {
top: 14.5vw;
left: 22vw;
animation: turnX 8s cubic-bezier(0.36, 0, 0.64, 1) -12s infinite alternate,
turnY 8s cubic-bezier(0.36, 0, 0.64, 1) -8s infinite alternate,
turn-self 16s cubic-bezier(0.36, 0, 0.64, 1) -8s infinite alternate;
}
.icon6 {
top: 15.25vw;
right: 11.25vw;
animation: turnX 8s cubic-bezier(0.36, 0, 0.64, 1) -14s infinite alternate,
turnY 8s cubic-bezier(0.36, 0, 0.64, 1) -10s infinite alternate,
turn-self 16s cubic-bezier(0.36, 0, 0.64, 1) -10s infinite alternate;
}
.icon7 {
top: 19vw;
left: 41vw;
animation: turnX 8s cubic-bezier(0.36, 0, 0.64, 1) -16s infinite alternate,
turnY 8s cubic-bezier(0.36, 0, 0.64, 1) -12s infinite alternate,
turn-self 16s cubic-bezier(0.36, 0, 0.64, 1) -12s infinite alternate;
}
.icon8 {
top: 22.25vw;
right: 11.25vw;
animation: turnX 8s cubic-bezier(0.36, 0, 0.64, 1) -18s infinite alternate,
turnY 8s cubic-bezier(0.36, 0, 0.64, 1) -14s infinite alternate,
turn-self 16s cubic-bezier(0.36, 0, 0.64, 1) -14s infinite alternate;
}
}
}
}
@keyframes centerRotate {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
/* icon自身的大小缩放 */
@keyframes turn-self {
0% {
transform: scale(0.7);
}
50% {
transform: scale(1);
}
100% {
transform: scale(0.7);
}
}
/* icon横向运动变化,x轴的范围 */
@keyframes turnX {
0% {
left: 3vw;
}
100% {
left: 41vw;
}
}
/*icon纵向运动变化,Y轴的范围 */
@keyframes turnY {
0% {
top: 14.5vw;
}
100% {
top: 24vw;
}
}
</style>