鍍金池/ 問答/動(dòng)漫  網(wǎng)絡(luò)安全  HTML/ vue利用javascript鉤子函數(shù)實(shí)現(xiàn)動(dòng)畫無效

vue利用javascript鉤子函數(shù)實(shí)現(xiàn)動(dòng)畫無效

想封裝一個(gè)簡(jiǎn)單的動(dòng)畫組件,用css實(shí)現(xiàn)了一遍,效果是可行的,如下:

<template>
    <div>
        <transition name="bar">
            <slot></slot>
        </transition>
    </div>
</template>

<style lang="stylus" scoped>
.bar-enter-active, .bar-leave-active{
    transition: all .3s;
}

.bar-leave-active{
    transform translateY(200px)
}

.bar-enter{
    transform translateY(200px)
}
</style>

因?yàn)楹芏嘈枰獎(jiǎng)討B(tài)計(jì)算,所以想改為javascript 鉤子函數(shù)來實(shí)現(xiàn),但是發(fā)現(xiàn)怎么嘗試都沒有效果:

<template>
    <div>
        <transition
            v-on:before-enter="beforeEnter"
            v-on:enter="enter"
            v-on:leave="leave"
        >
            <slot></slot>
        </transition>
    </div>
</template>
<script>
export default {
    name: 'animation',
    methods: {
        beforeEnter: function (el) {
            el.style.transform = 'translate-y(200px)'
        },
        // 此回調(diào)函數(shù)是可選項(xiàng)的設(shè)置
        // 與 CSS 結(jié)合時(shí)使用
        enter: function (el, done) {
            el.style.transitionDuration = "3s"
            el.style.transitionProperty = "all"
            done()
        },

        // 此回調(diào)函數(shù)是可選項(xiàng)的設(shè)置
        // 與 CSS 結(jié)合時(shí)使用
        leave: function (el, done) {
            el.style.transform = 'translate-y(200px)'
            // el.style.transition = 'all 3s'
            el.style.transitionDuration  = "3s"
            el.style.transitionProperty = "all"
            done()
        },
    }
}
</script>

問題出在哪兒呢?

回答
編輯回答
幼梔

@donglegend 你好,謝謝,基本上可以,但是這種方式感覺有缺陷,如下:

//假設(shè)我想在1s中完成動(dòng)畫(滑動(dòng)250px)
//那么我需要函數(shù)執(zhí)行多少次呢?
//很顯然,如果我想動(dòng)畫看上去越順滑,那必須每次移動(dòng)的像素就越小,所以函數(shù)執(zhí)行越頻繁;
//相反,如果函數(shù)間隔時(shí)間越大,動(dòng)畫會(huì)非常難看(一次移動(dòng)的像素太多)

問題:假設(shè)我滑動(dòng)的距離足夠大(1000px),執(zhí)行的時(shí)間足夠短(0.3s),看上去動(dòng)畫要足夠順滑(每次移動(dòng)5px),那么函數(shù)需要多長(zhǎng)時(shí)間執(zhí)行一次呢? 。0.3 / (1000 / 5) ,0.3s要執(zhí)行200次函數(shù),每 0.0015s 執(zhí)行一次,這么頻繁的執(zhí)行函數(shù)到底有沒有問題呢?如果每次只能移動(dòng)1px呢?

再者就是這些計(jì)算麻煩,不如css3動(dòng)畫來得方便。

我用css實(shí)現(xiàn)的動(dòng)畫和js鉤子實(shí)現(xiàn)的作比較,都是0.3s,總感覺css的動(dòng)畫要快,要順滑。

<template>
    <transition
        v-on:before-enter="beforeEnter"
        v-on:enter="enter"
        v-on:leave="leave"
    >
        <slot></slot>
    </transition>
</template>
<script>
export default {
    name: 'animation',
    data() {
        return {
            enterTimer: null,
            leaveTimer: null
        }
    },
    methods: {
        beforeEnter: function(el) {
            //設(shè)置滑塊的初始位置(滑塊的寬度)
            el.style.bottom = '-250px'
        },
        enter: function(el, done) {
            clearInterval(this.leaveTimer)
            let _v = 0
            //假設(shè)我想在1s中完成動(dòng)畫(滑動(dòng)250px)
            //那么我需要函數(shù)執(zhí)行多少次呢?
            //很顯然,如果我想動(dòng)畫看上去越順滑,那必須每次移動(dòng)的像素就越小,所以函數(shù)執(zhí)行越頻繁;
            //相反,如果函數(shù)間隔時(shí)間越大,動(dòng)畫會(huì)非常難看(一次移動(dòng)的像素太多)
            this.enterTimer = setInterval(() => {
                if (_v < 250) {
                    _v += 2.5
                } else {
                    _v = 250
                    clearInterval(this.enterTimer)
                    done()
                }
                el.style.opacity = _v
                el.style.transform = `translateY(-${_v}px)`
            }, 3)
        },
        leave: function(el, done) {
            clearInterval(this.enterTimer)
            let _v = 250
            this.leaveTimer = setInterval(() => {
                if (_v > 0) {
                    _v -= 2.5
                } else {
                    _v = 0
                    clearInterval(this.leaveTimer)
                    done()
                }
                el.style.opacity = _v
                el.style.transform = `translateY(-${_v}px)`
            }, 3)
        }
    }
}
</script>

之前一直以為官方價(jià)紹了兩種方式是等價(jià)的,并且兩種方式對(duì)應(yīng)的demo不是等效的,感覺這是巨大的一個(gè)坑

2018年1月13日 10:43
編輯回答
初念

題主可能沒太理解 javascript鉤子動(dòng)畫的用法。
你第一種是用 class類名切換通過css3自身實(shí)現(xiàn)的過渡動(dòng)畫,但是鉤子函數(shù)實(shí)現(xiàn)動(dòng)畫是另一種概念,需要通過 自己用定時(shí)器實(shí)現(xiàn),當(dāng)然也可以配合css使用,這個(gè)官方有說明,下面簡(jiǎn)單寫一個(gè) opacity 過渡demo,
題主可以參考理解一下,如有疑問,歡迎再次討論。

<template>
    <transition
        v-on:before-enter="beforeEnter"
        v-on:enter="enter"
        v-on:leave="leave"
    >
        <slot></slot>
    </transition>
</template>
<script>
export default {
    name: 'animation',
    data() {
        return {
            enterTimer: null,
            leaveTimer: null
        }
    },
    methods: {
        beforeEnter: function(el) {
            el.style.opacity = 0
            el.style.transform = 'translateX(0px)'
            el.style.transformOrigin = 'left'
        },
        // 此回調(diào)函數(shù)是可選項(xiàng)的設(shè)置
        // 與 CSS 結(jié)合時(shí)使用
        enter: function(el, done) {
            clearInterval(this.leaveTimer)
            let _v = 0
            this.enterTimer = setInterval(() => {
                if (_v < 1) {
                    _v += 0.01
                } else {
                    _v = 1
                    clearInterval(this.enterTimer)
                    done()
                }
                el.style.opacity = _v
                el.style.transform = `translateX(${_v * 100}px)`
            }, 30)
        },

        // 此回調(diào)函數(shù)是可選項(xiàng)的設(shè)置
        // 與 CSS 結(jié)合時(shí)使用
        leave: function(el, done) {
            clearInterval(this.enterTimer)
            let _v = 1
            this.leaveTimer = setInterval(() => {
                if (_v > 0) {
                    _v -= 0.01
                } else {
                    _v = 0
                    clearInterval(this.leaveTimer)
                    done()
                }
                el.style.opacity = _v
                el.style.transform = `translateX(${_v * 100}px)`
            }, 30)
        }
    }
}
</script>
2017年8月3日 08:14
編輯回答
旖襯
enter: function (el, done) {
   this.$nextTick(()=>{
            el.style.transitionDuration = "3s"
            el.style.transitionProperty = "all"
            })
            done()
        },

這樣試試

2018年2月18日 12:15