用户引导组件开发(2)遮罩层与突出元素
发布于 5 年前 作者 tsu 568 次浏览 来自 分享

我们一步步来吧,包括我踩过的坑我也会还原一遍,让大家一起长长见识

遮罩层

遮罩层是最没技术难度的,写个css就可以了。

.mask {
  z-index: 1110;
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background-color: rgba(0, 0, 0, 0.6);
}

按然后再加个bindtap,控制点击之后消失,感觉直接就可以用了呢。这里有铅笔画不出蜡笔的味道提供的一个代码片段:

https://developers.weixin.qq.com/s/cvqEYzmM7Ffn

突出元素

这个才是难点所在。

1、确定元素位置。

我们首先要找出这个元素的轮廓,这个我是通过boundingClientRect实现的。

  const query = wx.createSelectorQuery();
  query.select("#gameInfo").boundingClientRect(); //gameInfo就是我们所需要突出展示的元素ID,后续可以用config传入
  query.exec(function(res) {
      console.log(res);
  }

输出如下:

可以看到这个办法很好地取到了所要突出的元素的位置。

2、画出镂空遮罩。

这里我参考了这篇文章:https://www.cnblogs.com/mxdmg/p/10427605.html

文章中的方法一就不说了,又麻烦又浪费空间。

方法二我试了下,展示效果确实不错,但是也如文中所说的,点遮罩的时候会点到底下的元素,肯定会影响效果。

方法三没试,因为感觉有跟二一样的缺点。

方法四也没试,因为一看就知道很麻烦。

方法五把我导向了mask-image,想说能否用这个css属性在遮罩层上挖个洞出来。关于这方面的应用我觉得这篇文章写得挺好的:https://www.zhangxinxu.com/wordpress/2017/11/css-css3-mask-masks/。然而一一试过后,发现这个属性在小程序中好像用不了(也有可能是我哪里出错,反正就是没法生效)。

呵呵。。。以上几种方式折腾了一个晚上。

后来想想,干脆抛开幻想抛开依赖,自力更生。

不搜了,自己土办法画一个。

我用四个view作为遮罩,框出了需要突出的元素。

<view wx:if="{{showGuide}}" class="mask" bindtap="getHidden">
  <view class="mask_block" style="width:100%;top:0px;left:0px;height:{{showArea.top}}px"></view> //上
  <view class="mask_block" style="width:100%;top:{{showArea.bottom}}px;left:0px;height:100%"></view>  //下
  <view class="mask_block" style="height:{{showArea.height}}px;top:{{showArea.top}}px;left:0px;width:{{showArea.left}}px"></view> //左
  <view class="mask_block" style="height:{{showArea.height}}px;top:{{showArea.top}}px;left:{{showArea.right}}px;width:100%"></view> //右
</view>


上面的showArea就是第一步中取到的元素位置。

这样一来,遮罩中的元素突出就解决了。

3、还有一个坑

本来以为这一步搞定的时候,发现这个镂空的位置竟然还会漂移!在开发工具和真机中的位置不一样,就算同在真机中,这次展示和下次展示的位置也有可能不一样!

这TM是薛定谔的镂空框!

这就是当时的神奇漂移。

经验告诉我,会出现这种不确定性的——

十之八九都和元素的加载是否完成有关系

请好好记住这句话,可以节省你至少一天的调试时间。

是的,坑就在于步骤一的

 query.select("#gameInfo").boundingClientRect();

什么时候取的很关键。在小程序布局完成前,你可能会取到一个偏差值,导致了后面的踩坑。

我之前是在组件生命周期(还不清楚组件生命周期的看这里)中attached环节执行,不行。发现手册中还有一个ready,感觉和page中的onReady是一个东西,然而还是不行。。。

看来还是必须等页面的onReady触发之后才能取到完全正确的值。

所以我必须在主页面的onReady事件发生后再来做这个事情。

那么如何确定onReady呢?相当于我必须能够在onReady事件中去调用用户引导组件的初始化函数。。。想来想去,他们两者之间能够互动的也只有setData了。

也就是数据监听器,不懂的点这里

幸好按计划本来也是要传入配置数组的。于是在pages中的onReady传入配置数组,然后在组件中对配置数组进行监听。

 observers: {
    'config': function(config) {
      if (config) {
        this.initMask(config);
      }
    }
  }

如此一来,遮罩层跟元素的突出展示就算完成了。

当然,这样的遮罩层还是有些不足的,例如只支持方形镂空,如果是圆形元素看着就不那么美观。。。好在我目前没有这方面需求,以后有遇到再说吧。

回到顶部