本文说下微信小程序的动画创建
先看效果图
微信小程序动画演示
由于项目使用云开发,所以天然支持asnyc await
首先说下基本思路:
动画效果是点击中间的切换按钮,两边的文字向对方移动最终互换,移动过程中还有透明度变化,由于两边文字长度不同,要能够精确掌握各自移动的距离,获取节点信息必不可少,所以先封装了两个获取节点信息的函数,为了减少代码嵌套,使用promise封装。
getQuerysFields_Sync 能获取元素宽高,定位值(即top,left,bottom,right)、边距等信息
getQuerySync 可以获取元素宽高,定位置信息
具体用法请查阅小程序获取dom节点api
注意我这里因为使用云开发,所天然支持async /await,如果你的项目没有使用云开发,是不能尺寸async /await的,除非引入相关插件
第二将文字移动透明动画提出去,方便调用,函数为switchTextAnimationFun,中间按钮翻转动画单独写
// 中文苗文切换动画
async wantChangeL(){
let { input_cOrH}=this.data
let config={
computedStyle:['width','margin']
}
let switchImgDomInfo = await getQuerysFields_Sync('.arrew', config)
let textDomInfo = await getQuerySync('.switchText')
let switchImgMarginHalfX = parseInt(switchImgDomInfo.margin.split(' ')[1])
let switchImgWidth=parseInt(switchImgDomInfo.width)
let textWidth = textDomInfo.width
let switchTargetMoveX = switchImgMarginHalfX * 2 + switchImgWidth + textWidth
this.switchTextAnimationFun(1000, switchTargetMoveX)
//中间按钮翻转动画
let arrewAnimation = wx.createAnimation({
duration:1000,
timingFunction: 'ease'
})
let arrewImgRotateDeg = input_cOrH ? 180 : 0
arrewAnimation.rotateX(arrewImgRotateDeg).step(1000)
this.setData({
checkResultTexts: [],
arrewAnimation: arrewAnimation.export()
})
setTimeout(()=>{
this.switchTextAnimationFun(0, 0)
this.setData({
input_cOrH: !input_cOrH,
})
},1000)
},
// 切换文字动画
switchTextAnimationFun(duration, switchTargetMoveX){
let leftTextAnimation = wx.createAnimation({
duration,
timingFunction: 'ease'
})
let rightTextAnimation = wx.createAnimation({
duration,
timingFunction: 'ease'
})
let opacityAnimation=wx.createAnimation({
duration:2*duration/3,
timingFunction:'ease'
})
leftTextAnimation.translateX(switchTargetMoveX).step(duration)
rightTextAnimation.translateX(-switchTargetMoveX).step(duration)
opacityAnimation.opacity(0).step(2*duration/3)
this.setData({
leftTextAnimation: leftTextAnimation.export(),
rightTextAnimation: rightTextAnimation.export(),
opacityAnimation: opacityAnimation.export()
})
setTimeout(()=>{
opacityAnimation.opacity(1).step(duration / 3)
this.setData({
opacityAnimation: opacityAnimation.export()
})
},duration/2)
},
/*同步获取节点*/
export const getQuerySync = (dom, that) => {
return new Promise((resolve, reject) => {
if (that) {
that.createSelectorQuery().select(dom).boundingClientRect(res => {
// //console.log(res)
resolve(res)
}).exec()
} else {
wx.createSelectorQuery().select(dom).boundingClientRect(res => {
// //console.log(res)
resolve(res)
}).exec()
}
})
}
/*同步获取节点信息fields*/
export const getQuerysFields_Sync = (dom, config, that) => {
// let {id,dataset,size,scrollOffset,properties,computedStyle,context,rect}=config
// //console.log(wx)
return new Promise((resolve, reject) => {
if (that) {
that.createSelectorQuery().select(dom).fields(config, res => {
resolve(res)
}).exec()
} else {
wx.createSelectorQuery().select(dom).fields(config, res => {
resolve(res)
}).exec()
}
})
}
创建项目后,到index.wxml页面
<view class="indexPage">
<view class="indexPageTop">
<view class="logoBox rowCenter">
<image src="../images/logo.jpg" class="logo"></image>
</view>
<!-- 查询操作 -->
<view class="checkBox">
<!-- 选择语系 -->
<view class="switchHmongbBox rowCenter">
<Radios radioData="{{switchHmongbData}}" size="18" bindradioChange="IwantThisHmongb" value="{{switchHmongb}}"/>
</view>
<!-- 中苗文切换 -->
<view class="switchCheck rowCenter">
<view class="rowCenter" animation="{{leftTextAnimation}}">
<view class="rowCenter" animation="{{opacityAnimation}}">
<text class="switchText rowCenter">{{input_cOrH ? chinese : hmongb}}</text>
</view>
</view>
<view class="rowCenter" animation="{{arrewAnimation}}">
<image src="../images/arrew.png" class="arrew {{input_cOrH ?'arrewRotate0' : 'arrewRotate180'}}" bindtap="wantChangeL"></image>
</view>
<view class="rowCenter" animation="{{rightTextAnimation}}">
<view class="rowCenter" animation="{{opacityAnimation}}">
<text class="switchText rowCenter">{{input_cOrH ? hmongb : chinese}}</text>
</view>
</view>
</view>
<!-- 模糊查询精准查询 -->
<view class="wantMoreOrLessBox rowStart">
<Radios radioData="{{wantMoreOrLessData}}" size="18" bindradioChange="tellMeWantMoreOrLess" value="{{wantMoreOrLess}}"/>
</view>
<!-- 查询框 -->
<view class="inputCheckBox rowCenter">
<view class="wordInputBox rowCenter">
<input placeholder="请输入中文" class="wordInput" value="{{inputText}}" bindinput="getInputText"></input>
</view>
<view class="checkBtn rowCenter" bindtap="checkNow">查 询</view>
</view>
</view>
</view>
<!-- 查询结果 -->
<view class="checkResultBox">
<scroll-view scroll-y="true" class="checkResultText-scrollview" style="height:{{resultScrollHeight}}px;">
<view>
<block wx:for="{{checkResultTexts}}" wx:key="index">
<view class="checkResultTextBox rowStart">
<view class="copyBox" bindtap="copyTextFun" data-index="{{index}}">
<text></text>
<text></text>
</view>
<text class="resultText" bindtap="copyTextFun" data-index="{{index}}">{{input_cOrH ? item.hmongb : item.chinese}}</text>
<text class="checkText">{{input_cOrH ? item.chinese :item.hmongb }}</text>
</view>
</block>
</view>
</scroll-view>
</view>
<!-- 复制结果 -->
<view class="checkOptionBtnBox rowCenter">
<view class="checkOptionBtn clearResult rowCenter" bindtap="clearResult">清空查询</view>
<view class="checkOptionBtn copyResult rowCenter" bindtap="copyAllResult">复制结果</view>
</view>
</view>
@import "../../utils/style/style.wxss";
view,text{
font-size: 30rpx;
}
.logoBox{
width:260rpx;
height:260rpx;
border-radius: 50%;
overflow: hidden;
margin:30rpx auto 50rpx auto;
}
.logo{
width:260rpx;
height:260rpx;
}
.checkBox{
}
.switchHmongbBox{
margin-bottom: 20rpx;
}
.oneSwitchHmongbBox{
margin-right: 20rpx;
}
.radioText{
font-size: 24rpx;
color:#999999;
}
.switchCheck{
margin-bottom: 40rpx;
}
.switchText{
font-size: 40rpx;
width:200rpx;
font-weight: bold;
}
.arrew{
width:50rpx;
height:36rpx;
margin:0 50rpx;
}
.arrewRotate0{
/* transform:rotateY(0deg); */
/* transform-style:preserve-3d; */
/* transform-origin:100% 18px */
}
.arrewRotate180{
/* transform:rotateY(180deg); */
/* transform-style:preserve-3d; */
/* transform-origin:100% 18px */
}
.wantMoreOrLessBox{
width:580rpx;
margin:0 auto 20rpx auto;
}
.inputCheckBox{
}
.wordInputBox{
border:solid 2rpx #dddddd;
height:60rpx;
}
.wordInput{
height:60rpx;
padding:0 10rpx;
width:460rpx;
background: #ffffff;
}
.checkBtn{
width:120rpx;
height:60rpx;
background: #633319;
color:#ffffff;
font-size: 36rpx;
font-weight: bold;
border:solid 2rpx #633319;
}
/* 查询结果 */
.checkResultText-scrollview{
/* background: #fcfcfc; */
}
.checkResultTextBox{
flex-wrap: wrap;
margin-bottom: 20rpx;
}
.resultText{
margin: 0 20rpx 0 10rpx;
}
.copyBox{
position: relative;
width:30rpx;
height:30rpx;
}
.copyBox text{
width:20rpx;
height:20rpx;
position: absolute;
border:solid 2rpx #F29438;
background: #ffffff;
}
.copyBox text:first-of-type{
left:0;
top:0;
}
.copyBox text:last-of-type{
right:0;
bottom:0;
}
.checkResultBox{
margin:30rpx auto 50rpx auto;
width:600rpx;
height:250rpx;
align-items: flex-start;
}
.checkOptionBtnBox{
position: fixed;
bottom:0;
left:0;
width:100%;
}
.checkOptionBtn{
height:80rpx;
color:#ffffff;
font-size: 36rpx;
font-weight: bold;
width:50%;
}
.clearResult{
background: #666666;
}
.copyResult{
background: #F29438;
}
.left{
float:left;
}
.clear{
clear:both;
overflow:hidden;
}
.clear::after{
display: table;
content:'';
font-size:0;
}
.green{
color: #5AC994 !important;
}
.gray{
color:#999999 !important;
}
.graySmallText666{
color:#666666 !important;
font-size: 24rpx;
}
.graySmallText999{
color:#999999 !important;
font-size: 24rpx;
}
.wrap {
width: 100%;
height: 100%;
}
view,text{
color:#333333;
font-size: 28rpx;
}
/*按钮移动范围*/
.contact-area{
width:100%;
min-height:100vh;
}
/* flex布局 */
.rowStart{
display: flex;
flex-direction: row;
justify-content: flex-start;
align-items: center;
}
.rowAround{
display: flex;
flex-direction: row;
justify-content: space-around;
align-items: center;
}
.rowBtween{
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
}
.rowCenter{
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
}
.rowEnd{
display: flex;
flex-direction: row;
justify-content: flex-end;
align-items: center;
}
.columnStart{
display: flex;
flex-direction: column;
justify-content: flex-start;
align-items: center;
}
.columnAround{
display: flex;
flex-direction: column;
justify-content: space-around;
align-items: center;
}
.columnBtween{
display: flex;
flex-direction: column;
justify-content: space-between;
align-items: center;
}
.columnCenter{
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.columnEnd{
display: flex;
flex-direction: column;
justify-content: flex-end;
align-items: center;
}
/* 返回按钮 */
.back-area {
position: fixed;
top:0;
left:0;
width:100%;
height:100%;
z-index: 999;
}
.back-view {
width: 80rpx;
height: 80rpx;
}
.backBtn{
border:solid 2rpx #ffffff;
background: rgba(0,0,0,0.5);
border-radius: 50%;
color: #ffffff;
font-weight: bold;
width: 80rpx;
height:80rpx;
font-size:24rpx;
}
/* 页面标题 */
.pageTitleBox{
width: 100%;
position: relative;
z-index: 999;
}
.pageSecondTitleBox{
background: #5ac994;
position: fixed;
z-index: 999;
left:0;
top:0;
width:100%;
}
.pageTitle {
width: 100%;
text-align: center;
color: #fff;
font-size: 36rpx;
position: fixed;
left:0;
top:0;
z-index: 999;
font-weight: bold;
}
/*规格*/
.detailSpec{
background: #f5f5f5;
color:#333333;
}
.detailSpecActive{
background: #e6f2ed !important;
color:#5AC994 !important;
}
/*选好了大按钮*/
.chooseOkBtn{
background: #5AC994;
width:100%;
height:80rpx;
color:#ffffff;
}
/* 关闭按钮x */
.closeBox{
position: absolute;
top:20rpx;
right:20rpx;
width:40rpx;
height:40rpx;
}
.closeBox text{
background: #999999;
position: absolute;
left:50%;
top:50%;
transform: translate(-50%,-50%) rotate(-45deg);
}
.closeBox text:first-of-type{
width:28rpx;
height:2rpx;
}
.closeBox text:last-of-type{
width:2rpx;
height:28rpx;
}
/*弹窗黑是背景*/
.blackBk{
width:100%;
height:100vh;
background: rgba(0,0,0,0.7);
position: fixed;
left:0;
top:0;
z-index: 99999;
}
/*在底部的弹窗白底*/
.bottomWhiteBox{
background: #ffffff;
position: absolute;
bottom:0;
left:0;
width:100%;
padding:20rpx 20rpx 0rpx 20rpx;
box-sizing: border-box;
}
/*二维码canvas*/
.canvas-box{
position: fixed;
right:-100%;
top:-100%;
}
/*请稍后*/
.loadingBox{
position: fixed;
top:0;
left:0;
width:100%;
height:100vh;
z-index: 99999;
}
.loadingText{
color:#ffffff;
padding:5rpx 10rpx;
border-radius: 5rpx;
background: rgba(0,0,0,0.8);
}
/*动画箭头*/
.openSwitch{
transform: rotate(180deg);
}
.closeSwitch{
transform: rotate(0);
}
/*点击获取地理位置*/
.getLocationBox{
position: fixed;
left:0;
top:0;
width:100%;
height:100vh;
z-index: 99999;
}
.getLocationText{
background: #5ac994;
color:#ffffff;
}
/* 透明按钮 */
.transparentBtn{
background: transparent;
}
.transparentBtn::after{
outline: none;
border: none;
}
.getUserInfoBtn{
position: absolute;
left:0;
top:0;
width:100%;
height:100%;
z-index: 999;
}
/* /新 */
.jiantou-right{
width:23rpx;
height:41rpx;
}
.red{
color:red;
}
.yellow{
color:#F29438;
}
.deepYellow{
color:#633319;
}