微信小程序中使用map组件,ios手机中点击地图上的view,会触发底下的markertap,只要底下如果有marker点的话。

这就造成了用户体验不是很好。

然后无意间我发现点击能滑动的scroll-view反而不会触发底下的markertap,就等于是一个不穿透的容器。我就在想是不是view也可以换成scroll-view,然后防止穿透点击,答案是:可以。

但是体验还是不太好,因为scroll-view会滑动,所以按钮里面的内容也会滑动,不是最佳的解决方法。于是,我就想到可以用透明的可滑动的scroll-view放在上层作为隐形按钮,下层放普通的按钮样式,这回真正的解决了ios的bug。

一、地图上覆盖的子组件代码

wxml代码

<view class="box">
    <swiper circular>
        <swiper-item wx:for="{{switchArr}}">
            <view class="container" catchtap="switchItem" data-index="{{index}}" data-name="{{item.name}}">
                <view class="card">
                    <view class="content">
                        <view class="icon">
                            <image src="{{item.imageUrl}}" mode="aspectFill"></image>
                        </view>
                        <view class="bt">
                            <view class="title">{{item.name}}</view>
                        </view>
                    </view>
                </view>
            </view>
            <scroll-view class="scroll-view" scroll-y="true" catchtap="switchItem" data-index="{{index}}" data-name="{{item.name}}">
                <view style="height:100vh;"></view>
            </scroll-view>

        </swiper-item>
    </swiper>
    <view class="cancelSwitch" style="top:{{statusHeight+3}}px" catchtap="cancelSwitch">
        <text>退出页面</text>
    </view>

</view>

less代码

/* pages/subPack/otherAnimation/index.wxss */

page {
    box-sizing: border-box;
    font-family: sans-serif;
}

.cancelSwitch{
    position: absolute;
    left: 40rpx;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 210rpx;
    height: 60rpx;
    line-height: 60rpx;
    border-radius: 30rpx;
    color:#fff;
    background-color: #d94251;
    image{
        width: 35rpx;
        height: 30rpx;
        margin-left: 3rpx;
    }
}
.box{
    position: fixed;
    z-index: 10000;
    min-height: 100vh;
    background-color: #1a1c22;
    width: 100%;

    swiper {
        width: 100%;
        height: 100vh;

        swiper-item {
            width: 100%;
            height: 100vh;
            display: flex;
            flex-direction: column;
            justify-content: center;
            align-items: center;

            .container {
                position: relative;
                display: flex;
                justify-content: space-around;
                align-items: center;
                width: 710rpx;

                .card {
                    width: 100%;
                    margin: 20px;
                    padding: 40px 30px;
                    border-radius: 40px;
                    background-color: #20252a;
                    border: 4rpx solid #ffefa1;
                    box-shadow: -0px -0px 10px #ffefa1;

                    .imgBx {
                        position: relative;
                        text-align: center;
                    }
                    .content {
                        text-align: center;
                        display: flex;
                        flex-wrap: wrap;
                        justify-content: center;
                        align-items: center;

                        .icon {
                            padding: 20px;
                            margin-top: 15px;
                            height: 100%;
                            width: 120%;
                            border-radius: 40px;
                            color: #32a3b1;
                            font-size: 16px;
                            overflow: hidden;
                            text-decoration: none;
                            background: #20252a;
                            box-shadow: 13px 13px 26px #181c20, -13px -13px 26px #282e35;

                            image {
                                width: 100%;
                                border-radius: 10px;
                            }
                        }

                        .bt {
                            display: inline-block;
                            padding: 10px 20px;
                            margin-top: 45px;
                            border-radius: 40px;
                            color: #ffefa1;
                            font-size: 16px;
                            text-decoration: none;
                            background: #20252a;
                            box-shadow: 20px 20px 41px #161a1d,
                                -20px -20px 41px #2a3037;

                            &:hover {
                                background: #20252a;
                                box-shadow: inset 20px 20px 41px #161a1d,
                                    inset -20px -20px 41px #2a3037;
                            }
                        }
                    }
                    &:hover {
                        background: #20252a;
                        box-shadow: inset 20px 20px 41px #161a1d,
                            inset -20px -20px 41px #2a3037;
                    }

                }
            }
            .scroll-view{
                width: 750rpx;
                background-color: #fff;
                position:absolute;
                height: 1000rpx;
                opacity: 0;
            }
        }
    }
}

js代码

const app = getApp();
Component({
  data: {
    statusHeight: app.globalData.statusHeight,
    buttonCanUse:true
  },
  properties: {
      switchArr:{
          type:Array,
          value:[]
      }
  },
  methods: {
    switchItem(e) {
        if(!this.data.buttonCanUse){
            return
        }
        this.setData({
            buttonCanUse:false
        })
        this.triggerEvent('switchItem', {
            index:e.currentTarget.dataset.index,
            name:e.currentTarget.dataset.name
        })
        this.setData({
            buttonCanUse:true
        })
    },
    cancelSwitch() {
        this.triggerEvent('cancelSwitch')
    },
  }
})

二、小程序效果

map效果:map上面有很多点位 这些点位都是可以点击进去其他页面的点

 切换旅游路线的子组件:是覆盖在map之上的一个容器 z-index:10000

点击就可以切换到路线

三、问题所在

点击这个全景路线的时候 如果点击的位置下方有一个marker点,则他触发两个点击事件,即同时切换路线 同时进入marker点链接的路径

四、解决思路

利用可滑动的scroll-view不会穿透的特性,在子组件上面插入隐形scroll-view,设置点击事件,(用户以为点击的是子组件,实际上点击的是scroll-view,这是一个通用的思路),然后将scroll-view大小覆盖子组件

五、代码分析

核心代码:

<view class="container" catchtap="switchItem" data-index="{{index}}" data-name="{{item.name}}">
  <view class="card">
    <view class="content">
       <view class="icon">
         <image src="{{item.imageUrl}}" mode="aspectFill"></image>
       </view>
       view class="bt">
         <view class="title">{{item.name}}</view>
       </view>
    </view>
   </view>
</view> 
<scroll-view class="scroll-view" scroll-y="true" catchtap="switchItem" data-index="{{index}}" data-name="{{item.name}}">
       <view style="height:100vh;"></view>
</scroll-view>
.scroll-view{
   width: 750rpx;
   background-color: #fff;
   position:absolute;
   height: 1000rpx;
   opacity: 0;
}

 <view class="container" catchtap="switchItem" data-index="{{index}}" data-name="{{item.name}}">是子组件里面每个路线的容器,点击可以切换路线

我在同级写了一个scroll-view 设置宽度750rpx撑满屏幕 然后高度1000rpx盖住整个路线容器 并且将透明度改为零(即opacity:0)

然后在wxml中 设置scroll-y=“true” 在scroll-view里面放一个高度100vh的盒子,让整个scroll-view可滑动,因为scroll-y,所以是上下滑动。

这里为什么不设置scroll-x=“true” 然后在横向上滑动 是因为 我本身用了swiper组件 左右滑动切换,用scroll-x的话,两个滑动事件会冲突,会影响原有的滑动感受。然后在scroll-view上

然后在scroll-view上添加原本写在container上面的点击的点击事件,让用户点的实际上是scroll-view

这样就可以保证ios系统手机点击不会穿透了。

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐