欧美三级国产三级日韩三级_亚洲熟妇丰满大屁股熟妇_欧美亚洲成人一区二区三区_国产精品久久久久久模特

小程序與動畫的故事 - 新聞資訊 - 云南小程序開發(fā)|云南軟件開發(fā)|云南網(wǎng)站建設(shè)-昆明葵宇信息科技有限公司

159-8711-8523

云南網(wǎng)建設(shè)/小程序開發(fā)/軟件開發(fā)

知識

不管是網(wǎng)站,軟件還是小程序,都要直接或間接能為您產(chǎn)生價值,我們在追求其視覺表現(xiàn)的同時,更側(cè)重于功能的便捷,營銷的便利,運營的高效,讓網(wǎng)站成為營銷工具,讓軟件能切實提升企業(yè)內(nèi)部管理水平和效率。優(yōu)秀的程序為后期升級提供便捷的支持!

您當前位置>首頁 » 新聞資訊 » 小程序相關(guān) >

小程序與動畫的故事

發(fā)表時間:2021-4-13

發(fā)布人:葵宇科技

瀏覽次數(shù):66

一、故事序幕

時間一分一秒地流逝,小程序已伴隨我們?nèi)d有余,今天要講的是關(guān)于小程序與動畫的故事:從前...

二、故事開頭

一提小程序與動畫,首先想到的是什么?嗯,微信小程序獨創(chuàng)了一套動畫玩法,官方支持3種動畫方案,分別是 createAnimation 、 this.animate 和 CSS3動畫 。

1. createAnimation 與 Animation

創(chuàng)建一個動畫實例animation。調(diào)用實例的方法來描述動畫。最后通過動畫實例的export方法導(dǎo)出動畫數(shù)據(jù)傳遞給組件的animation屬性。

var animation = wx.createAnimation({
  transformOrigin: "50% 50%",
  duration: 1000,
  timingFunction: "ease",
  delay: 0
})

// step() 表示一組動畫的完成,可以在一組動畫中調(diào)用任意多個動畫方法
// 一組動畫中的所有動畫會同時開始,一組動畫完成后才會進行下一組動畫
animation.translate(150, 0).rotate(180).step()
animation.opacity(0).scale(0).step()
this.setData({
  animationData: animation.export()
})

2. 關(guān)鍵幀動畫 this.animate 接口

從小程序基礎(chǔ)庫 2.9.0 開始支持一種更友好的動畫創(chuàng)建方式,用于代替舊的 wx.createAnimation 。它具有更好的性能和更可控的接口。在頁面或自定義組件中,當需要進行關(guān)鍵幀動畫時,可以使用 this.animate 接口。

this.animate(selector, keyframes, duration, callback)

官方給出的例子:

this.animate('#container', [
    { opacity: 1.0, rotate: 0, backgroundColor: '#FF0000' },
    { opacity: 0.5, rotate: 45, backgroundColor: '#00FF00'},
    { opacity: 0.0, rotate: 90, backgroundColor: '#FF0000' },
    ], 5000, function () {
      this.clearAnimation('#container', { opacity: true, rotate: true }, function () {
        console.log("清除了#container上的opacity和rotate屬性")
      })
  }.bind(this))

3. css3動畫

這是界面動畫的常見方式,CSS 動畫運行效果良好,甚至在低性能的系統(tǒng)上。渲染引擎會使用跳幀或者其他技術(shù)以保證動畫表現(xiàn)盡可能的流暢。

利用樣式實現(xiàn)小程序動畫,用法和css用法相似,定義好指定的動畫類名后給元素加上即可。

這是一個模仿心跳的動畫:

@keyframes heartBeat {
  0% {
    transform: scale(1);
  }

  14% {
    transform: scale(1.3);
  }

  28% {
    transform: scale(1);
  }

  42% {
    transform: scale(1.3);
  }

  70% {
    transform: scale(1);
  }
}

.heartBeat {
  animation-name: heartBeat;
  animation-duration: 1.3s;
  animation-timing-function: ease-in-out;
}

三、故事發(fā)展

故事的設(shè)定是這樣子的:需要支持多種預(yù)設(shè)的動畫效果配置,且實現(xiàn)進場動畫、強調(diào)動畫、退場動畫按順序運行。

如下,“3件5折/2件7折/1件9折”的文本 設(shè)置了 進場動畫-從小到大 以及 強調(diào)動畫-脈沖 的動畫效果:

生成的小程序效果:

Taro 是小程序的好伙伴,而且基于故事的設(shè)定,H5 還是要點飯吃的。

要想快速進入故事高潮,不得不采用一些取巧的手段了,決定采用市面上常見的 Animate.css 動畫庫來支持多種預(yù)設(shè)的動畫效果!

1. 支持多種動畫配置

Animate.css是一個可在您的Web項目中使用的即用型跨瀏覽器動畫庫,預(yù)設(shè)了抖動(shake)、閃爍(flash)、彈跳(bounce)、翻轉(zhuǎn)(flip)、旋轉(zhuǎn)(rotateIn/rotateOut)、淡入淡出(fadeIn/fadeOut)等97種動畫效果。 官網(wǎng) 首頁即可查看所有動畫效果。

要支持多種動畫配置,考慮將 animate.css 這個非常棒的css庫引入到小程序內(nèi)使用。

從 https://github.com/animate-cs... 下載源碼,將 .css 文件 改名為 .wxss 或者.scss 文件,在頁面或組件中引入樣式文件即可。

import './animate.scss'

Animate.css 的使用非常簡單,因為它是把不同的動畫類型綁定到了不同的類里,所以想用哪種動畫,只需要把相應(yīng)的類添加到元素上就可以盡情享用了。

由于小程序?qū)Υa包的大小限制,因此可刪除 animate.css 中所有 @-webkit- 等前綴的樣式減少一半體積,甚至直接使用 @keyframes 的代碼,即去掉類名的方式調(diào)用。

2. 執(zhí)行完一個動畫后接著執(zhí)行另一個動畫 ?

從上文可知,采用的是CSS3的動畫方案,基本決定了故事的下一個發(fā)展階段。

如果要實現(xiàn)進場動畫、強調(diào)動畫、退場動畫按順序運行,那么需要監(jiān)聽上一個動畫結(jié)束,緊接著運行下一個動畫。

動畫過程中,微信小程序可以使用 bindtransitionend 、 bindanimationstart 、 bindanimationiteration 、 bindanimationend 來監(jiān)聽動畫事件。

在 Taro 中內(nèi)置組件的事件依然是以 on 開頭的,即 onTransitionEnd 、 onAnimationStart 、 onAnimationIteration 、 onAnimationEnd 。

注意:監(jiān)聽動畫事件都不是冒泡事件,需要綁定在真正發(fā)生了動畫的節(jié)點上才會生效。

要實現(xiàn)進場之前不可見,退場后不可見,設(shè)置 animation-fill-mode: both 即可,且不可移除樣式,因為退場動畫的效果效果 會失效,元素又顯示出來了。

可能還得處理其他行為,比如 消失的元素 實際可能還占位,交互點擊的行為最好解綁。

<View
  onAnimationEnd={this.onAnimationEnd}
>
  {this.props.children}
</View>

四、故事高潮

故事都鋪墊好了,終于來到了高潮。

眼尖的人兒也發(fā)現(xiàn)了,上文GIF圖 “生成的小程序效果” 還實現(xiàn)了滾動到可視區(qū)域才開始執(zhí)行動畫的效果。

這是老生常談的話題了,那怎么在小程序側(cè)實現(xiàn)呢?

方案一:頁面滾動模式

  1. 小程序利用 onPageScroll 的 API 監(jiān)聽用戶滑動頁面事件,可獲取 scrollTop :頁面在垂直方向已滾動的距離(單位px)。
  2. Taro.createSelectorQuery 獲取元素在顯示區(qū)域的豎直滾動位置。
  3. 基上計算是否在可視區(qū)域來判斷是否要開始動畫。

方案二:觀察者模式

  1. 不支持 onPageScroll 的情況下,則需要使用 Taro.createIntersectionObserver 獲取目標節(jié)點與參照區(qū)域的相交比例觸發(fā)相關(guān)的回調(diào)函數(shù),即觀察者模式。

代碼奉上

(1) Taro獲取當前頁面的方式

首先我們要知道如何獲取當前頁面棧,數(shù)組中第一個元素為首頁,最后一個元素為當前頁面:

getCurrentPage () {
  const pages = Taro.getCurrentPages ? Taro.getCurrentPages() : [{}]
  const currentPage = pages[pages.length - 1]
  return currentPage
}

(2) 初始化頁面滾動

判斷使用頁面滾動模式還是觀察者模式:

initPageScroll () {
  const env = Taro.getEnv()
  const currentPage = this.getCurrentPage()

  // 獲取onPageScroll方法
  const onPageScroll = currentPage.onPageScroll

  // 頁面滾動模式:h5 或「小程序頁面有onPageScroll鉤子」使用統(tǒng)一的代碼
  const isPageScroll =
    env === Taro.ENV_TYPE.WEB ||
    (env !== Taro.ENV_TYPE.WEB && onPageScroll !== undefined)

  // 觀察者模式:小程序頁面沒有 onPageScroll 鉤子,使用 Taro.createIntersectionObserver 監(jiān)聽
  const isObserver = env !== Taro.ENV_TYPE.WEB && Taro.createIntersectionObserver

  if (isPageScroll) {
    this.listenPageScroll(currentPage)
  } else if (isObserver) {
    this.observePageScroll()
  }
}

(3) 頁面滾動模式

首先在類外頭定義一個多環(huán)境的 pageScroll 鉤子,支持小程序和H5:

const createPageScroll = function(page) {
  const env = Taro.getEnv()
  let onPageScroll = () => {}

  if (env !== Taro.ENV_TYPE.WEB) {
    // 小程序
    const prevOnPageScroll = page.onPageScroll.bind(page)
    page.onPageScroll = e => {
      prevOnPageScroll(e)
      onPageScroll(e)
    }
  } else if (env === Taro.ENV_TYPE.WEB) {
    // H5
    window.addEventListener("scroll", () => {
      onPageScroll({ scrollTop: window.scrollY })
    })
  }

  return nextOnPageScroll => {
    onPageScroll = nextOnPageScroll
  }
}

使用上述定義的createPageScroll方法,開始監(jiān)聽滾動:

listenPageScroll (currentPage) {
  const pageScroll = createPageScroll(currentPage)
  pageScroll(this.onScroll)
}

獲取距離頁面頂部高度來判斷是否要開始動畫:

知識點:

  • 在 Taro 的頁面和組件類中, this 指向的是 Taro 頁面或組件的實例,而通過 this.$scope 獲取 Taro 的頁面和組件所對應(yīng)的小程序原生頁面和組件的實例。
  • Taro.createSelectorQuery 返回一個 SelectorQuery 對象實例。在自定義組件或包含自定義組件的頁面中,應(yīng)使用 this.createSelectorQuery() 來代替。
  • SelectorQuery對象實例可進一步查詢節(jié)點信息,提供 select 、 in 、 exec 等方法。
  • NodesRef 的 boundingClientRect 用于查詢節(jié)點的布局位置,相對于顯示區(qū)域,以像素為單位,其功能類似于 DOM 的 getBoundingClientRect。
onScroll = () => {
  const query = Taro.createSelectorQuery().in(this.$scope)
  query
    .select(`.animation-${this.uniq}`)
    .boundingClientRect(res => {
      if (!res) return

      let resTop = res.top
      const distance = res.height / 2
      const isStartAnimation = resTop + distance < this.windowHeight
      if (isStartAnimation && !this.isAnimated) {
        this.startAnimation()
        // 動畫只出現(xiàn)一次
        this.isAnimated = true
      }
    })
    .exec()
}

(4) 觀察者模式:

知識點:

  • Taro.createIntersectionObserver 創(chuàng)建并返回一個 IntersectionObserver 對象實例。在自定義組件或包含自定義組件的頁面中,應(yīng)使用 this.createIntersectionObserver([options]) 來代替。
  • IntersectionObserver 對象,用于推斷某些節(jié)點是否可以被用戶看見、有多大比例可以被用戶看見。
  • IntersectionObserver 的 relativeToViewport 方法 指定頁面顯示區(qū)域作為參照區(qū)域之一。
  • IntersectionObserver 的 observe 指定目標節(jié)點并開始監(jiān)聽相交狀態(tài)變化情況,其中 res.intersectionRatio 指相交區(qū)域占目標節(jié)點的布局區(qū)域的比例。
observePageScroll () {
  const navObserver = Taro.createIntersectionObserver(this.$scope, {
    initialRatio: 0.5,
    thresholds: [0.5]
  })
  navObserver.relativeToViewport()
  navObserver.observe(`.animation-${this.uniq}`, res => {
  const isStartAnimation = !this.isAnimated && res.intersectionRatio > 0.5
    if (isStartAnimation) {
      this.startAnimation()
      // 動畫只出現(xiàn)一次
      this.isAnimated = true
    }
  })
}

五、故事結(jié)尾

小程序與動畫的故事遠遠沒有結(jié)束,縱使故事有了開頭,你看到的只是故事的萬種可能的其中一種。

故事就要告一段落了,小程序的故事還在持續(xù)奔跑,感謝 微信小程序 和 taro 的文檔。

歡迎關(guān)注凹凸實驗室博客: aotu.io

或者關(guān)注凹凸實驗室公眾號(AOTULabs),不定時推送文章。

相關(guān)案例查看更多