UNIAPP实战项目笔记26 底部滑块动画效果完善底部滑块修改返回键默认行为

底部滑块动画效果

完善底部滑块

修改返回键默认行为

details.vue
主要代码如下:

<template>
    <view class="details">
        <!-- 商品图 -->
        <swiper :indicator-dots="true" :autoplay="true" :interval="3000" :duration="1000">
            <swiper-item
                v-for="(item,index) in swiperList"
                :key="index"
            >
                <view class="swiper-item">
                    <image class="swiper-img" :src="item.imgUrl" mode=""></image>
                </view>
            </swiper-item>
        </swiper>
        <!-- 价格和名称 -->
        <view class="details-goods">
            <view class="goods-pprice">¥399.00 </view>
            <view class="goods-oprice">¥599.00 </view>
            <view class="goods-name">大衣绒毛大款貂皮球毛 </view>
        </view>
        <!-- 商品详情图 -->
        <view class="">
            <view class=""><image class="details-img" src="../../static/img/b3.jpg" mode=""></image></view>
            <view class=""><image class="details-img" src="../../static/img/b3.jpg" mode=""></image></view>
            <view class=""><image class="details-img" src="../../static/img/b3.jpg" mode=""></image></view>
            <view class=""><image class="details-img" src="../../static/img/b3.jpg" mode=""></image></view>
            <view class=""><image class="details-img" src="../../static/img/b3.jpg" mode=""></image></view>
            <view class=""><image class="details-img" src="../../static/img/b3.jpg" mode=""></image></view>
        </view>
        
        <!-- 商品列表 -->
        <Card cardTitle="看了又看"></Card>
        <CommodityList :dataList="dataList"></CommodityList>
        
        <!-- 底部 -->
        <view class="details-foot">
            <view class="iconfont icon-xiaoxi"></view>
            <view class="iconfont icon-31gouwuche"></view>
            <view class="add-shopcart" @tap="showPop">加入购物车</view>
            <view class="purchase" @tap="showPop">立刻购买</view>
        </view>
        
        <!-- 底部弹出层 -->
        <view class="pop" v-show="isShow" @touchmove.stop="">
            <!-- 蒙层 -->
            <view class="pop-mask" @tap="hidePop"> </view>
            <!-- 内容块 -->
            <view class="pop-box" :animation="animationData">
                <view class="">
                    <image class="pop-img" src="../../static/img/b3.jpg" mode=""></image>
                </view>
                <view class="pop-num">
                    <view class="">
                        购买数量
                    </view>
                    <UniNumberBox min="1"></UniNumberBox>
                </view>
                <view class="pop-sub">
                    确定
                </view>
            </view>
        </view>
    </view>
</template>

<script>
    import Card from '@/components/common/Card.vue';
    import CommodityList from '@/components/common/CommodityList.vue';
    import UniNumberBox from '@/components/uni/uni-number-box/uni-number-box.vue';
    export default {
        data() {
            return {
                isShow:false,
                animationData:{},
                swiperList:[
                    {imgUrl:"../../static/img/b3.jpg"},
                    {imgUrl:"../../static/img/b3.jpg"},
                    {imgUrl:"../../static/img/b3.jpg"}
                ],
                dataList:[{
                      id:1,
                      imgUrl:"../../static/logo.png",
                      name:"迪奥绒毛大衣,今年必抢,错过瞬时不爽了,爆款疯狂销售",
                      pprice:"299",
                      oprice:"659",
                      discount:"5.2"
                  },
                  {
                      id:2,
                      imgUrl:"../../static/logo.png",
                      name:"迪奥绒毛大衣,今年必抢,错过瞬时不爽了,爆款疯狂销售",
                      pprice:"299",
                      oprice:"659",
                      discount:"5.2"
                  },{
                      id:3,
                      imgUrl:"../../static/logo.png",
                      name:"迪奥绒毛大衣,今年必抢,错过瞬时不爽了,爆款疯狂销售",
                      pprice:"299",
                      oprice:"659",
                      discount:"5.2"
                  }]
            };
        },
        components:{
            Card,
            CommodityList,
            UniNumberBox
        },
        // 修改返回默认行为
        onBackPress(){
            if (this.isShow) {
                this.hidePop();
                return true;  
            }
            
        },
        methods:{
            showPop(){
                // 初始化一个动画
                var animation = uni.createAnimation({
                    duration:200 // 动画时间
                });
                // 定义动画内容
                animation.translateY(600).step();
                // 导出动画数据传递给data层
                this.animationData = animation.export();
                this.isShow = true;
                setTimeout(()=>{
                    animation.translateY(0).step();
                    this.animationData = animation.export();
                },200)
            },
            hidePop(){
                var animation = uni.createAnimation({
                    duration:200
                });
                animation.translateY(600).step();
                this.animationData = animation.export();
                this.isShow = true;
                setTimeout(()=>{
                    animation.translateY(0).step();
                    this.isShow = false;
                },200)
            },
        }
    }
</script>

<style lang="scss">
swiper{
    width: 100%;
    height: 700rpx;
}
.swiper-img{
    width: 100%;
    height: 700rpx;
}
.details{
    padding-bottom: 90rpx;
}
.details-goods{
    text-align: center;
    font-weight: bold;
    font-size: 36rpx;
    padding: 10rpx 0;
}
.details-img{
    width: 100%;
}
.details-foot{
    position: fixed;
    left: 0;
    bottom: 0;
    width: 100%;
    height: 90rpx;
    display: flex;
    align-items: center;
    justify-content: center;
    background-color: #FFFFFF;
}
.details-foot .iconfont{
    width: 60rpx;
    height: 60rpx;
    border-radius: 100%;
    background-color: #000000;
    color: #FFFFFF;
    text-align: center;
    margin: 0 10rpx;
    line-height: 60rpx;
}
.add-shopcart{
    margin: 0 40rpx;
    padding: 6rpx 30rpx;
    background-color: #000000;
    color: #FFFFFF;
    border-radius: 40rpx;
    
}
.purchase{
    margin: 0 40rpx;
    padding: 6rpx 30rpx;
    background-color: #49BDFB;
    color: #FFFFFF;
    border-radius: 40rpx;
}
.pop{
    position: fixed;
    left: 0;
    top: 0;
    width: 100%;
    height: 100%;
    z-index: 9999;
}
.pop-mask{
    position: absolute;
    left: 0;
    top: 0;
    width: 100%;
    height: 100%;
    background-color: rgba(0, 0, 0, 0.3);
}
.pop-box{
    position: absolute;
    left: 0;
    bottom: 0;
    width: 100%;
    background-color: #FFFFFF;
}
.pop-img{
    width: 260rpx;
    height: 260rpx;
    top:-130rpx;
    border-radius:20rpx 20rpx 0 0;
    margin: 30rpx;
}
.pop-sub{
    line-height: 80rpx;
    background-color: #49BDFB;
    color: #FFFFFF;
    text-align: center;
}
.pop-num{
    padding: 20rpx;
    display: flex;
    justify-content: space-between;
}

</style>

实例图片

下部自动弹出动画

目录结构

前端目录结构
  • manifest.json 配置文件: appid、logo…

  • pages.json 配置文件: 导航、 tabbar、 路由

  • main.js vue初始化入口文件

  • App.vue 全局配置:样式、全局监视

  • static 静态资源:图片、字体图标

  • page 页面

    • index
      • index.vue
    • list
      • list.vue
    • my
      • my.vue
    • search
      • search.vue
    • search-list
      • search-list.vue
    • shopcart
      • shopcart.vue
    • details
      • details.vue
  • components 组件

    • index
      • Banner.vue
      • Hot.vue
      • Icons.vue
      • indexSwiper.vue
      • Recommend.vue
      • Shop.vue
    • common
      • Card.vue
      • Commondity.vue
      • CommondityList.vue
      • Line.vue
      • ShopList.vue
    • uni
      • uni-number-box
        • uni-number-box.vue
  • common 公共文件:全局css文件 || 全局js文件

    • api
      • request.js
    • common.css
    • uni.css

uni-number-box 使用的是uni默认组件

代码如下
uni-number-box.vue

<template>
	<view class="uni-numbox">
		<view @click="_calcValue('minus')" class="uni-numbox__minus uni-numbox-btns" :style="{background}">
			<text class="uni-numbox--text" :class="{ 'uni-numbox--disabled': inputValue <= min || disabled }" :style="{color}">-</text>
		</view>
		<input :disabled="disabled" @focus="_onFocus" @blur="_onBlur" class="uni-numbox__value" type="number"
			v-model="inputValue" :style="{background, color}" />
		<view @click="_calcValue('plus')" class="uni-numbox__plus uni-numbox-btns" :style="{background}">
			<text class="uni-numbox--text" :class="{ 'uni-numbox--disabled': inputValue >= max || disabled }" :style="{color}">+</text>
		</view>
	</view>
</template>
<script>
	/**
	 * NumberBox 数字输入框
	 * @description 带加减按钮的数字输入框
	 * @tutorial https://ext.dcloud.net.cn/plugin?id=31
	 * @property {Number} value 输入框当前值
	 * @property {Number} min 最小值
	 * @property {Number} max 最大值
	 * @property {Number} step 每次点击改变的间隔大小
	 * @property {String} background 背景色
	 * @property {String} color 字体颜色(前景色)
	 * @property {Boolean} disabled = [true|false] 是否为禁用状态
	 * @event {Function} change 输入框值改变时触发的事件,参数为输入框当前的 value
	 * @event {Function} focus 输入框聚焦时触发的事件,参数为 event 对象
	 * @event {Function} blur 输入框失焦时触发的事件,参数为 event 对象
	 */

	export default {
		name: "UniNumberBox",
		emits: ['change', 'input', 'update:modelValue', 'blur', 'focus'],
		props: {
			value: {
				type: [Number, String],
				default: 1
			},
			modelValue: {
				type: [Number, String],
				default: 1
			},
			min: {
				type: Number,
				default: 0
			},
			max: {
				type: Number,
				default: 100
			},
			step: {
				type: Number,
				default: 1
			},
			background: {
				type: String,
				default: '#f5f5f5'
			},
			color: {
				type: String,
				default: '#333'
			},
			disabled: {
				type: Boolean,
				default: false
			}
		},
		data() {
			return {
				inputValue: 0
			};
		},
		watch: {
			value(val) {
				this.inputValue = +val;
			},
			modelValue(val) {
				this.inputValue = +val;
			}
		},
		created() {
			if (this.value === 1) {
				this.inputValue = +this.modelValue;
			}
			if (this.modelValue === 1) {
				this.inputValue = +this.value;
			}
		},
		methods: {
			_calcValue(type) {
				if (this.disabled) {
					return;
				}
				const scale = this._getDecimalScale();
				let value = this.inputValue * scale;
				let step = this.step * scale;
				if (type === "minus") {
					value -= step;
					if (value < (this.min * scale)) {
						return;
					}
					if (value > (this.max * scale)) {
						value = this.max * scale
					}
				}

				if (type === "plus") {
					value += step;
					if (value > (this.max * scale)) {
						return;
					}
					if (value < (this.min * scale)) {
						value = this.min * scale
					}
				}

				this.inputValue = (value / scale).toFixed(String(scale).length - 1);
				this.$emit("change", +this.inputValue);
				// TODO vue2 兼容
				this.$emit("input", +this.inputValue);
				// TODO vue3 兼容
				this.$emit("update:modelValue", +this.inputValue);
			},
			_getDecimalScale() {

				let scale = 1;
				// 浮点型
				if (~~this.step !== this.step) {
					scale = Math.pow(10, String(this.step).split(".")[1].length);
				}
				return scale;
			},
			_onBlur(event) {
				this.$emit('blur', event)
				let value = event.detail.value;
				if (!value) {
					// this.inputValue = 0;
					return;
				}
				value = +value;
				if (value > this.max) {
					value = this.max;
				} else if (value < this.min) {
					value = this.min;
				}
				const scale = this._getDecimalScale();
				this.inputValue = value.toFixed(String(scale).length - 1);
				this.$emit("change", +this.inputValue);
				this.$emit("input", +this.inputValue);
			},
			_onFocus(event) {
				this.$emit('focus', event)
			}
		}
	};
</script>
<style lang="scss" scoped>
	$box-height: 26px;
	$bg: #f5f5f5;
	$br: 2px;
	$color: #333;

	.uni-numbox {
		/* #ifndef APP-NVUE */
		display: flex;
		/* #endif */
		flex-direction: row;
	}

	.uni-numbox-btns {
		/* #ifndef APP-NVUE */
		display: flex;
		/* #endif */
		flex-direction: row;
		align-items: center;
		justify-content: center;
		padding: 0 8px;
		background-color: $bg;
		/* #ifdef H5 */
		cursor: pointer;
		/* #endif */
	}

	.uni-numbox__value {
		margin: 0 2px;
		background-color: $bg;
		width: 40px;
		height: $box-height;
		text-align: center;
		font-size: 14px;
		border-left-width: 0;
		border-right-width: 0;
		color: $color;
	}

	.uni-numbox__minus {
		border-top-left-radius: $br;
		border-bottom-left-radius: $br;
	}

	.uni-numbox__plus {
		border-top-right-radius: $br;
		border-bottom-right-radius: $br;
	}

	.uni-numbox--text {
		// fix nvue
		line-height: 20px;

		font-size: 20px;
		font-weight: 300;
		color: $color;
	}

	.uni-numbox .uni-numbox--disabled {
		color: #c0c0c0 !important;
		/* #ifdef H5 */
		cursor: not-allowed;
		/* #endif */
	}
</style>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值