|
@@ -0,0 +1,529 @@
|
|
|
|
|
+<template>
|
|
|
|
|
+ <transition name="zoom-center" appear>
|
|
|
|
|
+ <div v-if="visible" class="slide_code_modal" @click.self="HandleConfirm">
|
|
|
|
|
+ <div class="slide_code_content">
|
|
|
|
|
+ <!-- <div class="modal_header">
|
|
|
|
|
+ <h3>{{ title }}</h3>
|
|
|
|
|
+ <i class="el-icon-close close_btn" @click="HandleConfirm"></i>
|
|
|
|
|
+ </div> -->
|
|
|
|
|
+
|
|
|
|
|
+ <div class="modal_body">
|
|
|
|
|
+ <slot>
|
|
|
|
|
+ <div class="slider_container">
|
|
|
|
|
+ <div class="slider_text">
|
|
|
|
|
+ 请拖动滑块完成拼图
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="container_bg" :style="{ backgroundImage: sliderBgUrl ? 'url(' + sliderBgUrl + ')' : '' }">
|
|
|
|
|
+ <div class="slider_bg" :style="{ left: sliderPositionX + 'px',top:sliderPositionY+'px', backgroundImage: sliderImgUrl ? 'url(' + sliderImgUrl + ')' : '' }">
|
|
|
|
|
+
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <!-- 验证成功的样式 -->
|
|
|
|
|
+ <transition name="slide-up">
|
|
|
|
|
+ <div class="slider_sucess" v-if="isSuccess">
|
|
|
|
|
+ {{sliderTime }}秒的速度超过{{sliderPrent}}%的用户
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="slider_failed" v-if="isFailed">
|
|
|
|
|
+ 验证失败,请重新拖动滑块尝试
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </transition>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="slider_track">
|
|
|
|
|
+
|
|
|
|
|
+ <div class="slider_button" :style="{ left: sliderPositionX + 'px' }" @mousedown="startSlide" @touchstart="startSlide">
|
|
|
|
|
+ <i class="el-icon-d-arrow-right"></i>
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </slot>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </transition>
|
|
|
|
|
+</template>
|
|
|
|
|
+
|
|
|
|
|
+<script>
|
|
|
|
|
+import user from "@/http/api/user";
|
|
|
|
|
+
|
|
|
|
|
+export default {
|
|
|
|
|
+ name: 'SlideCode',
|
|
|
|
|
+ props: {
|
|
|
|
|
+ value: {
|
|
|
|
|
+ type: Boolean,
|
|
|
|
|
+ default: false
|
|
|
|
|
+ },//关闭打开
|
|
|
|
|
+
|
|
|
|
|
+ sliderUUID:{
|
|
|
|
|
+ type:String,
|
|
|
|
|
+ default:''
|
|
|
|
|
+ },//图片唯一凭证
|
|
|
|
|
+
|
|
|
|
|
+ sliderBgUrl:{
|
|
|
|
|
+ type:String,
|
|
|
|
|
+ default:''
|
|
|
|
|
+ },//背景图片地址
|
|
|
|
|
+
|
|
|
|
|
+ sliderImgUrl:{
|
|
|
|
|
+ type:String,
|
|
|
|
|
+ default:''
|
|
|
|
|
+ },//滑块图片地址
|
|
|
|
|
+
|
|
|
|
|
+ sliderPositionY:{
|
|
|
|
|
+ type:[Number,String],
|
|
|
|
|
+ default:0
|
|
|
|
|
+ },//滑块y轴位置
|
|
|
|
|
+
|
|
|
|
|
+ title: {
|
|
|
|
|
+ type: String,
|
|
|
|
|
+ default: '安全验证'
|
|
|
|
|
+ },
|
|
|
|
|
+
|
|
|
|
|
+ },
|
|
|
|
|
+ data() {
|
|
|
|
|
+ return {
|
|
|
|
|
+ visible: false,
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ sliderPositionX: 0,//滑块的x轴位置
|
|
|
|
|
+ sliderWidth: 0,
|
|
|
|
|
+ sliderTime: 0,//滑动耗时(秒)
|
|
|
|
|
+ sliderPrent:'98',//百分比
|
|
|
|
|
+ startTime: 0,//开始滑动的时间戳
|
|
|
|
|
+ sliderVerified:0,//滑动验证码验证状态 0 未开始 1 验证成功 -1 验证失败
|
|
|
|
|
+ isSliding: false,//是否开始滑动
|
|
|
|
|
+ isSuccess:false,//是否验证成功
|
|
|
|
|
+ isFailed:false,//是否验证失败
|
|
|
|
|
+ startX: 0,//这里将用于存储鼠标相对于轨道的初始偏移
|
|
|
|
|
+
|
|
|
|
|
+ sliderText: '按住滑块拖动',
|
|
|
|
|
+
|
|
|
|
|
+ };
|
|
|
|
|
+ },
|
|
|
|
|
+ watch: {
|
|
|
|
|
+ value: {
|
|
|
|
|
+ handler(newVal) {
|
|
|
|
|
+ this.visible = newVal;
|
|
|
|
|
+ this.ResetSlider();//重置滑块位置
|
|
|
|
|
+ },
|
|
|
|
|
+ immediate: true
|
|
|
|
|
+ },
|
|
|
|
|
+ },
|
|
|
|
|
+ methods: {
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ //验证滑动验证码位置是否正确
|
|
|
|
|
+ VerifySliderCaptcha()
|
|
|
|
|
+ {
|
|
|
|
|
+ let param={
|
|
|
|
|
+ sliderUUID: this.sliderUUID,//图片唯一凭证
|
|
|
|
|
+ x: Math.round(this.sliderPositionX),//滑块位置
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ user.checkSlideCaptcha(param).then(res =>
|
|
|
|
|
+ {
|
|
|
|
|
+ console.log("验证滑动验证码返回结果",res);
|
|
|
|
|
+
|
|
|
|
|
+ if(res.code==200)
|
|
|
|
|
+ {
|
|
|
|
|
+ //验证成功
|
|
|
|
|
+ this.isSuccess = true;
|
|
|
|
|
+ this.sliderVerified = 1;
|
|
|
|
|
+ this.sliderPhone=res.data;
|
|
|
|
|
+ setTimeout(() => {
|
|
|
|
|
+ this.HandleConfirm();//关闭弹窗
|
|
|
|
|
+ }, 1000);
|
|
|
|
|
+
|
|
|
|
|
+ // 验证成功后,发送请求获取验证码
|
|
|
|
|
+ // this.sliderPhone=res.data;
|
|
|
|
|
+
|
|
|
|
|
+ // const timer = setInterval(() => {
|
|
|
|
|
+ // this.count--;
|
|
|
|
|
+ // this.codeText = `${this.count} 秒`;
|
|
|
|
|
+ // if (this.count <= 0) {
|
|
|
|
|
+ // clearInterval(timer);
|
|
|
|
|
+ // this.isCount = false;
|
|
|
|
|
+ // this.count = 300;
|
|
|
|
|
+ // this.codeText = '重新获取'
|
|
|
|
|
+ // }
|
|
|
|
|
+ // }, 1000);
|
|
|
|
|
+
|
|
|
|
|
+ }
|
|
|
|
|
+ else if(res.code==601)
|
|
|
|
|
+ {
|
|
|
|
|
+ //验证成功
|
|
|
|
|
+ this.sliderVerified = 1;
|
|
|
|
|
+ this.isSuccess = true;
|
|
|
|
|
+ // 验证成功后,发送请求获取验证码
|
|
|
|
|
+ this.sliderPhone=res.data;
|
|
|
|
|
+ this.$message.warning("滑块验证通过,您上次的验证码还在有效期,请输入上次发送的验证码进行登录!");
|
|
|
|
|
+ setTimeout(() => {
|
|
|
|
|
+ this.HandleConfirm();//关闭弹窗
|
|
|
|
|
+ }, 1000);
|
|
|
|
|
+ }
|
|
|
|
|
+ else if(res.code==602)
|
|
|
|
|
+ {
|
|
|
|
|
+ //滑动验证码过期 重新获取验证码
|
|
|
|
|
+ this.$message.error("滑块验证码已过期,已为您重新获取!");
|
|
|
|
|
+ // this.ObtainSliderImg();
|
|
|
|
|
+ this.$emit('refresh');//重新获取验证码
|
|
|
|
|
+ }
|
|
|
|
|
+ else if(res.code==400)
|
|
|
|
|
+ {
|
|
|
|
|
+ this.isFailed=true;
|
|
|
|
|
+ //滑动验证码过期 重新获取验证码
|
|
|
|
|
+ // this.$message.error(res.msg);
|
|
|
|
|
+ this.sliderVerified = -1;
|
|
|
|
|
+ this.sliderPositionX=0;
|
|
|
|
|
+ }
|
|
|
|
|
+ else{
|
|
|
|
|
+ this.isFailed=true;
|
|
|
|
|
+ //验证失败
|
|
|
|
|
+ this.sliderVerified = -1;
|
|
|
|
|
+ //重置滑块位置
|
|
|
|
|
+ this.sliderPositionX=0;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ //延迟2秒关闭失败层
|
|
|
|
|
+ setTimeout(() => {
|
|
|
|
|
+ this.isFailed = false;
|
|
|
|
|
+
|
|
|
|
|
+ }, 2000);
|
|
|
|
|
+ })
|
|
|
|
|
+
|
|
|
|
|
+ },
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ //关闭弹窗
|
|
|
|
|
+ HandleConfirm() {
|
|
|
|
|
+ this.visible = false;
|
|
|
|
|
+
|
|
|
|
|
+ this.$emit('close',this.sliderVerified,this.sliderPhone);
|
|
|
|
|
+ },
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ //重置滑块位置
|
|
|
|
|
+ ResetSlider() {
|
|
|
|
|
+ this.sliderPositionX = 0;
|
|
|
|
|
+ this.sliderVerified = 0;
|
|
|
|
|
+ this.sliderWidth = 0;
|
|
|
|
|
+ this.sliderText = '按住滑块拖动';
|
|
|
|
|
+ this.isSuccess = false;
|
|
|
|
|
+ this.isFailed=false;
|
|
|
|
|
+ },
|
|
|
|
|
+
|
|
|
|
|
+ //开始滑动事件
|
|
|
|
|
+ startSlide(event) {
|
|
|
|
|
+ event.preventDefault();
|
|
|
|
|
+ event.stopPropagation();
|
|
|
|
|
+ this.isSliding = true;//是否滑动
|
|
|
|
|
+
|
|
|
|
|
+ // 记录开始时间
|
|
|
|
|
+ this.startTime = Date.now();
|
|
|
|
|
+ // 获取轨道元素
|
|
|
|
|
+ const track = this.$el.querySelector('.slider_track');
|
|
|
|
|
+ const rect = track.getBoundingClientRect();
|
|
|
|
|
+
|
|
|
|
|
+ // 计算鼠标点击位置距离轨道左边缘的距离
|
|
|
|
|
+ const clientX = event.type.includes('mouse') ? event.clientX : event.touches[0].clientX;
|
|
|
|
|
+ this.startX = clientX - rect.left - this.sliderPositionX;
|
|
|
|
|
+
|
|
|
|
|
+ document.addEventListener('mousemove', this.onSlide);
|
|
|
|
|
+ document.addEventListener('mouseup', this.stopSlide);
|
|
|
|
|
+ document.addEventListener('touchmove', this.onSlide, { passive: false });
|
|
|
|
|
+ document.addEventListener('touchend', this.stopSlide);
|
|
|
|
|
+ },
|
|
|
|
|
+
|
|
|
|
|
+ onSlide(event)
|
|
|
|
|
+ {
|
|
|
|
|
+ if (!this.isSliding || this.isSuccess) return;
|
|
|
|
|
+
|
|
|
|
|
+ const track = this.$el.querySelector('.slider_track');
|
|
|
|
|
+ const rect = track.getBoundingClientRect();
|
|
|
|
|
+
|
|
|
|
|
+ // 计算当前鼠标距离轨道左边缘的距离
|
|
|
|
|
+ const currentClientX = event.type.includes('mouse') ? event.clientX : event.touches[0].clientX;
|
|
|
|
|
+ const currentRelativeX = currentClientX - rect.left;
|
|
|
|
|
+
|
|
|
|
|
+ // 新的滑块位置 = 当前鼠标相对位置 - 初始点击时的相对偏移
|
|
|
|
|
+ // 这样能保证滑块跟随鼠标移动,且不会发生跳变
|
|
|
|
|
+ let newPixelPosition = currentRelativeX - this.startX;
|
|
|
|
|
+
|
|
|
|
|
+ // 计算最大可移动距离
|
|
|
|
|
+ const maxPosition = 300 - 50;
|
|
|
|
|
+
|
|
|
|
|
+ // 限制范围
|
|
|
|
|
+ newPixelPosition = Math.max(0, Math.min(maxPosition, newPixelPosition));
|
|
|
|
|
+
|
|
|
|
|
+ this.sliderPositionX = newPixelPosition;
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ },
|
|
|
|
|
+
|
|
|
|
|
+ stopSlide() {
|
|
|
|
|
+ if (!this.isSliding) return;
|
|
|
|
|
+ // 计算滑动耗时
|
|
|
|
|
+ const endTime = Date.now();
|
|
|
|
|
+ this.sliderTime = parseFloat(((endTime - this.startTime) / 1000).toFixed(2));
|
|
|
|
|
+
|
|
|
|
|
+ console.log('滑动耗时:', this.sliderTime, '秒');
|
|
|
|
|
+ // 根据滑动时间计算百分比
|
|
|
|
|
+ if (this.sliderTime <= 1) {
|
|
|
|
|
+ this.sliderPrent = 99;
|
|
|
|
|
+ } else if (this.sliderTime <= 2) {
|
|
|
|
|
+ this.sliderPrent = 98;
|
|
|
|
|
+ } else if (this.sliderTime <= 3) {
|
|
|
|
|
+ this.sliderPrent = 97;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ this.sliderPrent = Math.max(0, 96 - Math.floor(this.sliderTime - 3));
|
|
|
|
|
+ }
|
|
|
|
|
+ this.isSliding = false;
|
|
|
|
|
+ document.removeEventListener('mousemove', this.onSlide);
|
|
|
|
|
+ document.removeEventListener('mouseup', this.stopSlide);
|
|
|
|
|
+ document.removeEventListener('touchmove', this.onSlide);
|
|
|
|
|
+ document.removeEventListener('touchend', this.stopSlide);
|
|
|
|
|
+ // 松开鼠标后,发送请求验证滑块位置
|
|
|
|
|
+ this.VerifySliderCaptcha();
|
|
|
|
|
+
|
|
|
|
|
+ },
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ },
|
|
|
|
|
+
|
|
|
|
|
+ beforeDestroy() {
|
|
|
|
|
+ document.removeEventListener('mousemove', this.onSlide);
|
|
|
|
|
+ document.removeEventListener('mouseup', this.stopSlide);
|
|
|
|
|
+ document.removeEventListener('touchmove', this.onSlide);
|
|
|
|
|
+ document.removeEventListener('touchend', this.stopSlide);
|
|
|
|
|
+ }
|
|
|
|
|
+};
|
|
|
|
|
+</script>
|
|
|
|
|
+
|
|
|
|
|
+<style scoped lang="scss">
|
|
|
|
|
+.slide_code_modal {
|
|
|
|
|
+ position: fixed;
|
|
|
|
|
+ top: 0;
|
|
|
|
|
+ left: 0;
|
|
|
|
|
+ right: 0;
|
|
|
|
|
+ bottom: 0;
|
|
|
|
|
+ // background-color: rgba(0, 0, 0, 0.5);//不要遮罩层
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ justify-content: center;
|
|
|
|
|
+ z-index: 9999;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.slide_code_content {
|
|
|
|
|
+ background: #fff;
|
|
|
|
|
+ border-radius: 8px;
|
|
|
|
|
+ box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);
|
|
|
|
|
+ min-width: 300px;
|
|
|
|
|
+ max-width: 600px;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.modal_header {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ justify-content: space-between;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ padding: 16px 20px;
|
|
|
|
|
+ border-bottom: 1px solid #e4e7ed;
|
|
|
|
|
+
|
|
|
|
|
+ h3 {
|
|
|
|
|
+ margin: 0;
|
|
|
|
|
+ font-size: 16px;
|
|
|
|
|
+ color: #303133;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .close_btn {
|
|
|
|
|
+ cursor: pointer;
|
|
|
|
|
+ font-size: 18px;
|
|
|
|
|
+ color: #909399;
|
|
|
|
|
+ transition: color 0.3s;
|
|
|
|
|
+
|
|
|
|
|
+ &:hover {
|
|
|
|
|
+ color: #f56c6c;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.modal_body {
|
|
|
|
|
+ padding: 20px;
|
|
|
|
|
+ min-height: 100px;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.modal_footer {
|
|
|
|
|
+ padding: 12px 20px;
|
|
|
|
|
+ border-top: 1px solid #e4e7ed;
|
|
|
|
|
+ text-align: right;
|
|
|
|
|
+
|
|
|
|
|
+ .el-button {
|
|
|
|
|
+ margin-left: 10px;
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.slider_container {
|
|
|
|
|
+
|
|
|
|
|
+ .slider_text
|
|
|
|
|
+ {
|
|
|
|
|
+ text-align: center;
|
|
|
|
|
+ height: 36px;
|
|
|
|
|
+ font-size: 16px;
|
|
|
|
|
+ }
|
|
|
|
|
+ //背景的图片
|
|
|
|
|
+ .container_bg
|
|
|
|
|
+ {
|
|
|
|
|
+ width: 300px;
|
|
|
|
|
+ height: 180px;
|
|
|
|
|
+ background-size: 100% 100%;
|
|
|
|
|
+ background-position: 0 0;
|
|
|
|
|
+ background-repeat: no-repeat;
|
|
|
|
|
+ position: relative;
|
|
|
|
|
+ overflow: hidden;
|
|
|
|
|
+ .slider_bg
|
|
|
|
|
+ {
|
|
|
|
|
+ width: 50px;
|
|
|
|
|
+ height: 50px;
|
|
|
|
|
+ background-position: 0 0;
|
|
|
|
|
+ background-repeat: no-repeat;
|
|
|
|
|
+ background-size: 100% 100%;
|
|
|
|
|
+ position: absolute;
|
|
|
|
|
+ left: 0;
|
|
|
|
|
+ top: 35px;
|
|
|
|
|
+ border-radius: 5px;
|
|
|
|
|
+ border:1px solid red;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .slider_sucess
|
|
|
|
|
+ {
|
|
|
|
|
+ width: 100%;
|
|
|
|
|
+ height: 40px;
|
|
|
|
|
+ background-color: #2BC644;
|
|
|
|
|
+ position: absolute;
|
|
|
|
|
+ left: 0;
|
|
|
|
|
+ bottom: 0;
|
|
|
|
|
+ z-index: 88;
|
|
|
|
|
+ line-height: 40px;
|
|
|
|
|
+ color:#fff;
|
|
|
|
|
+ font-size: 12px;
|
|
|
|
|
+ text-align: center;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .slider_failed
|
|
|
|
|
+ {
|
|
|
|
|
+ width: 100%;
|
|
|
|
|
+ height: 40px;
|
|
|
|
|
+ background-color: #ff5d39;
|
|
|
|
|
+ position: absolute;
|
|
|
|
|
+ left: 0;
|
|
|
|
|
+ bottom: 0;
|
|
|
|
|
+ z-index: 88;
|
|
|
|
|
+ line-height: 40px;
|
|
|
|
|
+ color:#fff;
|
|
|
|
|
+ font-size: 12px;
|
|
|
|
|
+ text-align: center;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.slider_track {
|
|
|
|
|
+ position: relative;
|
|
|
|
|
+ height: 40px;
|
|
|
|
|
+ background-color: #e4e7ed;
|
|
|
|
|
+ border-radius: 20px;
|
|
|
|
|
+ overflow: hidden;
|
|
|
|
|
+ user-select: none;
|
|
|
|
|
+ cursor: pointer;
|
|
|
|
|
+ margin-top: 20px;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.slider_button {
|
|
|
|
|
+ position: absolute;
|
|
|
|
|
+ left: 0;
|
|
|
|
|
+ top: 0;
|
|
|
|
|
+ width: 50px;
|
|
|
|
|
+ height: 36px;
|
|
|
|
|
+ background: #fff;
|
|
|
|
|
+ border: 2px solid #409eff;
|
|
|
|
|
+ border-radius: 25px;
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ justify-content: center;
|
|
|
|
|
+ cursor: grab;
|
|
|
|
|
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ i {
|
|
|
|
|
+ color: #409eff;
|
|
|
|
|
+ font-size: 16px;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ &:active {
|
|
|
|
|
+ cursor: grabbing;
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// 从底部升起的动画
|
|
|
|
|
+.slide-up-enter-active {
|
|
|
|
|
+ animation: slideUpIn 0.5s cubic-bezier(0.4, 0, 0.2, 1);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.slide-up-leave-active {
|
|
|
|
|
+ animation: slideUpOut 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+@keyframes slideUpIn {
|
|
|
|
|
+ from {
|
|
|
|
|
+ transform: translateY(100%);
|
|
|
|
|
+ opacity: 0;
|
|
|
|
|
+ }
|
|
|
|
|
+ to {
|
|
|
|
|
+ transform: translateY(0);
|
|
|
|
|
+ opacity: 1;
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+@keyframes slideUpOut {
|
|
|
|
|
+ from {
|
|
|
|
|
+ transform: translateY(0);
|
|
|
|
|
+ opacity: 1;
|
|
|
|
|
+ }
|
|
|
|
|
+ to {
|
|
|
|
|
+ transform: translateY(100%);
|
|
|
|
|
+ opacity: 0;
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.zoom-center-enter-active {
|
|
|
|
|
+ transition: all 0.8s cubic-bezier(0.4, 0, 0.2, 1);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.zoom-center-leave-active {
|
|
|
|
|
+ transition: all 0.8s cubic-bezier(0.4, 0, 0.2, 1);
|
|
|
|
|
+}
|
|
|
|
|
+.zoom-center-enter,
|
|
|
|
|
+.zoom-center-leave-to {
|
|
|
|
|
+ opacity: 0;
|
|
|
|
|
+ transform: scale(0.5);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.zoom-center-enter-to {
|
|
|
|
|
+ opacity: 1;
|
|
|
|
|
+ transform: scale(1);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.zoom-center-leave {
|
|
|
|
|
+ opacity: 1;
|
|
|
|
|
+ transform: scale(1);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.zoom-center-leave-to {
|
|
|
|
|
+ opacity: 0;
|
|
|
|
|
+ transform: scale(0.5);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+</style>
|