源码实现 1
<!DOCTYPE html>
<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>
</head>
<body>
<div class="box">1234</div>
<style>
* {
margin: 0;
padding: 0;
}
.box {
display: flex;
justify-content: center;
align-items: center;
position: relative;
width: 180px;
height: 250px;
border-radius: 20px;
margin: 100px auto;
background-color: #000;
overflow: hidden;
z-index: 0;
}
.box::before {
content: '';
position: absolute;
z-index: -2;
width: 120px;
height: 120%;
background: linear-gradient(#03fcc6, #ff0296);
animation: rotates 3s linear infinite;
}
.box::after {
content: '';
position: absolute;
z-index: -1;
border-radius: 20px;
inset: 5px;
background-color: #FFF;
/* background-color: #0e1538; */
}
@keyframes rotates {
to {
transform: rotate(360deg);
}
}
</style>
</body>
</html>
源码实现2
<!DOCTYPE html>
<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>
</head>
<body>
<div class="card">
<div class="bg"></div>
<div class="blob"></div>
</div>
<style>
.card {
position: relative;
width: 200px;
height: 250px;
border-radius: 14px;
z-index: 1111;
overflow: hidden;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
box-shadow: 20px 20px 60px #bebebe, -20px -20px 60px #ffffff;
}
.bg {
position: absolute;
top: 5px;
left: 5px;
width: 190px;
height: 240px;
z-index: 2;
background: rgba(255, 255, 255, 0.95);
backdrop-filter: blur(24px);
border-radius: 10px;
overflow: hidden;
outline: 2px solid white;
}
.blob {
position: absolute;
z-index: 1;
top: 50%;
left: 50%;
width: 150px;
height: 150px;
border-radius: 50%;
background-color: #ff0000;
opacity: 1;
filter: blur(12px);
animation: blob-bounce 3s infinite linear;
}
@keyframes blob-bounce {
0% {
transform: translate(-100%, -100%) translate3d(0, 0, 0);
}
25% {
transform: translate(-100%, -100%) translate3d(100%, 0, 0);
}
50% {
transform: translate(-100%, -100%) translate3d(100%, 100%, 0);
}
75% {
transform: translate(-100%, -100%) translate3d(0, 100%, 0);
}
100% {
transform: translate(-100%, -100%) translate3d(0, 0, 0);
}
}
</style>
</body>
</html>
封装成 vue 组件,让其成为一个容器:
<template>
<div class="card animate">
<div class="bg"></div>
<div v-if="isActive" class="blob"></div>
<slot></slot>
</div>
</template>
<script lang="ts">
import { defineComponent, ref, watch } from 'vue';
export default defineComponent({
name: 'AnimatedBorder',
props: {
isActive: {
type: Boolean,
required: true
}
},
});
</script>
<style scoped>
.card {
position: relative;
border-radius: 14px;
z-index: 1111;
overflow: hidden;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
box-shadow: 20px 20px 60px #bebebe, -20px -20px 60px #ffffff;
}
.bg {
position: absolute;
top: 5px;
left: 5px;
width: calc(100% - 10px);
height: calc(100% - 10px);
z-index: 2;
background: rgba(255, 255, 255);
backdrop-filter: blur(24px);
border-radius: 10px;
overflow: hidden;
outline: 2px solid white;
}
.blob {
position: absolute;
z-index: 1;
top: 50%;
left: 50%;
width: calc(100%);
height: calc(100%);
border-radius: 10%;
background-color: #ff0000;
opacity: 1;
filter: blur(2px);
animation: blob-bounce 3s infinite linear;
}
@keyframes blob-bounce {
0% {
transform: translate(-100%, -100%) translate3d(0, 0, 0);
}
25% {
transform: translate(-100%, -100%) translate3d(100%, 0, 0);
}
50% {
transform: translate(-100%, -100%) translate3d(100%, 100%, 0);
}
75% {
transform: translate(-100%, -100%) translate3d(0, 100%, 0);
}
100% {
transform: translate(-100%, -100%) translate3d(0, 0, 0);
}
}
.animate .blob {
animation: blob-bounce 3s infinite linear;
}
</style>