微信小程序 做一个通过拉拽动作来切换照片的效果

先看最终的效果展示:

在他人的小程序上发现了类似效果,但似乎用的是uniapp上的插件,所以我使用小程序原生的方式复刻一个。复刻过程中可以了解到关于拖拽的实现、判断拖拽方向、ios弹簧效果禁用、拖拽优化等。

页面的布局文件(wxml格式):

<!--pages/observation-desk/observation-desk.wxml-->
<view class="blur" style="background-image: url({{pictureList[currentIndex].img}});"></view>
<view class="bg">
    <view class="picture-box"  catch:touchmove="touchMoveHandler" catch:touchend="touchEndHandler"
      style="top:calc(50% + {{y + 'px'}}) ;"
    >
      <image mode="aspectFill" hidden="{{currentIndex + 2 >= pictureList.length}}" src="{{pictureList[currentIndex + 2].img}}" />
      <image mode="aspectFill" hidden="{{currentIndex + 1 >= pictureList.length}}" src="{{pictureList[currentIndex + 1].img}}" />
      <view style="position: relative;">
        <image class="center-picture" mode="aspectFill" src="{{pictureList[currentIndex].img}}" />
        <view class="picture-name">
          {{pictureList[currentIndex].name}}
        </view>
      </view>
      <image mode="aspectFill" hidden="{{pictureList[currentIndex - 1] == null}}" src="{{pictureList[currentIndex - 1].img}}" />
      <image mode="aspectFill" hidden="{{pictureList[currentIndex - 2] == null}}" src="{{pictureList[currentIndex - 2].img}}" />
    </view>
</view>

页面的样式文件(wxss格式):

.bg {
  width: 100vw; 
  height: 100vh; 
  overflow: hidden; 
  position: relative;
}
/** 模糊的背景 */
.blur {
  position: absolute;
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
  width: 100vw;
  height: 100vh;
  top: 0;
  left: 0;
  filter: blur(3px);
}
/** 放所有图片的大盒子 */
.picture-box {
  transform: translate(-50%, -50%);
  position: absolute;
  left: 50%;
  display: flex;
  align-items: center;
  flex-direction: column;
}
/** 当前选中图片的文字描述 */
.picture-name {
  z-index: 1001; 
  position: absolute;
  bottom: 10px; 
  left: 50%;
  transform:translateX(-50%);
  background-color: rgba(0,0,0,0.3); 
  color: white;
  text-align: center;
  width: calc(100% - 10px);
  padding: 15px;
}
.picture-box image {
  height: 150px;
  border: 5px solid white;
  border-radius: 8px;
  position: relative;
}
.picture-box image::after {
  content: "";
  background-color: rgba(255,255,255,0.5);
  width: 100%;
  height: 100%;
  top: 0;
  left: 0;
  position: absolute;
}
/** 当前选中的图片的样式 */
.picture-box .center-picture {
  width: 300px;
  z-index: 1000;
}
.picture-box .center-picture::after {
  background-color: transparent;
}
.picture-box>image:nth-child(1) {
  width: 240px;
  margin-bottom: -70px;
}
.picture-box>image:nth-child(2) {
  width: 260px;
  margin-bottom: -70px;
}
.picture-box>image:nth-child(4) {
  width: 260px;
  margin-top: -70px;
  z-index: 999;
}
.picture-box>image:nth-child(5) {
  width: 240px;
  margin-top: -70px;
  z-index: 998;
}

页面的JS文件:

//记录上一次拖拽时的基准位置
let touchY = null;
//拖拽方向:true表示上翻,false表示下翻
let upward = null;
const app = getApp()
Page({

  data: {
    //通用图片路径的前缀
    imgUrl: app.globalData.imgUrl,
    //拖拽时元素的y轴方向的位置
    y:0,
    //图片列表
    pictureList: [
      {
        //图片的url路径,用你自己的图片路径
        img: app.globalData.imgUrl + "/" + "observation-desk1.png",
        //图片的名字,当图片选中时会显示出来
        name: "1号看海"
      },{
        img: app.globalData.imgUrl + "/" + "observation-desk2.png",
        name: "2号嬉海"
      },{
        img: app.globalData.imgUrl + "/" + "observation-desk3.png",
        name: "3号爱海"
      }, {
        img: app.globalData.imgUrl + "/" + "observation-desk5.jpg",
        name: "5号绘海"
      }, {
        img: app.globalData.imgUrl + "/" + "observation-desk8.jpg",
        name: "8号平台"
      }
      , {
        img: app.globalData.imgUrl + "/" + "observation-desk10.jpg",
        name: "10号平台"
      }, {
        img: app.globalData.imgUrl + "/" + "observation-desk12.png",
        name: "12号平台"
      }
    ],
    //当前选中图片的下标
    currentIndex: 0,
  },
  //拖拽移动事件处理函数
  touchMoveHandler(e) {
    const {screenY} = e.changedTouches[0]
    const offset =  screenY - touchY
    if(touchY == null) {
      touchY = screenY; 
      return
    }
    upward = this.data.y - offset > 0
    this.setData({y:offset})
  },
  //拖拽结束事件处理函数
  touchEndHandler() {
    let {currentIndex,pictureList} = this.data
    //下翻的情况
    if(upward===false) {
      if(currentIndex < pictureList.length - 1) {
        currentIndex = currentIndex + 1
      }
    }
    //上翻的情况
    else if(upward === true){
      if(currentIndex > 0) {
        currentIndex = currentIndex - 1
      }
    }
    this.setData({ currentIndex, y:0 })
    touchY = null
    upward = null
  },
})

禁用ios弹簧效果(在页面对应的JSON文件中将disableScroll设置为true)

{
  "usingComponents": {},
  "disableScroll": true
}

最后:监听touchmove事件时利用catch方式来代替bind可以阻止事件冒泡提高一些性能。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值