小程序輪播如何實(shí)現(xiàn)3d裸眼效果?下面本篇文章來(lái)給大家介紹一下實(shí)現(xiàn)方法,為春節(jié)氣氛添燈加彩,希望對(duì)大家有所幫助!
一個(gè)APP眾多功能模塊中,首頁(yè)輪播圖扮演著重要角色,它是分發(fā)重點(diǎn)資訊的入口。想起幾個(gè)月前看過(guò)一篇文章–《自如客APP裸眼3D效果的實(shí)現(xiàn)》,該文提及在安卓app端實(shí)現(xiàn)了如下裸眼3d banner輪播效果圖:
受該文啟發(fā),決定“依葫蘆畫(huà)瓢”,嘗試在小程序端模擬實(shí)現(xiàn)一個(gè)春節(jié)氛圍滿(mǎn)滿(mǎn)的3d裸眼效果輪播圖。
原理
仔細(xì)觀(guān)察上面實(shí)現(xiàn)的動(dòng)態(tài)效果圖,可以看出該banner圖并非常規(guī)的一張圖片,而是采用了一張圖內(nèi)容分層的方式疊加顯示(上文提及的文章有提到,是采用了背景層,前景和中景三個(gè)疊加后呈現(xiàn),可以先移步上文了解),然后監(jiān)聽(tīng)手機(jī)方向傳感器,根據(jù)方向?qū)η熬昂捅尘斑M(jìn)行移動(dòng),造成視覺(jué)上的景深效果。
有趣的是,如果你使用的是iPhone手機(jī),相信你應(yīng)該能發(fā)現(xiàn)在首頁(yè)狀態(tài)下,隨著手機(jī)不同方向的轉(zhuǎn)動(dòng),背景圖會(huì)跟著反方向輕微移動(dòng),也能給人一種類(lèi)似的景深效果。(效果如下圖)
實(shí)戰(zhàn)
介紹完了原理,那就開(kāi)始實(shí)戰(zhàn)吧。
翻閱小程序文檔,我們需要用到兩個(gè)API:wx.startDeviceMotionListening 和 wx.onDeviceMotionChange。 這里我們需要重點(diǎn)關(guān)注的是wx.onDeviceMotionChange這個(gè)API返回的內(nèi)容,根據(jù)文檔,該API返回如下三個(gè)值:
如果你是第一次接觸這個(gè)API,相信你看了文檔也是一頭霧水,接下來(lái)我將用chrome瀏覽器調(diào)試工具幫你徹底理解這三個(gè)值分別是什么意思。
借助chrome開(kāi)發(fā)者工具理解API返回值
打開(kāi)瀏覽器開(kāi)發(fā)者工具,按照如下步驟打開(kāi)傳感器調(diào)試:
打開(kāi)后,看這里:
咦?這不是一樣的嗎?沒(méi)錯(cuò),這里顯示的三個(gè)值剛好與該API返回值對(duì)應(yīng)。可以看到在alpha=0,beta=90,gamma=0的情況下,代表手機(jī)是垂直立在平面,我門(mén)可以點(diǎn)擊選項(xiàng)或者直接在輸入框中修改值,就可以直觀(guān)的看到隨著值的變化,手機(jī)的翻轉(zhuǎn)狀態(tài)變化,例如手機(jī)平放桌面時(shí),三個(gè)參數(shù)值如下:
有了上面實(shí)時(shí)模擬的工具,接下來(lái)這個(gè)圖就好理解了:
- alpha:表示設(shè)備沿 Z 軸旋轉(zhuǎn)的角度,范圍為 0~360;
- beta:表示設(shè)備在x軸上的旋轉(zhuǎn)角度,范圍為-180~180。它描述的是設(shè)備由前向后旋轉(zhuǎn)的情況;
- gamma:表示設(shè)備在y軸上的旋轉(zhuǎn)角度,范圍為-90~90。它描述的是設(shè)備由左向右旋轉(zhuǎn)的情況。
代碼
wxml:
<view class="swiper-box"> <image src="{{item}}" wx:for="{{background}}" class="swiper-bg {{animationStart || current === index ? 'fadeIn' : 'fadeOut'}} "></image> <swiper indicator-dots="{{true}}" indicator-active-color="#fff" interval="{{3000}}" autoplay="{{true}}" circular="{{true}}" bindchange="handleChange" bindtransition="handleTransition" bindanimationfinish="handleFinish"> <block wx:for="{{background}}" wx:key="*this"> <swiper-item> <view class="swiper-item-content" > <image class="icon" src="../../images/cloud.png" style="width: 90px; height: 90px;transform: translate3d({{x}}px, {{y}}px, {{z}}px);" wx:if="{{index === 0}}"></image> <image class="icon" src="../../images/firecrackers.png" style="width: 90px; height: 90px;transform: translate3d({{x}}px, {{y}}px, {{z}}px);" wx:else></image> <text class="text" wx:if="{{index === 0}}">新年快樂(lè)</text> <text class="text" wx:else>大吉大利</text> </view> </swiper-item> </block> </swiper> </view>
這里注意的是,由于swiper只能嵌套swiper-item組件,所以需要將背景圖放置于swiper同級(jí),并用定位的方式顯示
js:
// index.js // 獲取應(yīng)用實(shí)例 const app = getApp() Page({ data: { background: ['https://cloud-minapp-39237.cloud.ifanrusercontent.com/1n6jtVIbbJ3rnAv7.jpg', 'https://cloud-minapp-39237.cloud.ifanrusercontent.com/1n6mBOvOutOFQ3E8.png',], x: 0, y: 0, z: 0, animationFinish: true, // 動(dòng)畫(huà)是否執(zhí)行完成 animationStart: false, // 是否開(kāi)始執(zhí)行動(dòng)畫(huà) current: 0, }, // 動(dòng)畫(huà)開(kāi)始執(zhí)行 handleTransition(e) { if (this.data.animationFinish) { this.setData({ animationFinish: false, animationStart: true, }) } }, // 動(dòng)畫(huà)執(zhí)行結(jié)束 handleFinish() { this.setData({ animationFinish: true, animationStart: false, }) }, // current值變化 handleChange(e) { this.setData({ current: e.detail.current, }) }, onLoad() { const that = this; // 監(jiān)聽(tīng)方向變化 wx.startDeviceMotionListening({ success() { wx.onDeviceMotionChange(function (res) { const { alpha, // 0-360 beta, // -180-180 gamma // -90- 90 } = res const disX = gamma / 90 * 20 const disY = beta / 90 * 12 let z = 0 if (disX > 0 || disY > 0) { z = 20 } else { z = -20 } that.setData({ x: disX, y: disY, z }) }) } }) } })
這里要做解釋的代碼是
const disY = beta / 90 * 12
正常我們使用手機(jī)是屏幕朝上,所以取相對(duì)值一半即可。 根據(jù)計(jì)算得到的偏移x,y后,頁(yè)面通過(guò)transform: translate3d()
改變?cè)仄凭嚯x。
最終實(shí)現(xiàn)效果
這里看起來(lái)效果不是特別明顯,原因有兩個(gè):
- 素材圖是我網(wǎng)上找到拼湊而成,總體合成效果并不美觀(guān),想達(dá)到較逼真的效果需要設(shè)計(jì)配合出素材圖;
- 在偏移至最大值時(shí),未做緩沖動(dòng)畫(huà),不合符直覺(jué)(這里后面有時(shí)間再研究實(shí)現(xiàn));
額外的動(dòng)畫(huà)效果
其實(shí)借助該方向API,我們還可以作為觸發(fā)動(dòng)畫(huà)的觸發(fā)器。例如在手機(jī)翻轉(zhuǎn)到一定角度值時(shí),我們可以播放煙花效果
安裝lottie-miniprogram包
npm i lottie-miniprogram
安裝完之后記得在微信開(kāi)發(fā)者工具中點(diǎn)擊構(gòu)建npm包
wxml:
<canvas id="canvas" type="2d" style="position: absolute;top: 0;left: 0;width: 300px; height: 200px;z-index: 99;"></canvas>
js:
onLoad() { // 初始化lottie動(dòng)畫(huà) wx.createSelectorQuery().select('#canvas').node(res => { const canvas = res.node const context = canvas.getContext('2d') lottie.setup(canvas) lottieInstance = lottie.loadAnimation({ path: 'https://assets10.lottiefiles.com/packages/lf20_1qfekvox.json', autoplay: true, loop: false, rendererSettings:{ context } }) }).exec() }
然后在wx.onDeviceMotionChange
中調(diào)用
lottieInstance.play()
處理觸發(fā)即可
完整代碼
https://github.com/pengjinlong/cases/tree/main/spring-article
本文轉(zhuǎn)載自:https://juejin.cn/post/7051490823497580574
作者:碼克吐溫
【相關(guān)學(xué)習(xí)推薦:小程序開(kāi)發(fā)教程】