设计目标
起初我们希望得到一个把任意内容放进去后,如果内容溢出高度,那么就自行开始垂直滚动。最好在容器高度发生变化后依旧可以重新获取高度而不影响滚动。
实现原理
主要原理就是通过初始化2块dom,然后上下依次排布,然后利用css的transform
属性更新位置,利用requestAnimationFrame
方法进行实时更新动画。
灵魂画师上线了。
演示地址
tiger.happykit.org/#/demo/roll…
完成代码
happyboot-tiger/HbAdminRollArea.vue at master · pumelotea/happyboot-tiger (github.com)
<script setup>
import { onBeforeUnmount, onMounted, ref } from 'vue'
const props = defineProps({
speed: {
type : Number,
default: 1000
},
direction: {
type : String,
default: 'up'
}
})
const box = ref(null)
const refRoll1 = ref(null)
const refRoll2 = ref(null)
let top = 0
let height = 0
let shadowHeight = 0
const sp = props.speed / 1000
let end = false
let isMouseHover = false
function refresh () {
height = refRoll1.value.clientHeight
shadowHeight = refRoll2.value.clientHeight
if (shadowHeight !== height) {
refRoll2.value.innerHTML = refRoll1.value.innerHTML
}
if (top < 0) {
if (Math.abs(top) >= height) {
const tmp = refRoll1.value
refRoll1.value = refRoll2.value
refRoll2.value = tmp
top = 0
}
refRoll1.value.style.transform = `translate3d(0,${top}px,0)`
refRoll2.value.style.transform = `translate3d(0,${height + top}px,0)`
} else {
if (Math.abs(top) >= height) {
const tmp = refRoll1.value
refRoll1.value = refRoll2.value
refRoll2.value = tmp
top = -height
}
refRoll1.value.style.transform = `translate3d(0,${top}px,0)`
refRoll2.value.style.transform = `translate3d(0,${top - height}px,0)`
}
}
function doAnimationFrame () {
requestAnimationFrame(() => {
if (end) {
return
}
if (isMouseHover) {
refresh()
doAnimationFrame()
return
}
if (height > box.value.clientHeight) {
if (props.direction === 'down') {
top += sp
}
if (props.direction === 'up') {
top -= sp
}
} else {
top = 0
}
refresh()
doAnimationFrame()
})
}
function onMouseEnter () {
isMouseHover = true
}
function onMouseLeaver () {
isMouseHover = false
}
onMounted(doAnimationFrame)
onBeforeUnmount(() => {
end = true
})
</script>
<template>
<div
ref="box"
class="hb-admin-roll-list-com"
@mouseenter="onMouseEnter"
@mouseleave="onMouseLeaver"
>
<div
ref="refRoll1"
class="roll-item"
>
<div class="list-item">
<slot />
</div>
</div>
<div
ref="refRoll2"
class="roll-item"
/>
</div>
</template>
<style scoped>
.hb-admin-roll-list-com{
width: 100%;
height: 100%;
overflow: hidden;
position: relative;
}
.hb-admin-roll-list-com::-webkit-scrollbar{
display: none;
}
.roll-item{
width: 100%;
position: absolute;
}
.list-item{
}
</style>
小结
可能还存在问题,往兄弟们指出,共同进步。