仿了潮汐睡眠小程序的代碼。【如果有侵權聯系刪除
最近做的項目有個彈出層效果,類似音樂播放器那種。按照普通的做了一般感覺交互不是很優雅,設計妹子把潮汐睡眠的彈層給我看了看,感覺做的挺好,於是乘着有空仿照了一下。
首先善用度娘反編譯弄到了源碼,但是打不開。然后自己研究源碼發現他們用的是movable-view實現的。
於是仿照着搭出了基礎框架。
新建了個組件
wxml
<!--components/playpanel/playpanel.wxml--> <movable-area style="height:{{areaH}}px;" class="wrapper"> <movable-view bindchange="onPresent" bindtouchend="dragPanelEnd" bindtouchstart="dragPanelStart" class="sleep-panel-wrapper" damping="{{40}}" direction="vertical" friction="{{1}}" inertia="{{false}}" outOfBounds="{{false}}" style="padding-top:{{0}}px" x="{{0}}" y="{{sleepPanelPosition}}" class="panel"> <view class="" bindtap="presentPanel" hover-class="none" hover-stop-propagation="false"> 背景內容 </view> </movable-view> </movable-area> <scroll-view scroll-y style="height:400rpx" class="scroll-w" wx:if="{{showlist}}"> 歌曲列表 <view id="green" class="scroll-view-item bc_green"></view> <view id="red" class="scroll-view-item bc_red"></view> <view id="yellow" class="scroll-view-item bc_yellow"></view> <view id="blue" class="scroll-view-item bc_blue"></view> </scroll-view>
歌曲列表提取出來是因為滾動組件和可拖拽的手勢事件會互相影響,如果不需要彈出層有可滾動的區域可以無視。
js部分精簡一下就是這樣,abcd這些變量名應該是源碼做了加密……appjs里還要定義一下初始數據
// components/playpanel/playpanel.js let d = getApp(); Component({ /** * 組件的屬性列表 */ properties: { areaH:Number }, /** * 組件的初始數據 */ data: { sleepPanelPosition: d.globalData.screenHeight - (d.globalData.isFullScreen ? 24 : 0) - 80 / (375 / d.globalData.screenWidth), topPosition: d.globalData.statusBarHeight + d.globalData.navBarHeight, bottomPosition: d.globalData.screenHeight - (d.globalData.isFullScreen ? 24 : 0) - 80 / (375 / d.globalData.screenWidth), presentProgress: 0, disableAnimated: !1, showlist:false, }, /** * 組件的方法列表 */ methods: { dragPanelEnd(e) { let changedTouches = e.changedTouches; let pageY = changedTouches[0].pageY; let topPosition = this.data.topPosition; let bottomPosition = this.data.bottomPosition; let distance = pageY - this.dragOrigin; let speed = (bottomPosition - topPosition)/10; let h = 0; h = this.data.sleepPanelPosition === topPosition ? distance > speed ? bottomPosition : topPosition : distance < -speed ?topPosition : bottomPosition,this.setData({ sleepPanelPosition: h, showlist: h === topPosition }); }, presentPanel() { const {sleepPanelPosition: a, topPosition: b, bottomPosition: c} = this.data; this.setData({ sleepPanelPosition: a === b ? c : b, }); let showList = this.data.sleepPanelPosition === b this.setData({ showlist: showList }) }, dragPanelStart(a) { const {changedTouches: b} = a; if (b[0]) { const {pageY: a} = b[0]; this.dragOrigin = a; } }, onPresent({detail: a}) { const {y: b} = a, {topPosition: c, bottomPosition: d} = this.data, e = 1 - parseInt(1e3 * ((b - c) / (d - c))) / 1e3; e !== this.data.presentProgress && this.setData({ presentProgress: e }), this.data.disableAnimated || this.setData({ disableAnimated: !0 }), clearTimeout(this.recoverAnimation), this.recoverAnimation = setTimeout(() => { this.setData({ disableAnimated: !1 }), this.recoverAnimation = null; }, 100); }, } })
//app.js ``` onShow() { wx.getSystemInfo({ success: a => { const { screenHeight: b, screenWidth: c, statusBarHeight: d } = a; this.globalData.isFullScreen = parseInt(100 * (c / b)) < parseInt(100 * (9 / 17)), this.globalData.isBiggerScreen = 667 < b, this.globalData.statusBarHeight = d, this.globalData.navBarHeight = 44, this.globalData.navBarFontSize = 18.5, this.globalData.btnScopeSize = 40, this.globalData.btnSize = 32, this.globalData.screenHeight = b, this.globalData.screenWidth = c; } }); }, ```
wxss部分,主要是.panel不要設置top值,其他好像沒啥。
/* components/playpanel/playpanel.wxss */ .wrapper { position: fixed; top: 0; left: 0; bottom: 0; right: 0; width: 100vw; height: 200vh; pointer-events:none; } .panel { width: 100%; background: rgba(233, 233, 255, 0.8); height: 100vh; pointer-events: auto; } .scroll-view-item { height: 300rpx; } .bc_green { background: green; } .bc_red { background: red; } .bc_yellow { background: yellow; } .bc_blue { background: blue; } .scroll-w { position: fixed; bottom: 0; }