Featured image of post 微信小程序实现全屏可拖动滑块组件

微信小程序实现全屏可拖动滑块组件

使用小程序`moveable-area`实现可视区域内自由拖动元素,并适配不同机型

需求是商城内的购物车图标遮挡了商品,需要在当前可视区域自由拖动购物车组件,不影响用户点击商品。

效果预览

示例图

录制的gif有一定的掉帧,实际上真机拖动的时候是流畅的。

解决思路

查阅文档,微信小程序提供了movable-areamovable-view标签。目前项目里的当前页面是比较简单的,所以可以用movable-area包裹整个可视页面,movable-view包裹你要移动的元素。关键在于项目中使用了自定义导航栏mp-navigation-bar,如何获取页面剩余的内容可用高度。

代码实现

index.wxml

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<mp-navigation-bar background="#3883ff"  title="商城" back="{{false}}"></mp-navigation-bar>
<movable-area>
    <!-- 内容区域 -->
    <view style="height: {{contentHeight}}px">
        <view class="goods-container">
            <view class="goods-box" wx:for="{{goodsList}}" wx:key="id" bindtap="toDetailsTap" data-id="{{item.id}}">
                <view class="img-box">
                    <image src="{{item.pic}}" class="image" mode="aspectFill" lazy-load="true" />
                </view>
                <view class="goods-title van-multi-ellipsis--l2">{{item.name}}</view>
                <view class="price-parent">
                    <view class="goods-price">¥ {{item.price}}</view>
                 </view>
        </view>
    </view>
    <!-- 内容区域 end -->
    <!-- 需要拖动的组件 -->
    <movable-view x="{{x}}" y="{{y}}" direction="all">
         <!-- vant-weapp框架中的一个购物车组件,可以替换为其它元素/组件 start -->
        <van-goods-action-icon
        icon-class="goods-icon"
        icon="cart-o"
        text="购物车"
        bind:click="goShopCar"
        info="{{ shopNum ? shopNum : '' }}" />
         <!-- vant-weapp框架中的一个购物车组件,可以替换为其它元素/组件 end -->
    </movable-view>
    <!-- 需要拖动的组件 end -->
</movable-area>

index.wxss

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
movable-view {
    display: flex;
    align-items: center;
    justify-content: center;
    height: 100rpx;
    width: 100rpx;
    background-color: #fff;
    border-radius: 20rpx;
    box-shadow: 0rpx 20rpx 50rpx -12rpx rgba(0,0,0,0.25) ;
}

movable-area {
    height: 100%;
    width: 100%;
}

index.js

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
Page({
    data: {
        // 设置拖动组件的初始位置
        x:340,
        y: 0,
        
        goodsList: [
            {id: 15, pic: "https://images.pexels.com/photos/2113994/pexels-photo-2113994.jpeg", name: "手表", price: 699},
            {id: 17, pic: "https://images.pexels.com/photos/221185/pexels-photo-221185.jpeg", name: "平板", price: 1900},
            {id: 20, pic: "https://images.pexels.com/photos/1203803/pexels-photo-1203803.jpeg", name: "相机", price: 8150},
            {id: 21, pic: "https://images.pexels.com/photos/270640/pexels-photo-270640.jpeg", name: "键盘", price: 2168}
        ],
    },
    onLoad(){
        this.getCartHeight()
    },
    getCartHeight(){
        // 页面初始化时 设置购物车初始位置为 停留在页面高度的2/3的位置 也可以设置成其他值
        const height = Math.floor((wx.getSystemInfoSync().windowHeight)*2/3);
        this.setData({
            y: height
        })
        
        // 获取 自定义导航栏 时 页面高度
        let customWindowHeight = wx.getSystemInfoSync().windowHeight
        // console.log('customWindowHeight', customWindowHeight)
        let navH = wx.getStorageSync('navigationBarHeight') + wx.getStorageSync('statusBarHeight')
        // console.log('navH', navH)

        let contentHeight = customWindowHeight - navH*2

        this.setData({
            contentHeight
        })
    },
})

app.js

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
App({
    globalData: {},
    onLaunch() {
        // 自定义导航
        this.getNavHeight()
    },
    getNavHeight(){
      const { statusBarHeight, platform } = wx.getSystemInfoSync()
      const { top, height } = wx.getMenuButtonBoundingClientRect()

      // 状态栏高度 (包含wifi信号、电量、时间的那一行顶部状态栏)
      wx.setStorageSync('statusBarHeight', statusBarHeight)

      // 整个导航栏高度 = 胶囊按钮高度 + 状态栏到胶囊按钮间距 * 2                                                           // Android导航栏高度 = 32px + 8px * 2 = 48px                                                                   // iOS导航栏高度 = 32px + 6px * 2 = 44px
        
      // 判断胶囊按钮信息是否成功获取
      if (top && top !== 0 && height && height !== 0) {
          const navigationBarHeight = (top - statusBarHeight) * 2 + height
          // 导航栏高度
          wx.setStorageSync('navigationBarHeight', navigationBarHeight)
      } else {
          wx.setStorageSync(
            'navigationBarHeight',
            platform === 'android' ? 48 : 40
          )
      }
    },
})

参考资料

moveable-area 微信小程序文档

小程序自定义导航栏适配(完美版)

Built with Hugo
Theme Stack designed by Jimmy