首頁 > web前端 > uni-app > 主體

uniapp怎麼實現小程式頁面的自由拖曳功能

青灯夜游
發布: 2021-09-07 19:28:04
轉載
8544 人瀏覽過

uniapp怎麼實作小程式頁面的自由拖曳功能?以下這篇文章跟大家介紹一下uniapp實作小程式頁面自由拖曳組件的方法,希望對大家有幫助!

uniapp怎麼實現小程式頁面的自由拖曳功能

先看實現效果:

uniapp怎麼實現小程式頁面的自由拖曳功能

【相關推薦:《uniapp教學》】

實作過程

根據查閱文檔,要實現拖曳功能,大概有三種方式:

1.給需要實現拖曳的元素監聽#catchtouchmove事件,動態修改樣式座標

#這種方式最容易想到,透過js監聽觸控位置動態修改元素座標。但是拖曳是即時性要求非常高的操作,你不能說在這個操作裡面去設定節流函數減少setData操作,並且本身每次setData操作也是比較耗性能的,很容易造成拖曳卡頓,這個方案可以先排除。

2.movable-area movable-view

#movable-area元件的作用是定義一個區域,在這個區域內的movable- view的元件可以被使用者自由的移動,同時movable-view也可以輕鬆設定放大縮小效果。根據元件定義,可以想到它的使用場景大概是在頁面局部區域內對一些元素拖曳縮放,這個與我們想要的在整個頁面進行自由拖曳的需求不符。

3.wxs回應事件

wxs是專門用來解決有頻繁互動的場景,它直接在視圖層運行,免去了視圖層跟邏輯層通訊帶來的效能損耗,實現流暢的動畫效果。詳見:wxs回應事件 。根據wxs的使用場景,基本能確定我們要的功能實作應該使用wxs方案。

程式碼實作

我們使用的是uniapp框架,查閱uniapp文檔,官方直接提供了一個自由拖曳的程式碼案例,鏈接點擊這裡

直接拿官方的程式碼範例改造一番,如下:

<template>
    <view catchtouchmove="return">
        <view @click="play" @touchstart="hudun.touchstart" @touchmove="hudun.touchmove" @touchend="hudun.touchend">
            <canvas id="lottie-canvas" type="2d" style="width: 88px; height: 102px;"></canvas>
        </view>
    </view>
</template>

<script module="hudun">
    var startX = 0
    var startY = 0
    var lastLeft = 20
    var lastTop = 20

    function touchstart(event, ins) {
        ins.addClass(&#39;expand&#39;)
        var touch = event.touches[0] || event.changedTouches[0]
        startX = touch.pageX
        startY = touch.pageY
    }
    
    function touchmove(event, ins) {
        var touch = event.touches[0] || event.changedTouches[0]
        var pageX = touch.pageX
        var pageY = touch.pageY
        var left = pageX - startX + lastLeft
        var top = pageY - startY + lastTop
        startX = pageX
        startY = pageY
        lastLeft = left
        lastTop = top
        ins.selectComponent(&#39;.movable&#39;).setStyle({
            right: -left + &#39;px&#39;,
            bottom: -top + &#39;px&#39;
        })
    }
    
    function touchend(event, ins) {
        ins.removeClass(&#39;expand&#39;)
    }
    
    module.exports = {
        touchstart: touchstart,
        touchmove: touchmove,
        touchend: touchend
    }
</script>

<script>
    import lottie from &#39;lottie-miniprogram&#39;
    let insList = {} // 存放动画实例集合
    export default {
        props: {
            tag: String
        },
        data() {
            return {
                isPlay: true,
            }
        },
        methods: {
            init() {
                const query = uni.createSelectorQuery().in(this)
                query.select(&#39;#lottie-canvas&#39;).fields({ node: true, size: true }).exec((res) => {
                    const canvas = res[0].node
                    const context = canvas.getContext(&#39;2d&#39;)
                    const dpr = uni.getSystemInfoSync().pixelRatio
                    canvas.width = res[0].width * dpr
                    canvas.height = res[0].height * dpr
                    context.scale(dpr, dpr)
                    lottie.setup(canvas)
                    const ins = lottie.loadAnimation({
                        loop: true,
                        autoplay: true,
                        path: &#39;https://usongshu.oss-cn-beijing.aliyuncs.com/data/other/f8780255686b0bb35d25464b2eeea294.json&#39;,
                        rendererSettings: {
                            context,
                        },
                    })
                    insList[this.tag] = ins
                    setTimeout(() => {
                        this.isPlay = false
                        ins.stop()
                    }, 3000)
                })
            },
            play() {
                const ins = insList[this.tag]
                if (!this.isPlay) {
                    this.isPlay = true
                    ins.play()
                    setTimeout(() => {
                        this.isPlay = false
                        ins.stop()
                    }, 3000)
                }
            }
        },
        beforeDestroy() {
            delete insList[this.tag]
        }
    }
</script>

<style>
    .area
        position fixed
        right 20px
        bottom 20px
        width 88px
        height 102px
        z-index 99999

    .expand
        width 100vw
        height 100vh

    .movable
        position absolute
</style>
登入後複製

上面程式碼是開篇效果圖實作的完整程式碼,已經封裝一個單獨的元件。我們要拖曳的是一個canvas元素,用到了lottie動畫庫,點擊時會播放動畫。如果你要實現頁面拖曳的只是一個簡單的按鈕,那程式碼量會少很多。如果你要實現的功能跟這個類似,那麼針對上面程式碼有以下幾點需要值得解釋:

1.我們的需求是在多個頁面需要展示,經過查閱相關資料,是沒法實現在只在一個地方放置元件,然後每個頁面展示,必須每個頁面引入該元件。幸運的是,uniapp支援定義全域小程式元件,可以幫助我們減少引入的程式碼量。做法如下: 在main.js中定義元件

// 动画组件
import { HudunAnimation } from &#39;@/components/hudun-animation/index&#39;
Vue.component(&#39;HudunAnimation&#39;, HudunAnimation)
登入後複製

頁面中使用: wxml:

<HudunAnimation tag="index" ref="hudunRef"></HudunAnimation>
登入後複製
// 进入页面时初始化动画
mounted() {
    this.$refs.hudunRef.init()
}
登入後複製

2.可以注意到,上面封裝的元件當中,有一個tag屬性,它是用來識別來自哪個頁面的動畫實例。它的存在是由於在元件當中,正常情況下我們可以直接在data中定義一個屬性存放動畫實例,但是經過踩坑發現如果直接這麼寫

this.ins = lottie.loadAnimation({})
登入後複製

控制台會報一個錯誤,是因為lottie.loadAnimation({})回傳的物件放置在data中會經過一個JSON.stringfy的過程,在這個過程中不知道什麼原因報錯了。為了解決此報錯,改為在元件全域定義一個insList存放動畫實例集合,透過傳入的tag拿到對應的頁面實例,然後呼叫對應的實例play方法。

頁面穿透及點擊問題

1、拖曳頁面的時候,會帶動頁面的滾動,解決這個問題很簡單,在area view中新增

catchtouchmove="return"
登入後複製

即可

2、無法點選拖曳區域頁面按鈕問題。首先我們的拖曳區域是整個頁面,用的是fixed定位覆蓋整個頁面,但是這麼一來就會導致蒙層下面的頁面無法回應點擊事件。所以我們需要透過動態設定類別名稱expand,當元素處於拖曳狀態時,我們才將蒙層的區域覆蓋整個頁面,而初始時區域跟拖曳元素保持一致即可。程式碼實作見上面完整程式碼

檢視體驗效果

#微信搜尋小程式:說客英語--你的私人外教

更多程式相關知識,請造訪:程式設計入門! !

以上是uniapp怎麼實現小程式頁面的自由拖曳功能的詳細內容。更多資訊請關注PHP中文網其他相關文章!

相關標籤:
來源:juejin.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板
關於我們 免責聲明 Sitemap
PHP中文網:公益線上PHP培訓,幫助PHP學習者快速成長!