📌个人主页:个人主页
🧀 推荐专栏:小程序开发成神之路
📝作者简介:一个读研中创业、打工中学习的能搞全栈、也搞算法、目前在搞大数据的奋斗者。
⭐️您的小小关注是我持续输出的动力!
⭐️
一、应用介绍
这次要分享的小程序功能为好友匹配动画界面
,这是一款以交友相亲为背景的恋爱主题样式组件。
纯css样式
和JS原生语法
打造,支持多端的开发,小程序、H5、APP均能丝滑享受。
二、效果展示
三、技术与难点
3.1 基本开发环境
- 开发框架:
uniapp
- 代码语法:
vue 2
、html
、css3
3.2 开发要点
- (1)头像图片的生成
- 先引入
<image>
标签,配置好相应的图片路径
- 先引入
<image class="dot" src="randomImg" style="width: 92px;height: 92px;border-radius: 50px;"></image>`
- 再通过CSS样式将其变成圆形
-webkit-border-radius: 50%;
-moz-border-radius: 50%;
border-radius: 50%;
-
(2)CSS动画的引入
对于网页元素的动画效果我们使用CSS 3 动画
,不太熟悉的小伙伴可以直接查看文档进行学习:CSS动画教程- 先声明一个放缩动画变量
@keyframes 动画变量名(taoren) {
0% {
-webkit-transform:scale(0) translateX(0);
transform:scale(0) translateX(0);
opacity:.6
}
5% {
-webkit-transform:scale(1) translateX(0) translateY(-80%);
transform:scale(1) translateX(0) translateY(-80%);
opacity:.8
}
20% {
opacity:1
}
30% {
opacity:.2
}
32% {
opacity:0;
visibility:hidden
}
50% {
-webkit-transform:scale(1.9) translateX(-40px) translateY(-340%);
transform:scale(1.9) translateX(-40px) translateY(-340%)
}
100% {
-webkit-transform:translateX(-100px);
transform:translateX(-100px)
}
}
- 将动画变量绑定到相应的元素样式中
.相应原始的Class名称 {
animation:taoren
}
- (3)JS循环逻辑的控制
在元素和动画都具备的基础之上,接下来进行更重要的操作:将元素所设置的动画按照特定的规则进行重复播放。- JS中要实现重复播放的逻辑,通常的做法是使用
setInterval
方法。
- JS中要实现重复播放的逻辑,通常的做法是使用
this.interval = setInterval((function() {
// 动画逻辑
}
), this.intervalTime)
四、完整源码
代码基于vue 2
语法编写,拷贝出来需保存为.vue
文件。该示例代码中,包括三大模块:<script>
,<template>
,<style>
,三大模块的作用分别是:控制元素逻辑和数据绑定
,编写组织页面元素的渲染
,控制和渲染元素的样式
。
<template>
<view class="center">
<view class="container">
<image class="dot" src="randomImg" style="width: 92px;height: 92px;border-radius: 50px;"></image>
<view class="pulse"></view>
<view class="pulse1"></view>
<view class="prize-flying" >
<view v-for="(item,index) in flyLeftList" class="fly-prize fly-left"
:style="{ 'background': 'url('+ item.img +')', '-webkit-animation-duration': flySpeed + 's','animation-duration': flySpeed + 's' }"></view>
<view v-for="(item,index) in flyCenterList" class="fly-prize fly-center"
:style="{ 'background': 'url('+ item.img +')', '-webkit-animation-duration': flySpeed + 's','animation-duration': flySpeed + 's' }"></view>
<view v-for="(item,index) in flyRightList" class="fly-prize fly-right"
:style="{ 'background': 'url('+ item.img +')', '-webkit-animation-duration': flySpeed + 's','animation-duration': flySpeed + 's' }"></view>
</view>
</view>
<view class="flex justify-center items-center match-button" @click="showMan">
<view class="match-btn">
心动匹配
</view>
</view>
</view>
</template>
<script>
import utils from '@/utils/utils'
export default {
components: {utils},
data() {
return {
show:false,
randomImg:'/static/imgs/mm1.jpg',
flyLeftList: [],
flyCenterList: [],
flyRightList: [],
userList:[{img:'/static/imgs/mm1.jpg'},{img:'/static/imgs/mm2.jpg'},{img:'/static/imgs/mm3.jpg'}],
flySpeed: 25,
indexRecord: 0,
intervalTime: 2.5,
interval: null,
};
},
// 从后台进入前台显示
onShow() {
this.flyLeftList=[];
this.flyCenterList=[];
this.flyRightList=[];
this.refreshUser();
},
// 从前台进入后台
onHide() {
this.flyLeftList=[];
this.flyCenterList=[];
this.flyRightList=[];
clearInterval(this.interval);
},
methods:{
showMan(){
console.log('========')
this.show =true
},
refreshUser(){
this.flyInterval();
},
flyInterval() {
if(this.interval != null){
clearInterval(this.interval);
}
var t = this;
this.pushFlyList(),
this.interval = setInterval((function() {
t.pushFlyList()
}
), 1e3 * this.intervalTime)
},
pushFlyList() {
var t = 0;
while (t < 3) {
this.indexRecord == this.userList.length - 1 ? this.indexRecord = 0 : this.indexRecord++;
var a = this.userList[this.indexRecord];
switch (t) {
case 0:
this.flyLeftList.push(a);
break;
case 1:
this.flyCenterList.push(a);
break;
case 2:
this.flyRightList.push(a);
break
}
t++
}
},
}
}
</script>
<style lang="scss">
page{
height: 100%;
background: url('~@/static/imgs/home/bg.png');
}
.match-button{
background-image: linear-gradient(to top, #c471f5 0%, #fa71cd 100%);
color: #ffff;
border-radius: 100rpx;
padding: 20rpx;
}
.center {
height: 100%;
flex: auto;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
//background-color: red;
}
@keyframes warn {
0% {
transform: scale(0.3);
-webkit-transform: scale(0.3);
opacity: 0.0;
}
25% {
transform: scale(0.3);
-webkit-transform: scale(0.3);
opacity: 0.1;
}
50% {
transform: scale(0.5);
-webkit-transform: scale(0.5);
opacity: 0.3;
}
75% {
transform: scale(0.8);
-webkit-transform: scale(0.8);
opacity: 0.5;
}
100% {
transform: scale(1);
-webkit-transform: scale(1);
opacity: 0.0;
}
}
@keyframes warn1 {
0% {
transform: scale(0.3);
-webkit-transform: scale(0.3);
opacity: 0.0;
}
25% {
transform: scale(0.3);
-webkit-transform: scale(0.3);
opacity: 0.1;
}
50% {
transform: scale(0.3);
-webkit-transform: scale(0.3);
opacity: 0.3;
}
75% {
transform: scale(0.5);
-webkit-transform: scale(0.5);
opacity: 0.5;
}
100% {
transform: scale(0.8);
-webkit-transform: scale(0.8);
opacity: 0.0;
}
}
.container {
position: relative;
width: 96px;
height: 96px;
/*border: 1px solid #000; hovertree.com */
}
/* 保持大小不变的小圆圈 何问起 */
.dot {
position: absolute;
width: 92px;
height: 92px;
//left: -2.5px;
//top: -2.5px;
-webkit-border-radius: 50%;
-moz-border-radius: 50%;
//border: 2px solid red;
border-radius: 50%;
z-index: 2;
animation: msClock 1.8s linear infinite;
}
@keyframes msClock{
0%,90%,100%{ transform: rotate(0) scale(1);}
20%,40%{ transform: rotate(-15deg) scale(1.1);}
30%,50%{ transform: rotate(15deg) scale(1.1);}
}
/* 产生动画(向外扩散变大)的圆圈 */
.pulse {
position: absolute;
width: 320px;
height: 320px;
left: -120px;
top: -120px;
border: 6px solid $dating-color-primary;
-webkit-border-radius: 50%;
-moz-border-radius: 50%;
border-radius: 50%;
z-index: 1;
opacity: 0;
-webkit-animation: warn 2s ease-out;
-moz-animation: warn 2s ease-out;
animation: warn 2s ease-out;
-webkit-animation-iteration-count: infinite;
-moz-animation-iteration-count: infinite;
animation-iteration-count: infinite;
box-shadow: 1px 1px 30px $dating-color-primary;
}
.pulse1 {
position: absolute;
width: 320px;
height: 320px;
left: -120px;
top: -120px;
border: 6px solid $dating-color-primary;
-webkit-border-radius: 50%;
-moz-border-radius: 50%;
border-radius: 50%;
z-index: 1;
opacity: 0;
-webkit-animation: warn1 2s ease-out;
-moz-animation: warn1 2s ease-out;
animation: warn1 2s ease-out;
-webkit-animation-iteration-count: infinite;
-moz-animation-iteration-count: infinite;
animation-iteration-count: infinite;
box-shadow: 1px 1px 30px $dating-color-primary;
}
a{color:blue;text-decoration:none;}
.match-button{
position: fixed;
bottom: calc(var(--status-bar-height) + 120rpx);
}
.prize-flying{
z-index:99;
width:100px;
position:absolute;
bottom:50%;
left:50%;
-webkit-transform:translateX(-50%);
transform:translateX(-50%)
}
.prize-flying .fly-prize {
text-align:center;
position:absolute;
top:100%;
opacity:0;
width:39px;
height:39px;
background-repeat:no-repeat!important;
background-size:100% 100%!important;
border-radius:50%;
background:#fff;
padding:7px
}
.showCard {
z-index:10;
animation:warn
}
.prize-flying .fly-left {
left:0;
z-index:5;
animation:flyleft-data-v-1a236634
}
.prize-flying .fly-center {
left:30px;
z-index:3;
animation:flycenter-data-v-1a236634
}
.prize-flying .fly-right {
right:0;
z-index:5;
animation:flyright-data-v-1a236634
}
@keyframes flyleft-data-v-1a236634 {
0% {
-webkit-transform:scale(0) translateX(0);
transform:scale(0) translateX(0);
opacity:.6
}
5% {
-webkit-transform:scale(1) translateX(0) translateY(-80%);
transform:scale(1) translateX(0) translateY(-80%);
opacity:.8
}
20% {
opacity:1
}
30% {
opacity:.2
}
32% {
opacity:0;
visibility:hidden
}
50% {
-webkit-transform:scale(1.9) translateX(-40px) translateY(-340%);
transform:scale(1.9) translateX(-40px) translateY(-340%)
}
100% {
-webkit-transform:translateX(-100px);
transform:translateX(-100px)
}
}
@keyframes flycenter-data-v-1a236634 {
0% {
-webkit-transform:scale(0) translateX(0);
transform:scale(0) translateX(0);
opacity:.6
}
5% {
-webkit-transform:scale(1) translateX(0) translateY(-80%);
transform:scale(1) translateX(0) translateY(-80%);
opacity:.8
}
20% {
opacity:1
}
30% {
opacity:.2
}
32% {
opacity:0;
visibility:hidden
}
34% {
opacity:0
}
50% {
-webkit-transform:scale(1.9) translateX(0) translateY(-340%);
transform:scale(1.9) translateX(0) translateY(-340%)
}
100% {
-webkit-transform:translateX(0);
transform:translateX(0)
}
}
@keyframes flyright-data-v-1a236634 {
0% {
-webkit-transform:scale(0) translateX(0);
transform:scale(0) translateX(0);
opacity:.6
}
5% {
-webkit-transform:scale(1) translateX(0) translateY(-80%);
transform:scale(1) translateX(0) translateY(-80%);
opacity:.8
}
20% {
opacity:1
}
30% {
opacity:.2
}
32% {
opacity:0;
visibility:hidden
}
34% {
opacity:0
}
50% {
-webkit-transform:scale(1.9) translateX(40px) translateY(-340%);
transform:scale(1.9) translateX(40px) translateY(-340%)
}
100% {
-webkit-transform:translateX(100px);
transform:translateX(100px)
}
}
</style>