官方服务微信:dat818 购买与出租对接

弹框实现效果及对话框跟随手势下拉的实现方法解析

4万

主题

2

回帖

12万

积分

管理员

积分
123961
发表于 昨天 02:42 | 显示全部楼层 |阅读模式
<p[]一、先看一下弹框实现效果1.抖音实现效果</p>   
2.我的实现效果

    二、对话框跟随手势下拉实现

    通过观察展示的成果截图,能够察觉到浮动框会随手势朝下方向位移并达成同步位移,要达成此功能,必须测量出手势朝下移动的具体数值,接着将这个数值赋予浮动框,以此决定其向下收起的幅度。

    即:弹窗向下移动的距离 = 手势向下移动的距离

    1.手势向下移动距离的计算公式

    手势下移的长度等于手势移动末点的Y值减去手势移动起点的Y值

    在中提供了可以兼容多端的监听页面上元素的触摸方法:

    1.手指开始触摸元素

    .:.(: ):

    2.手指触摸元素后移动。

    .:.(: ):

    3.手指结束触摸元素

    .:.(: ):

     字段定义如下:

    字段类型必填默认值说明

    array

    触摸事件,当前停留在屏幕中的触摸点信息的数组

    array

    触摸事件,当前变化的触摸点信息的数组

    2.获取手势向下移动的距离

    接下来会借助选项api来完成对应任务,这样做也是为了能够同时适配vue2和vue3的不同版本。

<p style='margin-bottom:15px;color:#555555;font-size:15px;line-height:200%;text-indent:2em;'>    <pre><code class="hljs language-js" lang="js"><template>
<span class="xml"><span class="hljs-tag"><<span class="hljs-name">uni-popup</span> <span class="hljs-attr">ref</span>=<span class="hljs-string">"popup"</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"bottom"</span>></span>
    <span class="hljs-tag"><<span class="hljs-name">view</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"content"</span>
        @<span class="hljs-attr">touchstart</span>=<span class="hljs-string">"touchstart"</span>
        @<span class="hljs-attr">touchmove</span>=<span class="hljs-string">"touchmove"</span>
    ></span>
      ...
    <span class="hljs-tag"></<span class="hljs-name">view</span>></span>
<span class="hljs-tag"></<span class="hljs-name">uni-popup</span>></span></span>
</template>
<span class="xml"><span class="hljs-tag"><<span class="hljs-name">script</span>></span><span class="javascript">
  <span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> {
    <span class="hljs-title function_">data</span>(<span class="hljs-params"></span>) {
      <span class="hljs-keyword">return</span> {
        <span class="hljs-comment">// 手势向下移动距离</span>
        <span class="hljs-attr">moveDistance</span>: <span class="hljs-number">0</span>
      }
    },
    <span class="hljs-attr">methods</span>: {
      <span class="hljs-comment">// 开始触摸元素</span>
      <span class="hljs-title function_">touchstart</span>(<span class="hljs-params">e</span>) {
        <span class="hljs-variable language_">this</span>.<span class="hljs-property">startY</span> = e.<span class="hljs-property">changedTouches</span>[<span class="hljs-number">0</span>].<span class="hljs-property">clientY</span>;
        <span class="hljs-variable language_">this</span>.<span class="hljs-property">startIme</span> = <span class="hljs-title class_">Date</span>.<span class="hljs-title function_">now</span>()
        <span class="hljs-variable language_">this</span>.<span class="hljs-property">toumoveTime</span> = <span class="hljs-title class_">Date</span>.<span class="hljs-title function_">now</span>()
      },
      <span class="hljs-comment">// 触摸元素后移动</span>
      <span class="hljs-title function_">touchmove</span>(<span class="hljs-params">e</span>) {
        <span class="hljs-keyword">const</span> clientY = e.<span class="hljs-property">changedTouches</span>[<span class="hljs-number">0</span>].<span class="hljs-property">clientY</span>;
        <span class="hljs-comment">// 忽略上划</span>
        <span class="hljs-keyword">if</span> (clientY < <span class="hljs-variable language_">this</span>.<span class="hljs-property">startY</span>) {
          <span class="hljs-keyword">return</span>
        }
        <span class="hljs-comment">// 下滑,计算手势移动距离</span>
        <span class="hljs-variable language_">this</span>.<span class="hljs-property">moveDistance</span> = clientY - <span class="hljs-variable language_">this</span>.<span class="hljs-property">startY</span>
      },
    }
  }
</span><span class="hljs-tag"></<span class="hljs-name">script</span>></span></span>
</code></pre></p>
   


    通过e..可获取当前屏幕触摸的Y坐标。

    3.弹框向下隐藏同步手指向下触摸移动距离

    利用css属性调整弹窗的向下偏移量,能够实现弹窗的隐藏功能。

    : `(${this.}px)`

<p style='margin-bottom:15px;color:#555555;font-size:15px;line-height:200%;text-indent:2em;'>    <pre><code class="hljs language-js" lang="js"><script>
  <span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> {
    <span class="hljs-title function_">data</span>(<span class="hljs-params"></span>) {
      <span class="hljs-keyword">return</span> {
        <span class="hljs-comment">// 手势向下移动距离</span>
        <span class="hljs-attr">moveDistance</span>: <span class="hljs-number">0</span>
      }
    },
    <span class="hljs-attr">computed</span>: {
      <span class="hljs-title function_">contentStyle</span>(<span class="hljs-params"></span>) {
        <span class="hljs-keyword">return</span> {
          <span class="hljs-attr">transform</span>: <span class="hljs-string">`translateY(<span class="hljs-subst">${<span class="hljs-variable language_">this</span>.moveDistance}</span>px)`</span>,
        }
      }
    },
  }
</script>
<span class="xml"><span class="hljs-tag"><<span class="hljs-name">template</span>></span>
<span class="hljs-tag"><<span class="hljs-name">uni-popup</span> <span class="hljs-attr">ref</span>=<span class="hljs-string">"popup"</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"bottom"</span>></span>
    <span class="hljs-tag"><<span class="hljs-name">view</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"content"</span>
        <span class="hljs-attr">...</span>
       <span class="hljs-attr">:style</span>=<span class="hljs-string">"contentStyle"</span>
    ></span>
      ...
    <span class="hljs-tag"></<span class="hljs-name">view</span>></span>
<span class="hljs-tag"></<span class="hljs-name">uni-popup</span>></span>
<span class="hljs-tag"></<span class="hljs-name">template</span>></span></span>
</code></pre></p>
    三、关闭弹窗时机

    弹窗的拖拽功能现已实现,接下来要设定其收起时机,在符合标准时执行this.$refs.popup.close()指令来关闭弹窗。经过反复验证,发现抖音的评论弹窗存在两种触发收起的状况,一是当界面底部达到特定距离,二是当用户迅速完成对元素的起始、移动及结束触碰这三个连续动作时,弹窗便会自动关闭。

    关闭弹窗后,我们能够对元素附加处理,在触摸动作完成之际开展必要运算。

    1.计算距离底部距离

    距离底部距离 = 窗口高度 - 当前手指触摸结束的Y坐标

<p style='margin-bottom:15px;color:#555555;font-size:15px;line-height:200%;text-indent:2em;'>    <pre><code class="hljs language-js" lang="js"><span class="hljs-title function_">touchend</span>(<span class="hljs-params">e</span>) {
    <span class="hljs-comment">// 触摸结束Y坐标</span>
    <span class="hljs-keyword">const</span> clientY = e.<span class="hljs-property">changedTouches</span>[<span class="hljs-number">0</span>].<span class="hljs-property">clientY</span>;
    <span class="hljs-comment">// 获取窗口高度</span>
    <span class="hljs-keyword">const</span> { windowHeight } = uni.<span class="hljs-title function_">getSystemInfoSync</span>();
    <span class="hljs-comment">// 距离底部距离</span>
    <span class="hljs-keyword">const</span>距离等于窗口高度减去当前指针位置
}
</code></pre></p>
    2.计算手势完成时间

<p style='margin-bottom:15px;color:#555555;font-size:15px;line-height:200%;text-indent:2em;'>    <pre><code class="hljs language-js" lang="js"><span class="hljs-title function_">touchstart</span>(<span class="hljs-params">e</span>) {
    <span class="hljs-variable language_">this</span>.<span class="hljs-property">startIme</span> = <span class="hljs-title class_">Date</span>.<span class="hljs-title function_">now</span>()
},
<span class="hljs-title function_">touchend</span>(<span class="hljs-params">e</span>) {
    <span class="hljs-comment">// 手势完成时间(毫秒)</span>
    <span class="hljs-keyword">const</span> toumoveTime = <span class="hljs-title class_">Date</span>.<span class="hljs-title function_">now</span>() - <span class="hljs-variable language_">this</span>.<span class="hljs-property">startIme</span>
},
</code></pre></p>
    3.根据计算值,完成弹窗关闭逻辑

<p style='margin-bottom:15px;color:#555555;font-size:15px;line-height:200%;text-indent:2em;'>    <pre><code class="hljs language-js" lang="js"><span class="hljs-title function_">touchend</span>(<span class="hljs-params">e</span>) {
    <span class="hljs-comment">// 触摸结束Y坐标</span>
    <span class="hljs-keyword">const</span> clientY = e.<span class="hljs-property">changedTouches</span>[<span class="hljs-number">0</span>].<span class="hljs-property">clientY</span>;
    <span class="hljs-comment">// 获取窗口高度</span>
    <span class="hljs-keyword">const</span> { windowHeight } = uni.<span class="hljs-title function_">getSystemInfoSync</span>();
    <span class="hljs-comment">// 距离底部距离</span>


    <span class="hljs-keyword">const</span> distance = windowHeight - clientY
    <span class="hljs-comment">// 滑动时间(毫秒),小于某个时间则自动close</span>
    <span class="hljs-keyword">const</span> toumoveTime = <span class="hljs-title class_">Date</span>.<span class="hljs-title function_">now</span>() - <span class="hljs-variable language_">this</span>.<span class="hljs-property">startIme</span>
    <span class="hljs-comment">// 必须触发了touchmove方法</span>
    <span class="hljs-keyword">if</span> (<span class="hljs-variable language_">this</span>.<span class="hljs-property">moveDistance</span> > <span class="hljs-number">0</span> && (distance < <span class="hljs-variable language_">this</span>.<span class="hljs-property">bottomCloseValue</span> || toumoveTime < <span class="hljs-variable language_">this</span>.<span class="hljs-property">moveCloseTime</span>)) {
      <span class="hljs-variable language_">this</span>.<span class="hljs-title function_">close</span>();
    } <span class="hljs-keyword">else</span> {
      <span class="hljs-variable language_">this</span>.<span class="hljs-property">moveDistance</span> = <span class="hljs-number">0</span>;
    }
},
</code></pre></p>
    当触摸动作停止后,如果符合预设的间距标准,并且达到规定的完成时限,那么就会撤销那个弹出界面;否则,就会把弹窗恢复原状。

    四、打开全屏

    全屏模式的核心在于确定可用的显示区域,同时将弹出窗口的尺寸调整为该区域的高度。

<p style='margin-bottom:15px;color:#555555;font-size:15px;line-height:200%;text-indent:2em;'>    <pre><code class="hljs language-js" lang="js"><span class="hljs-title function_">toggleFullScreen</span>(<span class="hljs-params"></span>) {
    <span class="hljs-keyword">if</span> (<span class="hljs-variable language_">this</span>.<span class="hljs-property">isFullScrren</span>) {
      <span class="hljs-comment">// 关闭全屏,高度设为内容高度</span>
      <span class="hljs-variable language_">this</span>.<span class="hljs-property">height</span> = <span class="hljs-variable language_">this</span>.<span class="hljs-property">contentHeight</span>
    } <span class="hljs-keyword">else</span> {
    <span class="hljs-comment">// 开启全屏,设为视口高度</span>
      <span class="hljs-variable language_">this</span>.<span class="hljs-property">height</span> = <span class="hljs-variable language_">this</span>.<span class="hljs-property">windowHeight</span>
    }
    <span class="hljs-variable language_">this</span>.<span class="hljs-property">isFullScrren</span> = !<span class="hljs-variable language_">this</span>.<span class="hljs-property">isFullScrren</span>
},
</code></pre></p>
    同时兼容ios微信小程序和App端顶部和底部安全区域适配

    适配手机顶部和底部安全区域

<p style='margin-bottom:15px;color:#555555;font-size:15px;line-height:200%;text-indent:2em;'>    <pre><code class="hljs language-js" lang="js"><span class="hljs-keyword">const</span> {
    safeArea,
    windowHeight,
    screenHeight,
    osName
} = uni.<span class="hljs-title function_">getSystemInfoSync</span>();
<span class="hljs-comment">调整布局以适应顶部和底部预留空间, safeArea.height指定安全区域的高度, 以逻辑像素计</span>
<span class="hljs-keyword">const</span>安全视口高度等于视口高度减去屏幕高度与安全区域之差<span class="hljs-property">bottom</span>)
<span class="hljs-comment">// 打开全屏的高度</span>
<span class="hljs-variable language_">this</span>.<span class="hljs-property">windowHeight</span> = safeWindowHeight
</code></pre></p>
    适配手机app端顶部和底部安全区域

<p style='margin-bottom:15px;color:#555555;font-size:15px;line-height:200%;text-indent:2em;'>    <pre><code class="hljs language-js" lang="js"><span class="hljs-comment">// #ifdef APP-PLUS</span>
<span class="hljs-keyword">const</span> {
    windowHeight,
    osName
} = uni.<span class="hljs-title function_">getSystemInfoSync</span>();
<span class="hljs-keyword">if</span> (osName === <span class="hljs-string">'ios'</span>) {
    <span class="hljs-comment">// ios没设备</span>
} <span class="hljs-keyword">else</span> {
    <span class="hljs-comment">// android</span>
    打开全屏的高度
    <span class="hljs-variable language_">this</span>.<span class="hljs-property">windowHeight</span> = windowHeight
}
</code></pre></p>
    五、总结

    以上实现主要有三部分内容:

    1.弹窗跟随手势向下移动。

    2.手势距离底部一定距离或者手势移动足够快关闭弹窗。

    运用uni.()方法取得设备相关数据,依据这些数据计算弹出层所需的全屏垂直尺寸,确保能适配多种设备规格。

    去体验插件:插件市场
您需要登录后才可以回帖 登录 | 立即注册

Archiver|手机版|小黑屋|关于我们

Copyright © 2001-2025, Tencent Cloud.    Powered by Discuz! X3.5    京ICP备20013102号-30

违法和不良信息举报电话:86-13718795856 举报邮箱:hwtx2020@163.com

GMT+8, 2025-9-1 01:56 , Processed in 0.097375 second(s), 18 queries .