日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網為廣大站長提供免費收錄網站服務,提交前請做好本站友鏈:【 網站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

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('expand')
        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('.movable').setStyle({
            right: -left + 'px',
            bottom: -top + 'px'
        })
    }
     
    function touchend(event, ins) {
        ins.removeClass('expand')
    }
     
    module.exports = {
        touchstart: touchstart,
        touchmove: touchmove,
        touchend: touchend
    }
</script>
 
<script>
    import lottie from 'lottie-miniprogram'
    let insList = {} // 存放動畫實例集合
    export default {
        props: {
            tag: String
        },
        data() {
            return {
                isPlay: true,
            }
        },
        methods: {
            init() {
                const query = uni.createSelectorQuery().in(this)
                query.select('#lottie-canvas').fields({ node: true, size: true }).exec((res) => {
                    const canvas = res[0].node
                    const context = canvas.getContext('2d')
                    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: 'https://usongshu.oss-cn-beijing.aliyuncs.com/data/other/f8780255686b0bb35d25464b2eeea294.json',
                        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 '@/components/hudun-animation/index'
Vue.component('HudunAnimation', 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拖拽功能 小程序頁面拖拽 自由拖拽
用戶無頭像

網友整理

注冊時間:

網站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網站吧!
最新入駐小程序

數獨大挑戰2018-06-03

數獨一種數學游戲,玩家需要根據9

答題星2018-06-03

您可以通過答題星輕松地創建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學四六

運動步數有氧達人2018-06-03

記錄運動步數,積累氧氣值。還可偷

每日養生app2018-06-03

每日養生,天天健康

體育訓練成績評定2018-06-03

通用課目體育訓練成績評定