一、应用介绍
这次要分享的小程序功能为好友匹配动画界面
,这是一款以交友相亲为背景的恋爱主题样式组件。
纯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
方法
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>