feat: 同步长江大学的风采墙优化
This commit is contained in:
Binary file not shown.
|
After Width: | Height: | Size: 714 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 72 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 249 KiB |
@@ -0,0 +1,152 @@
|
||||
|
||||
|
||||
Vue.component("spread-back-button", {
|
||||
template: `<div
|
||||
class="float-btn"
|
||||
:class="{ 'is-dragging': dragging }"
|
||||
:style="{ left: x + 'px', top: y + 'px' }"
|
||||
@mousedown="startDrag"
|
||||
@touchstart="startDrag"
|
||||
@click="handleClick"
|
||||
>
|
||||
<!-- 外发光 -->
|
||||
<div class="glow-ring"></div>
|
||||
|
||||
<!-- 点击涟漪 -->
|
||||
<span
|
||||
v-for="r in ripples"
|
||||
:key="r.id"
|
||||
class="ripple"
|
||||
:style="{ left: r.x + 'px', top: r.y + 'px' }"
|
||||
></span>
|
||||
|
||||
<!-- 图标 -->
|
||||
<div class="icon-wrap">
|
||||
<van-icon name="share-o" size="28" class="flip-icon" ></van-icon>
|
||||
</div>
|
||||
</div>`,
|
||||
props: {
|
||||
path: {
|
||||
type: String,
|
||||
default: '/platform/h5/home'
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
x: 20,
|
||||
y: 200,
|
||||
dragging: false,
|
||||
offsetX: 0,
|
||||
offsetY: 0,
|
||||
|
||||
startX: 0,
|
||||
startY: 0,
|
||||
moved: false,
|
||||
|
||||
ripples: [],
|
||||
rippleId: 0
|
||||
}
|
||||
},
|
||||
|
||||
mounted() {
|
||||
const pos = localStorage.getItem("float-btn-pos")
|
||||
if (pos) {
|
||||
const { x, y } = JSON.parse(pos)
|
||||
this.x = x
|
||||
this.y = y
|
||||
}
|
||||
|
||||
window.addEventListener("mousemove", this.onDrag)
|
||||
window.addEventListener("mouseup", this.endDrag)
|
||||
|
||||
window.addEventListener("touchmove", this.onDrag, { passive: false })
|
||||
window.addEventListener("touchend", this.endDrag)
|
||||
},
|
||||
|
||||
beforeDestroy() {
|
||||
window.removeEventListener("mousemove", this.onDrag)
|
||||
window.removeEventListener("mouseup", this.endDrag)
|
||||
|
||||
window.removeEventListener("touchmove", this.onDrag)
|
||||
window.removeEventListener("touchend", this.endDrag)
|
||||
},
|
||||
|
||||
methods: {
|
||||
startDrag(e) {
|
||||
const point = e.touches ? e.touches[0] : e
|
||||
|
||||
this.dragging = true
|
||||
this.moved = false
|
||||
|
||||
this.startX = point.clientX
|
||||
this.startY = point.clientY
|
||||
|
||||
this.offsetX = point.clientX - this.x
|
||||
this.offsetY = point.clientY - this.y
|
||||
},
|
||||
|
||||
onDrag(e) {
|
||||
if (!this.dragging) return
|
||||
|
||||
if (e.cancelable) e.preventDefault()
|
||||
|
||||
const point = e.touches ? e.touches[0] : e
|
||||
|
||||
let newX = point.clientX - this.offsetX
|
||||
let newY = point.clientY - this.offsetY
|
||||
|
||||
const btnSize = 54
|
||||
const maxX = window.innerWidth - btnSize
|
||||
const maxY = window.innerHeight - btnSize
|
||||
|
||||
this.x = Math.max(0, Math.min(newX, maxX))
|
||||
this.y = Math.max(0, Math.min(newY, maxY))
|
||||
|
||||
const dx = Math.abs(point.clientX - this.startX)
|
||||
const dy = Math.abs(point.clientY - this.startY)
|
||||
|
||||
if (dx > 5 || dy > 5) {
|
||||
this.moved = true
|
||||
}
|
||||
},
|
||||
|
||||
endDrag() {
|
||||
if (!this.dragging) return
|
||||
|
||||
this.dragging = false
|
||||
|
||||
localStorage.setItem(
|
||||
"float-btn-pos",
|
||||
JSON.stringify({
|
||||
x: this.x,
|
||||
y: this.y
|
||||
})
|
||||
)
|
||||
},
|
||||
|
||||
handleClick(e) {
|
||||
|
||||
if (this.moved) return
|
||||
|
||||
const point = e.changedTouches ? e.changedTouches[0] : e
|
||||
|
||||
const rect = this.$el.getBoundingClientRect()
|
||||
const id = this.rippleId++
|
||||
|
||||
this.ripples.push({
|
||||
id,
|
||||
x: point.clientX - rect.left,
|
||||
y: point.clientY - rect.top
|
||||
})
|
||||
|
||||
setTimeout(() => {
|
||||
this.ripples = this.ripples.filter(r => r.id !== id)
|
||||
}, 600)
|
||||
if (this.path === '-1') {
|
||||
window.history.back()
|
||||
} else {
|
||||
this.$pjaxReplace(this.path)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
Reference in New Issue
Block a user