效果如下图:


APIs
Scrollbar
参数 | 说明 | 类型 | 默认值 |
---|
contentClass | 内容 div 的类名 | string | undefined |
contentStyle | 内容 div 的样式 | CSSProperties | {} |
size | 滚动条的大小,单位 px | number | 5 |
trigger | 显示滚动条的时机,'none' 表示一直显示 | ‘hover’ | ‘none’ | ‘hover’ |
autoHide | 是否自动隐藏滚动条,仅当 trigger: 'hover' 时生效;为 true 时表示鼠标在滚动区域且不滚动时自动隐藏,滚动时自动显示;为 false 时表示鼠标在滚动区域时始终显示,无论是否在滚动 | boolean | true |
delay | 滚动条自动隐藏的延迟时间,单位 ms | number | 500 |
xScrollable | 是否使用横向滚动 | boolean | false |
yScrollable | 是否使用纵向滚动 | boolean | true |
xPlacement | 横向滚动时滚动条的位置 | ‘top’ | ‘bottom’ | ‘bottom’ |
yPlacement | 纵向滚动时滚动条的位置 | ‘left’ | ‘right’ | ‘right’ |
Slots
名称 | 说明 | 类型 |
---|
default | 自定义内容 | v-slot:default |
Methods
名称 | 说明 | 类型 |
---|
scrollTo | 滚动到指定坐标位置 | (options: { left?: number, top?: number, behavior?: ScrollBehavior })=> void | (x: number, y: number) => void |
scrollBy | 滚动一段特定距离 | (options: { left?: number, top?: number, behavior?: ScrollBehavior })=> void | (x: number, y: number) => void |
getScrollData | 获取滚动元素数据 | () => { scrollWidth: number, clientWidth: number, scrollHeight: number, clientHeight: number } |
ScrollBehavior Type
值 | 说明 |
---|
smooth | 平滑滚动并产生过渡效果 |
instant | 滚动会直接跳转到目标位置,没有过渡效果 |
auto | 或缺省值表示浏览器会自动选择滚动时的过渡效果 |
Events
名称 | 说明 | 类型 |
---|
scroll | 滚动的回调 | (e: Event, direction: ‘left’ | ‘right’ | ‘top’ | ‘bottom’) => void |
scrollend | 滚动结束的回调 | (e: Event, direction: ‘left’ | ‘right’ | ‘top’ | ‘bottom’) => void |
创建滚动条组件Scrollbar.vue
其中引入使用了以下工具函数:
<script setup lang="ts">
import { ref, computed, onMounted } from 'vue'
import type { CSSProperties } from 'vue'
import { debounce, useResizeObserver, useScroll } from 'components/utils'
export interface Props {
contentClass?: string
contentStyle?: CSSProperties
size?: number
trigger?: 'hover' | 'none'
autoHide?: boolean
delay?: number
xScrollable?: boolean
yScrollable?: boolean
xPlacement?: 'top' | 'bottom'
yPlacement?: 'left' | 'right'
}
const props = withDefaults(defineProps<Props>(), {
contentClass: undefined,
contentStyle: () => ({}),
size: 5,
trigger: 'hover',
autoHide: true,
delay: 500,
xScrollable: false,
yScrollable: true,
xPlacement: 'bottom',
yPlacement: 'right'
})
const containerRef = ref()
const contentRef = ref()
const railVerticalRef = ref()
const railHorizontalRef = ref()
const showYTrack = ref(false)
const showXTrack = ref(false)
const containerScrollHeight = ref(0)
const containerScrollWidth = ref(0)
const containerClientHeight = ref(0)
const containerClientWidth = ref(0)
const containerHeight = ref(0)
const containerWidth = ref(0)
const contentHeight = ref(0)
const contentWidth = ref(0)
const railHeight = ref(0)
const railWidth = ref(0)
const containerScrollTop = ref(0)
const containerScrollLeft = ref(0)
const mouseEnter = ref(false)
const trackYPressed = ref(false)
const trackXPressed = ref(false)
const mousePressedLeave = ref(false)
const memoYTop = ref<number>(0)
const memoXLeft = ref<number>(0)
const memoMouseY = ref<number>(0)
const memoMouseX = ref<number>(0)
const horizontalContentStyle = { width: 'fit-content' }
const yTrackHover = ref(false)
const xTrackHover = ref(false)
const emits = defineEmits(['scroll', 'scrollend'])
const autoShowTrack = computed(() => {
return props.trigger === 'hover' && props.autoHide
})
const notAutoShowTrack = computed(() => {
return props.trigger === 'hover' && !props.autoHide
})
const isYScroll = computed(() => {
return containerScrollHeight.value > containerClientHeight.value
})
const isXScroll = computed(() => {
return containerScrollWidth.value > containerClientWidth.value
})
const isScroll = computed(() => {
if (containerScrollHeight.value || containerScrollWidth.value) {
return (props.yScrollable && isYScroll.value) || (props.xScrollable && isXScroll.value)
}
return true
})
const trackHeight = computed(() => {
if (props.yScrollable && isYScroll.value) {
if (containerHeight.value && contentHeight.value && railHeight.value) {
const value = Math.min(
containerHeight.value,
(railHeight.value * containerHeight.value) / contentHeight.value + 1.5 * props.size
)
return Number(value.toFixed(4))
}
}
return 0
})
const trackTop = computed(() => {
if (containerHeight.value && contentHeight.value && railHeight.value) {
return (
(containerScrollTop.value / (contentHeight.value - containerHeight.value)) *
(railHeight.value - trackHeight.value)
)
}
return 0
})
const verticalTrackStyle = computed(() => {
return {
top: `${trackTop.value}px`,
height: `${trackHeight.value}px`
}
})
const trackWidth = computed(() => {
if (props.xScrollable && isXScroll.value) {
if (containerWidth.value && contentWidth.value && railWidth.value) {
const value = (railWidth.value * containerWidth.value) / contentWidth.value + 1.5 * props.size
return Number(value.toFixed(4))
}
}
return 0
})
const trackLeft = computed(() => {
if (containerWidth.value && contentWidth.value && railWidth.value) {
return (
(containerScrollLeft.value / (contentWidth.value - containerWidth.value)) * (railWidth.value - trackWidth.value)
)
}
return 0
})
const horizontalTrackStyle = computed(() => {
return {
left: `${trackLeft.value}px`,
width: `${trackWidth.value}px`
}
})
onMounted(() => {
updateState()
})
const {
left: scrollingLeft,
right: scrollingRight,
top: scrollingTop,
bottom: scrollingBottom
} = useScroll(containerRef)
useResizeObserver([containerRef, contentRef], updateState)
function updateScrollState(): void {
containerScrollTop.value = containerRef.value.scrollTop
containerScrollLeft.value = containerRef.value.scrollLeft
}
function updateScrollbarState(): void {
containerScrollHeight.value = containerRef.value.scrollHeight
containerScrollWidth.value = containerRef.value.scrollWidth
containerClientHeight.value = containerRef.value.clientHeight
containerClientWidth.value = containerRef.value.clientWidth
containerHeight.value = containerRef.value.offsetHeight
containerWidth.value = containerRef.value.offsetWidth
contentHeight.value = contentRef.value.offsetHeight
contentWidth.value = contentRef.value.offsetWidth
railHeight.value = railVerticalRef.value.offsetHeight
railWidth.value = railHorizontalRef.value.offsetWidth
}
function updateState(): void {
updateScrollState()
updateScrollbarState()
}
const debounceYScrollEnd = debounce(yScrollEnd, 100)
const debounceXScrollEnd = debounce(xScrollEnd, 100)
const debounceHideYScrollbar = debounce(hideYScrollbar, 100 + props.delay)
const debounceHideXScrollbar = debounce(hideXScrollbar, 100 + props.delay)
function yScrollEnd(e: Event, direction: 'left' | 'right' | 'top' | 'bottom'): void {
emits('scrollend', e, direction)
}
function xScrollEnd(e: Event, direction: 'left' | 'right' | 'top' | 'bottom'): void {
emits('scrollend', e, direction)
}
function hideYScrollbar(): void {
if (autoShowTrack.value && !yTrackHover.value) {
showYTrack.value = false
}
if (notAutoShowTrack.value && !mouseEnter.value) {
showYTrack.value = false
}
}
function hideXScrollbar(): void {
if (autoShowTrack.value && !xTrackHover.value) {
showXTrack.value = false
}
if (notAutoShowTrack.value && !mouseEnter.value) {
showXTrack.value = false
}
}
function onScroll(e: Event): void {
if (scrollingLeft.value || scrollingRight.value) {
let direction: string = ''
if (scrollingLeft.value) {
direction = 'left'
}
if (scrollingRight.value) {
direction = 'right'
}
emits('scroll', e, direction)
if (autoShowTrack.value) {
showXTrack.value = true
if (!trackXPressed.value) {
debounceXScrollEnd(e, direction)
debounceHideXScrollbar()
}
}
}
if (scrollingTop.value || scrollingBottom.value) {
let direction: string = ''
if (scrollingTop.value) {
direction = 'top'
}
if (scrollingBottom.value) {
direction = 'bottom'
}
emits('scroll', e, direction)
if (autoShowTrack.value) {
showYTrack.value = true
if (!trackYPressed.value) {
debounceYScrollEnd(e, direction)
debounceHideYScrollbar()
}
}
}
updateScrollState()
}
function onMouseEnter(): void {
mouseEnter.value = true
if (trackXPressed.value || trackYPressed.value) {
mousePressedLeave.value = false
} else {
if (!autoShowTrack.value) {
showXTrack.value = true
showYTrack.value = true
}
}
}
function onMouseLeave(): void {
mouseEnter.value = false
if (trackXPressed.value || trackYPressed.value) {
mousePressedLeave.value = true
} else {
if (!autoShowTrack.value) {
if (showXTrack.value) {
debounceHideXScrollbar()
}
if (showYTrack.value) {
debounceHideYScrollbar()
}
}
}
}
function onEnterYTrack(): void {
yTrackHover.value = true
}
function onLeaveYTrack(): void {
yTrackHover.value = false
if (autoShowTrack.value && !trackYPressed.value) {
debounceHideYScrollbar()
}
}
function onEnterXTrack(): void {
xTrackHover.value = true
}
function onLeaveXTrack(): void {
xTrackHover.value = false
if (autoShowTrack.value && !trackXPressed.value) {
debounceHideXScrollbar()
}
}
function handleYTrackMouseDown(e: MouseEvent): void {
trackYPressed.value = true
memoYTop.value = containerScrollTop.value
memoMouseY.value = e.clientY
document.addEventListener('mousemove', handleYTrackMouseMove)
document.addEventListener('mouseup', handleYTrackMouseUp)
handleYTrackMouseMove(e)
}
function handleYTrackMouseMove(e: MouseEvent): void {
const diffY = e.clientY - memoMouseY.value
const dScrollTop =
(diffY * (contentHeight.value - containerHeight.value)) / (containerHeight.value - trackHeight.value)
const toScrollTopUpperBound = contentHeight.value - containerHeight.value
let toScrollTop = memoYTop.value + dScrollTop
toScrollTop = Math.min(toScrollTopUpperBound, toScrollTop)
toScrollTop = Math.max(toScrollTop, 0)
containerRef.value.scrollTop = toScrollTop
}
function handleYTrackMouseUp(): void {
trackYPressed.value = false
if (autoShowTrack.value && !yTrackHover.value) {
debounceHideYScrollbar()
} else if (notAutoShowTrack.value && mousePressedLeave.value) {
mousePressedLeave.value = false
debounceHideYScrollbar()
}
document.removeEventListener('mousemove', handleYTrackMouseMove)
document.removeEventListener('mouseup', handleYTrackMouseUp)
}
function handleXTrackMouseDown(e: MouseEvent): void {
trackXPressed.value = true
memoXLeft.value = containerScrollLeft.value
memoMouseX.value = e.clientX
document.addEventListener('mousemove', handleXTrackMouseMove)
document.addEventListener('mouseup', handleXTrackMouseUp)
handleXTrackMouseMove(e)
}
function handleXTrackMouseMove(e: MouseEvent): void {
const diffX = e.clientX - memoMouseX.value
const dScrollLeft = (diffX * (contentWidth.value - containerWidth.value)) / (containerWidth.value - trackWidth.value)
const toScrollLeftUpperBound = contentWidth.value - containerWidth.value
let toScrollLeft = memoXLeft.value + dScrollLeft
toScrollLeft = Math.min(toScrollLeftUpperBound, toScrollLeft)
toScrollLeft = Math.max(toScrollLeft, 0)
containerRef.value.scrollLeft = toScrollLeft
}
function handleXTrackMouseUp(): void {
trackXPressed.value = false
if (autoShowTrack.value && !xTrackHover.value) {
debounceHideXScrollbar()
} else if (notAutoShowTrack.value && mousePressedLeave.value) {
mousePressedLeave.value = false
debounceHideXScrollbar()
}
document.removeEventListener('mousemove', handleXTrackMouseMove)
document.removeEventListener('mouseup', handleXTrackMouseUp)
}
function scrollTo(...args: any[]): void {
containerRef.value?.scrollTo(...args)
}
function scrollBy(...args: any[]): void {
containerRef.value?.scrollBy(...args)
}
function getScrollData(): object {
return {
scrollTop: containerScrollTop.value,
scrollWidth: containerScrollWidth.value,
scrollHeight: containerScrollHeight.value,
clientWidth: containerClientWidth.value,
clientHeight: containerClientHeight.value
}
}
defineExpose({
scrollTo,
scrollBy,
getScrollData
})
</script>
<template>
<div
class="m-scrollbar"
:style="`
--scrollbar-width: ${size}px;
--scrollbar-height: ${size}px;
--scrollbar-border-radius: ${size}px;
--scrollbar-color: rgba(0, 0, 0, 0.25);
--scrollbar-color-hover: rgba(0, 0, 0, 0.4);
--scrollbar-rail-horizontal-top: 4px 2px auto 2px;
--scrollbar-rail-horizontal-bottom: auto 2px 4px 2px;
--scrollbar-rail-vertical-right: 2px 4px 2px auto;
--scrollbar-rail-vertical-left: 2px auto 2px 4px;
--scrollbar-rail-color: transparent;
`"
@mouseenter="isScroll && trigger === 'hover' ? onMouseEnter() : () => false"
@mouseleave="isScroll && trigger === 'hover' ? onMouseLeave() : () => false"
>
<div ref="containerRef" class="scrollbar-container" :class="{ 'container-scroll': isScroll }" @scroll="onScroll">
<div
ref="contentRef"
class="scrollbar-content"
:class="contentClass"
:style="[xScrollable ? { ...horizontalContentStyle, ...contentStyle } : contentStyle]"
>
<slot></slot>
</div>
</div>
<div
v-show="yScrollable"
ref="railVerticalRef"
class="scrollbar-rail rail-vertical"
:class="`rail-vertical-${yPlacement}`"
>
<div
class="scrollbar-track"
:class="{ 'track-visible': trigger === 'none' || showYTrack }"
:style="verticalTrackStyle"
@mouseenter="autoShowTrack ? onEnterYTrack() : () => false"
@mouseleave="autoShowTrack ? onLeaveYTrack() : () => false"
@mousedown.prevent.stop="handleYTrackMouseDown"
></div>
</div>
<div
v-show="xScrollable"
ref="railHorizontalRef"
class="scrollbar-rail rail-horizontal"
:class="`rail-horizontal-${xPlacement}`"
>
<div
class="scrollbar-track"
:class="{ 'track-visible': trigger === 'none' || showXTrack }"
:style="horizontalTrackStyle"
@mouseenter="autoShowTrack ? onEnterXTrack() : () => false"
@mouseleave="autoShowTrack ? onLeaveXTrack() : () => false"
@mousedown.prevent.stop="handleXTrackMouseDown"
></div>
</div>
</div>
</template>
<style lang="less" scoped>
.m-scrollbar {
overflow: hidden;
position: relative;
z-index: auto;
height: 100%;
width: 100%;
.scrollbar-container {
width: 100%;
height: 100%;
min-height: inherit;
max-height: inherit;
scrollbar-width: none;
&::-webkit-scrollbar,
&::-webkit-scrollbar-track-piece,
&::-webkit-scrollbar-thumb {
width: 0;
height: 0;
display: none;
}
.scrollbar-content {
box-sizing: border-box;
min-width: 100%;
}
}
.container-scroll {
overflow: scroll;
}
.scrollbar-rail {
position: absolute;
pointer-events: none;
user-select: none;
background: var(--scrollbar-rail-color);
-webkit-user-select: none;
.scrollbar-track {
z-index: 9;
position: absolute;
cursor: pointer;
opacity: 0;
pointer-events: none;
background-color: var(--scrollbar-color);
transition:
background-color 0.2s cubic-bezier(0.4, 0, 0.2, 1),
opacity 0.3s cubic-bezier(0.4, 0, 0.2, 1);
&:hover {
background-color: var(--scrollbar-color-hover);
}
}
.track-visible {
opacity: 1;
pointer-events: all;
}
}
.rail-vertical {
width: var(--scrollbar-width);
.scrollbar-track {
width: var(--scrollbar-width);
border-radius: var(--scrollbar-border-radius);
bottom: 0;
}
}
.rail-vertical-left {
inset: var(--scrollbar-rail-vertical-left);
}
.rail-vertical-right {
inset: var(--scrollbar-rail-vertical-right);
}
.rail-horizontal {
height: var(--scrollbar-height);
.scrollbar-track {
height: var(--scrollbar-height);
border-radius: var(--scrollbar-border-radius);
right: 0;
}
}
.rail-horizontal-top {
inset: var(--scrollbar-rail-horizontal-top);
}
.rail-horizontal-bottom {
inset: var(--scrollbar-rail-horizontal-bottom);
}
.scrollbar-thumb {
position: absolute;
background-color: rgba(0, 0, 0, 0.5);
transition: background-color 0.2s cubic-bezier(0.4, 0, 0.2, 1);
}
}
</style>
在要使用的页面引入
其中引入使用了以下组件:
<script setup lang="ts">
import Scrollbar from './Scrollbar.vue'
function onScroll(e: Event, direction: 'left' | 'right' | 'top' | 'bottom') {
console.log('scroll', e, direction)
}
function onScrollEnd(e: Event, direction: 'left' | 'right' | 'top' | 'bottom') {
console.log('scrollend', e, direction)
}
</script>
<template>
<div>
<h1>{{ $route.name }} {{ $route.meta.title }}</h1>
<h2 class="mt30 mb10">基本使用</h2>
<Scrollbar style="max-height: 120px" @scroll="onScroll" @scrollend="onScrollEnd">
我们在田野上面找猪<br />
想象中已找到了三只<br />
小鸟在白云上面追逐<br />
它们在树底下跳舞<br />
啦啦啦啦啦啦啦啦咧<br />
啦啦啦啦咧<br />
我们在想象中度过了许多年<br />
想象中我们是如此的疯狂<br />
我们在城市里面找猪<br />
想象中已找到了几百万只<br />
小鸟在公园里面唱歌<br />
它们独自在想象里跳舞<br />
啦啦啦啦啦啦啦啦咧<br />
啦啦啦啦咧<br />
我们在想象中度过了许多年<br />
许多年之后我们又开始想象<br />
啦啦啦啦啦啦啦啦咧
</Scrollbar>
<h2 class="mt30 mb10">横向滚动</h2>
<Scrollbar x-scrollable @scroll="onScroll" @scrollend="onScrollEnd">
<div style="white-space: nowrap; padding: 12px">
我们在田野上面找猪 想象中已找到了三只 小鸟在白云上面追逐 它们在树底下跳舞 啦啦啦啦啦啦啦啦咧 啦啦啦啦咧
我们在想象中度过了许多年 想象中我们是如此的疯狂 我们在城市里面找猪 想象中已找到了几百万只 小鸟在公园里面唱歌
它们独自在想象里跳舞 啦啦啦啦啦啦啦啦咧 啦啦啦啦咧 我们在想象中度过了许多年 许多年之后我们又开始想象
啦啦啦啦啦啦啦啦咧
</div>
</Scrollbar>
<h2 class="mt30 mb10">垂直及横向滚动</h2>
<Scrollbar style="max-height: 120px" x-scrollable @scroll="onScroll" @scrollend="onScrollEnd">
<div style="white-space: nowrap; padding-right: 12px" v-for="n in 9" :key="n">
我们在田野上面找猪 想象中已找到了三只 小鸟在白云上面追逐 它们在树底下跳舞 啦啦啦啦啦啦啦啦咧 啦啦啦啦咧
我们在想象中度过了许多年 想象中我们是如此的疯狂 我们在城市里面找猪 想象中已找到了几百万只 小鸟在公园里面唱歌
它们独自在想象里跳舞 啦啦啦啦啦啦啦啦咧 啦啦啦啦咧 我们在想象中度过了许多年 许多年之后我们又开始想象
啦啦啦啦啦啦啦啦咧
</div>
<div style="white-space: nowrap; padding-bottom: 12px">
我们在田野上面找猪 想象中已找到了三只 小鸟在白云上面追逐 它们在树底下跳舞 啦啦啦啦啦啦啦啦咧 啦啦啦啦咧
我们在想象中度过了许多年 想象中我们是如此的疯狂 我们在城市里面找猪 想象中已找到了几百万只 小鸟在公园里面唱歌
它们独自在想象里跳舞 啦啦啦啦啦啦啦啦咧 啦啦啦啦咧 我们在想象中度过了许多年 许多年之后我们又开始想象
啦啦啦啦啦啦啦啦咧
</div>
</Scrollbar>
<h2 class="mt30 mb10">触发方式</h2>
<Scrollbar style="max-height: 120px" trigger="none">
我们在田野上面找猪<br />
想象中已找到了三只<br />
小鸟在白云上面追逐<br />
它们在树底下跳舞<br />
啦啦啦啦啦啦啦啦咧<br />
啦啦啦啦咧<br />
我们在想象中度过了许多年<br />
想象中我们是如此的疯狂<br />
我们在城市里面找猪<br />
想象中已找到了几百万只<br />
小鸟在公园里面唱歌<br />
它们独自在想象里跳舞<br />
啦啦啦啦啦啦啦啦咧<br />
啦啦啦啦咧<br />
我们在想象中度过了许多年<br />
许多年之后我们又开始想象<br />
啦啦啦啦啦啦啦啦咧
</Scrollbar>
<h2 class="mt30 mb10">鼠标在滚动区域时不自动隐藏</h2>
<Scrollbar style="max-height: 120px" :auto-hide="false" :delay="1000">
我们在田野上面找猪<br />
想象中已找到了三只<br />
小鸟在白云上面追逐<br />
它们在树底下跳舞<br />
啦啦啦啦啦啦啦啦咧<br />
啦啦啦啦咧<br />
我们在想象中度过了许多年<br />
想象中我们是如此的疯狂<br />
我们在城市里面找猪<br />
想象中已找到了几百万只<br />
小鸟在公园里面唱歌<br />
它们独自在想象里跳舞<br />
啦啦啦啦啦啦啦啦咧<br />
啦啦啦啦咧<br />
我们在想象中度过了许多年<br />
许多年之后我们又开始想象<br />
啦啦啦啦啦啦啦啦咧
</Scrollbar>
<h2 class="mt30 mb10">自定义样式</h2>
<h3 class="mb10">可通过设置 size 属性,自定义相关 --scrollbar 变量进行各种样式自定义</h3>
<Scrollbar
style="
max-height: 120px;
border-radius: 12px;
--scrollbar-color: rgba(0, 0, 0, 0.45);
--scrollbar-color-hover: rgba(0, 0, 0, 0.65);
--scrollbar-rail-vertical-right: 2px 6px 2px auto;
"
:size="8"
:content-style="{ backgroundColor: '#e6f4ff', padding: '16px 24px', fontSize: '16px' }"
>
我们在田野上面找猪<br />
想象中已找到了三只<br />
小鸟在白云上面追逐<br />
它们在树底下跳舞<br />
啦啦啦啦啦啦啦啦咧<br />
啦啦啦啦咧<br />
我们在想象中度过了许多年<br />
想象中我们是如此的疯狂<br />
我们在城市里面找猪<br />
想象中已找到了几百万只<br />
小鸟在公园里面唱歌<br />
它们独自在想象里跳舞<br />
啦啦啦啦啦啦啦啦咧<br />
啦啦啦啦咧<br />
我们在想象中度过了许多年<br />
许多年之后我们又开始想象<br />
啦啦啦啦啦啦啦啦咧
</Scrollbar>
<h2 class="mt30 mb10">滚动条位置</h2>
<Flex vertical>
<Scrollbar style="max-height: 120px; padding-left: 12px" y-placement="left">
我们在田野上面找猪<br />
想象中已找到了三只<br />
小鸟在白云上面追逐<br />
它们在树底下跳舞<br />
啦啦啦啦啦啦啦啦咧<br />
啦啦啦啦咧<br />
我们在想象中度过了许多年<br />
想象中我们是如此的疯狂<br />
我们在城市里面找猪<br />
想象中已找到了几百万只<br />
小鸟在公园里面唱歌<br />
它们独自在想象里跳舞<br />
啦啦啦啦啦啦啦啦咧<br />
啦啦啦啦咧<br />
我们在想象中度过了许多年<br />
许多年之后我们又开始想象<br />
啦啦啦啦啦啦啦啦咧
</Scrollbar>
<Scrollbar x-scrollable x-placement="top">
<div style="white-space: nowrap; padding: 12px">
我们在田野上面找猪 想象中已找到了三只 小鸟在白云上面追逐 它们在树底下跳舞 啦啦啦啦啦啦啦啦咧 啦啦啦啦咧
我们在想象中度过了许多年 想象中我们是如此的疯狂 我们在城市里面找猪 想象中已找到了几百万只 小鸟在公园里面唱歌
它们独自在想象里跳舞 啦啦啦啦啦啦啦啦咧 啦啦啦啦咧 我们在想象中度过了许多年 许多年之后我们又开始想象
啦啦啦啦啦啦啦啦咧
</div>
</Scrollbar>
</Flex>
</div>
</template>