Skip to content

Commit

Permalink
feat: split implementation for skyline.
Browse files Browse the repository at this point in the history
close #247.
  • Loading branch information
Tidyzq committed Oct 17, 2024
1 parent 4335fb1 commit 6de0191
Show file tree
Hide file tree
Showing 11 changed files with 585 additions and 160 deletions.
4 changes: 3 additions & 1 deletion src/components/slideview/slideview.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
{
"component": true,
"styleIsolation": "apply-shared",
"usingComponents": {}
"usingComponents": {
"slideview-skyline": "/components/slideview/slideviewSkyline"
}
}
4 changes: 0 additions & 4 deletions src/components/slideview/slideview.less
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,3 @@
.weui-slideview__btn__wrp {
justify-content: center;
}
/** for skyline */
.weui-slideview_icon .weui-slideview__btn {
display: flex; /* skyline inline-block 居中有问题 */
}
194 changes: 46 additions & 148 deletions src/components/slideview/slideview.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,19 +25,11 @@ Component({
},
show: {
type: Boolean,
value: false,
observer() {
if (!this.st) return
if (this.data.show) {
this.showButtons()
} else {
this.hideButtons()
}
}
value: false
},
duration: {
type: Number,
value: 350 // 动画市场,单位ms
value: 350 // 动画时长,单位ms
},
throttle: {
type: Number,
Expand All @@ -52,27 +44,49 @@ Component({
/**
* 组件的初始数据
*/
data: {},
data: {
size: null,
renderer: 'webview'
},

created() {
this.setData({ renderer: this.renderer })
},

/**
* 组件的方法列表
*/
ready() {
this.updateRight()
this.addClassNameForButton()
// 共享元素 this.st
this.st = {
movex: wx.worklet.shared(0),
max: wx.worklet.shared(0),
startX: wx.worklet.shared(0),
startY: wx.worklet.shared(0),
out: wx.worklet.shared(this.data.show),
isMoving: wx.worklet.shared(false),
firstAngle: wx.worklet.shared(0),
buttons: wx.worklet.shared([])
}
this.initAnimate()
},
/**
* 组件的方法列表
*/
methods: {
updateRight() {
// 获取右侧滑动显示区域的宽度
const data: any = this.data
const query = wx.createSelectorQuery().in(this)
query
.select('.left')
.boundingClientRect((res) => {
const btnQuery = wx.createSelectorQuery().in(this)
btnQuery
.selectAll('.btn')
.boundingClientRect((rects) => {
this.setData({
size: {
buttons: rects,
button: res,
show: data.show,
disable: data.disable,
throttle: data.throttle,
rebounce: data.rebounce
}
})
})
.exec()
})
.exec()
},
addClassNameForButton() {
// @ts-ignore
const { buttons, icon } = this.data
Expand All @@ -89,131 +103,15 @@ Component({
buttons
})
},
buttonTap(event) {
this.hideButtons()
const index = event.currentTarget.dataset.index
this.triggerEvent(
'buttontap',
{
index,
data: this.data.buttons[index].data
},
{}
)
buttonTapByWxs(data) {
this.triggerEvent('buttontap', data, {})
},
transitionEnd() {},

showButtons() {
if (this.data.disable) return
const { movex, max, out } = this.st
if (out.value) return
out.value = true
movex.value = this.data.duration
? wx.worklet.timing(max.value, { duration: this.data.duration }, () => {})
: max.value
this.triggerEvent('show', {}, {})
},

hideButtons() {
if (this.data.disable) return
const { movex, out } = this.st
if (!out.value) return
out.value = false
movex.value = this.data.duration
? wx.worklet.timing(0, { duration: this.data.duration }, () => {})
: 0
hide() {
this.triggerEvent('hide', {}, {})
},

// 动画,从 wxs 迁移过来
// 用 this.st 来存滑动状态
initAnimate() {
// 左侧动画
this.applyAnimatedStyle('.weui-slideview__left', () => {
'worklet'
const { movex } = this.st
return {
transform: `translateX(${-movex.value}px)`
}
})

// 按钮动画
this.createSelectorQuery()
.selectAll('.btn')
.boundingClientRect((rects) => {
// 记录单个按钮最大值,总的最大值为所有按钮宽度的和
let total = 0
const buttons = []
for (let i = rects.length - 1; i >= 0; i--) {
total += rects[i].width
buttons[i] = total
}
this.st.buttons.value = buttons
this.st.max.value = total
if (this.data.show) this.st.movex.value = total

for (let index = rects.length - 1; index >= 0; index--) {
this.applyAnimatedStyle(`.btn-${index}`, () => {
'worklet'
const { movex, max, buttons } = this.st
const leftWidth = buttons.value[index]
const transformx = (movex.value * leftWidth) / max.value

return {
transform: `translateX(${-transformx}px)`
}
})
}
})
.exec()
},
touchstart(event) {
'worklet'

if (this.data.disable) return // disable的逻辑
const { startX, startY, firstAngle } = this.st
startX.value = event.touches[0].pageX
startY.value = event.touches[0].pageY
firstAngle.value = 0
},
touchmove(event) {
'worklet'
if (this.data.disable) return // disable的逻辑
const { startX, startY, firstAngle, isMoving, movex, max, out } = this.st
const pagex = event.touches[0].pageX - startX.value
const pagey = event.touches[0].pageY - startY.value
// 左侧45度角为界限,大于45度则允许水平滑动
if (firstAngle.value === 0) {
firstAngle.value = Math.abs(pagex) - Math.abs(pagey)
}
if (firstAngle.value < 0) {
return
}

isMoving.value = true
if (out.value) {
movex.value = Math.max(0, Math.min(max.value - pagex, max.value))
} else {
movex.value = Math.max(0, Math.min(-pagex, max.value))
}

return false // 禁止垂直方向的滑动
show() {
this.triggerEvent('show', {}, {})
},
touchend(event) {
'worklet'
if (this.data.disable) return // disable的逻辑
const { throttle } = this.data
const { startX, isMoving } = this.st
if (!isMoving.value) return

const pagex = event.changedTouches[0].pageX - startX.value

isMoving.value = false
if (Math.abs(pagex) < throttle || pagex > 0) {
this.hideButtons()
} else {
this.showButtons()
}
}
transitionEnd() {}
}
})
34 changes: 29 additions & 5 deletions src/components/slideview/slideview.wxml
Original file line number Diff line number Diff line change
@@ -1,21 +1,45 @@
<!-- slide-view/slide-view.wxml -->
<view class="weui-slideview weui-movable-view {{icon ? 'weui-slideview_icon' : ''}} ext-class" style="width: 100%;height: 100%;">
<view bindtouchstart="touchstart" bindtouchmove="touchmove" bindtouchend="touchend" class="weui-slideview__left left" style="width:100%;">
<wxs module="handler" src="./slideview.wxs"></wxs>
<view wx:if="{{renderer === 'webview'}}" class="weui-slideview weui-movable-view {{icon ? 'weui-slideview_icon' : ''}} ext-class" style="width: 100%;height: 100%;">
<view bindtransitionend="{{handler.transitionEnd}}"
show="{{show}}" change:show="{{handler.showChange}}"
rebounce="{{rebounce}}" change:rebounce="{{handler.rebounceChange}}"
duration="{{duration}}" change:duration="{{handler.durationChange}}"
change:disable="{{handler.disableChange}}" disable="{{disable}}"
change:prop="{{handler.sizeReady}}" prop="{{size}}"
bindtouchstart="{{handler.touchstart}}" bindtouchmove="{{handler.touchmove}}" bindtouchend="{{handler.touchend}}" class="weui-slideview__left left" style="width:100%;">
<slot></slot>
</view>
<view class="weui-slideview__right right">
<view class="weui-slideview__buttons" style="height:100%;width:100%;" wx:if="{{buttons && buttons.length}}">
<view wx:for="{{buttons}}" wx:key="index" class='btn weui-slideview__btn__wrp btn-{{index}} {{item.className}}'>
<view wx:for="{{buttons}}" wx:key="index" class='btn weui-slideview__btn__wrp {{item.className}}'>
<view
bind:tap="buttonTap"
bindtap="{{handler.hideButton}}"
data-data="{{item.data}}"
data-index="{{index}}"
class='weui-slideview__btn {{item.extClass}}'
aria-role="button"
>
<view wx:if="{{!icon}}">{{item.text}}</view>
<text wx:if="{{!icon}}">{{item.text}}</text>
<image class="weui-slideview__btn__icon" wx:else src="{{item.src}}"/>
</view>
</view>
</view>
</view>
</view>
<slideview-skyline
wx:elif="{{renderer === 'skyline'}}"
ext-class="ext-class"
buttons="{{buttons}}"
disable="{{disable}}"
duration="{{duration}}"
icon="{{icon}}"
show="{{show}}"
rebounce="{{rebounce}}"
throttle="{{throttle}}"
bind:buttontap="buttonTapByWxs"
bind:hide="hide"
bind:show="show"
>
<slot />
</slideview-skyline>
Loading

0 comments on commit 6de0191

Please sign in to comment.