如何实现一个左滑出现删除按钮的功能

2 篇文章 1 订阅

给列表添加左滑出现删除按钮的效果,经常出现在类似购物车的实例中。今天我们一起实现下这个效果。基于uniapp,h5端同理

<template>
  <view class="list-item">
    <!-- 滑动容器 -->
    <view
      class="swipe-container"
      @touchstart="onTouchStart"
      @touchmove="onTouchMove"
      @touchend="onTouchEnd"
	  :style="{transform:‘translateX(’+moveX+'px)}"
    >
      <!-- 列表项内容 -->
      <view class="content">
        <!-- 列表项内容 -->
        <!-- ... -->
		测试内容测试内容测试内容测试内容测试内容测试内容测试内容测试内容测试内容
      </view>
      <!-- 删除选项 -->
    <!--  <view v-if="showDeleteOption" class="delete-option" :style="deleteOptionStyle" @click="deleteItem">
        删除
      </view> -->
	  <view  class="delete-option" @click="deleteItem">
	    删除
	  </view>
    </view>
  </view>
</template>

<script>
export default {
  data() {
    return {
      startX: 0, // 记录触摸起始位置
      moveX: 0, // 记录横向位移
      showDeleteOption: false,
      isAnimating: false,
	  delBtnWidth:100,
	  distance:0
    };
  },

  methods: {
	  
    onTouchStart(event) {
      // 记录触摸起始位置
      this.startX = event.touches[0].clientX;
    },
    onTouchMove(event) {
      // 计算横向位移
      this.moveX = event.touches[0].clientX - this.startX;
		console.log("movex",this.moveX)
	  if(this.moveX>=0){
		  this.moveX=0
	  }else{
		  if(this.moveX<-this.delBtnWidth/2){
		  	this.moveX=-this.delBtnWidth	  
		  }
	  }

    },
    onTouchEnd() {
		if(this.moveX<0){
				if(Math.abs(this.moveX)<this.delBtnWidth/2){
					this.moveX=0
				}else{
					this.moveX=-this.delBtnWidth
				}
		}
		
      
    },
  
  }
}
</script>

<style>
.swipe-container {
  position: relative;
  height: 100%;
/*  overflow: hidden;
 */  touch-action: pan-y; /* 允许垂直方向滚动 */
 transition: all 0.5s;
}

.delete-option {
  position: absolute;
  top: 0;
  right: -100px;
  height: 100%;
  width: 100px;
  background-color: red;
  color: white;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 14px;
  transition: opacity 0.3s;
}

.content {
  height: 100%;
  padding-right: 100px;  /* 设置内容右侧距离为删除选项的宽度 */
}
</style>

这里我们只是对单个的选项做了左滑删除操作,那对于列表而言,我们则需要对数据进行一点改造:

 

   <view class="message_list">
                    <view class="item" v-for="(item, index) in list" :key="index">
                        <view class="time_name">时间段({{index+1}})</view>
                        <view class="time_item" 
                                @touchstart="drawStart($event,item)" 
                                @touchmove="drawMove($event,item)" 
                                @touchend="drawEnd($event,item)" 
                                :style="{transform:'translateX('+item.moveX+'px)'}"
                              
                        >
                            <view class="item_cont">                        
                                <view class="start_item" >
                                    <view class="start_item_title">开始时间</view>
                                    <view @click="triggerTime(item)">{{item.startTime||"--"}}</view>
                                </view>
                                <view class="end_item" >
                                    <view class="end_item_title">结束时间</view>
                                    <view @click="triggerTime(item)">{{item.endTime||"--"}}</view>
                                    </view>
                            </view>
                            <view class="del_item" @click="triggerDelItem(item,index)">删除</view>
                        </view>
                    </view>
            </view>

 然后再看看我们的js代码:

export default {
    data(){
        return {
            list:[
                {id:"001",timebName:"时间段",startTime:"10:00",endTime:"14:00",moveX:0},
                {id:"002",timebName:"时间段",startTime:"9:00",endTime:"15:00",moveX:0},
                {id:"003",timebName:"时间段",startTime:"11:00",endTime:"18:00",moveX:0},
            ],
			curLang: Vue.config.lang,
            curTimeItem:{
                startTime:"",
                endTime:"",
            },
            hours: Array.from({ length: 24 }, (_, i) => i),
            minutes: Array.from({ length: 60 }, (_, i) => i),
            timeValue: [8, 30], 
            isShowPicker:false,
            delBtnWidth: 60,
            startX:0,
            moveX:0,
            visible:false
        }                
    },

methods:{
        i18nCast,

        drawStart(e){
            this.startX=e.touches[0].clientX;
            console.log("this.startx",this.startX)
        },
        drawMove(e,item){
           
            item.moveX=e.touches[0].clientX-this.startX;
            if(item.moveX>=0){
                item.moveX=0
            }else{
                if(item.moveX<=-this.delBtnWidth/2){
                    item.moveX=-this.delBtnWidth
                }
            }
        },
        drawEnd(e,item){
          
            if(item.moveX<0){
                if(Math.abs(item.moveX)<this.delBtnWidth/2){
                    item.moveX=0
                }else{
                    item.moveX=-this.delBtnWidth
                }
            }
            console.log("t抬起:",item.moveX)
        },
      
    }

最后是我们的css代码:

 .time_item{
                display: flex;
                padding: 3.2vw 0 3.2vw 5.3333vw;;
                box-sizing: border-box;
                position: relative;
                background: #fff;
                transition: all 0.2s ease-in;
                .item_cont{
                    padding-right: 32vw;
                    height: 100%;
                    // width: calc(100% - 60px);
                    display: flex;
                    width: 100%;
                    .start_item,.end_item{
                        width: 50%;
                    }
                    .start_item_title,.end_item_title{
                        font-size: 3.7333vw;
                        font-style: normal;
                        font-weight: 400;
                        line-height: 5.3333vw;
                    }
                }
                .del_item{
                    width: 16vw;
                    height: 100%;
                    background-color: #FF5F3D;
                    color: white;
                    position: absolute;
                    top: 0;
                    right:-16vw;
                    font-size: 3.7333vw;
                    font-weight: 400;
                    line-height: 5.3333vw;
                    display: flex;
                    justify-content: center;
                    align-items: center;
                }
            }   

 

当然我们也可以采用定位的方式实现这个效果:

<template>
	<view class="SwipeActionBox">
		<view v-for="item in csListArrl" :key="item.id" class="order-item" @touchstart="drawStart($event,item)"
			@touchmove="drawMove($event,item)" @touchend="drawEnd($event,item)" :style="{right:`${item.right}px`}">
			<view class="content">{{item.name}}</view>
			<view class="remove" @click="delData(item)">注 销</view>
		</view>

	</view>
</template>

<script>
	
	export default {
	
		data() {
			return {
				csListArrl: [{
						id: "001",
						name: "测绘一测绘一测绘一测绘一",
						right: 0
					},
					{
						id: "002",
						name: "测绘二测绘二测绘二测绘二测",
						right: 0
					},
					{
						id: "003",
						name: "测绘三测绘三测绘三测绘三测",
						right: 0
					},
				],
				//左滑默认宽度
				delBtnWidth: 160

			}
		},
		onLoad() {

		},
		methods: {
			//开始触摸滑动
			drawStart(e, item) {
				console.log("开始触发");
				var touch = e.touches[0];
				this.startX = touch.clientX;
				
			},
			//触摸滑动
			drawMove(e, item) {
				console.log("滑动");
				var touch = e.touches[0];
				
				var disX = touch.clientX-this.startX ;
				console.log("disx:", disX)
				  if(disX<-this.delBtnWidth/2){
					disX=-this.delBtnWidth	 
				  }
				  item.right = disX
				}
				
			},
			//触摸滑动结束
			drawEnd(e, item) {
				console.log("滑动结束");
				console.log("滑动结束--", e.currentTarget);
				console.log("item:", item)
			
				
				if(this.startX<0){
					if(Math.abs(this.startX)<this.delBtnWidth/2){
						this.startX=0
					}else{
						this.startX=-this.delBtnWidth
					}
				}
		
			},
			//删除方法
			delData(item) {
				console.log("删除")
				uni.showModal({
					title: '提示',
					content: "确认注销该人员?",
					success: function(res) {
						if (res.confirm) {
							console.log('用户点击确定');
						} else if (res.cancel) {
							console.log('用户点击取消');
						}
					}
				});
			}

		}
	}
</script>

<style scoped>
	.order-item {
		width: 100%;
		display: flex;
		position: relative;
		padding: 10px 0;
		transition: all 0.2s ease-out;
	}

	.remove {
		width: 80px;
		height: 100%;
		background-color: red;
		color: white;
		position: absolute;
		top: 0;
		right: -165px;
		display: flex;
		justify-content: center;
		align-items: center;
		font-size: 16px;
	}
</style>

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值