Vue Component for creating fake scroll. Sometimes you only need to create scroll area without actually scrolling the content (fixed) and you use the scroll data to move another thing. This is what you need!
npm install --save vue-fake-scroll
or
yarn add vue-fake-scroll
import Vue from 'vue'
import VueFakeScroll from 'vue-fake-scroll'
Vue.component('vue-fake-scroll', VueFakeScroll)
<template>
...
</template>
<script>
import VueFakeScroll from 'vue-fake-scroll'
export default {
name: 'YourComponentName',
components: {
VueFakeScroll,
...
},
...
}
</script>
If you don't use webpack (for example in CodePen etc):
<link rel="stylesheet" href="node-modules/vue-fake-scroll/dist/vue-fake-scroll.css" />
<script src="node-modules/vue-fake-scroll/dist/vue-fake-scroll.umd.js"></script>
or use unpkg
<link rel="stylesheet" href="https://unpkg.com/vue-fake-scroll/dist/vue-fake-scroll.css" />
<script src="https://unpkg.com/vue-fake-scroll/dist/vue-fake-scroll.umd.js"></script>
and then you still need to register it:
Vue.component('vue-fake-scroll', VueFakeScroll)
You need to set up the virtual scroll area size.
For example: The scroll area needs to be 2000 x 3000 inside 100 x 200 window. You need to set property of VueFakeScroll :scroll-width="2000"
and :scroll-height="3000"
. You need also to resize the component to 100 x 200 with CSS.
<template>
<VueFakeScroll class="scroll" :scroll-width="2000" :scroll-height="3000">
...
</VueFakeScroll>
</template>
<style scoped>
.scroll {
width: 100px;
height: 200px;
}
</style>
So you need to get the scroll data, you can do it with listening the @update
event. The @update
event will fire when:
- The user scroll
scrollTop
orscrollLeft
of the element (not the component) changed programmatically- The
scrollWidth
orscrollHeight
of the component (not the element) changed by binding - The element changed size because of css (change in pixel, so if it's in percentage, if the parent change, it will change too). Size change detection using (vue-resize)[https://github.com/Akryum/vue-resize] component.
The object passed to the event contains these infos:
scrollLeft
: how far horizontal space scrolled in pixelscrollTop
: how far vertical space scrolled in pixelscrollWidth
: the total scrollable area widthscrollHeight
: the total scrollable area heightclientWidth
: the viewing window width (vertical scrollbar not included), could be smaller than the cssclientHeight
: the viewing window height (horizontal scrollbar not included), could be smaller than the cssscrollLeftMax
: the maximum value forscrollLeft
, it's calculated byscrollWidth - clientWidth
scrollTopMax
: the maximum value forscrollTop
, it's calculated byscrollHeight - clientHeight
scrollLeftInterval
: how far horizontal space scrolled in range from 0 to 1, it's calculated byscrollLeft / scrollLeftMax
scrollTopInterval
: how far vertical space scrolled in range from 0 to 1, it's calculated byscrollTop / scrollTopMax
Example:
<template>
<VueFakeScroll
:scroll-width="scrollWidth"
:scroll-height="scrollHeight"
:style="{width: width+'px', height: height+'px'}"
@update="handleUpdate">
{{scrollLeftInterval}} - {{scrollTopInterval}}
</VueFakeScroll>
</template>
<script>
import VueFakeScroll from 'vue-fake-scroll'
export default {
data() {
return {
scrollWidth: 2000,
scrollHeight: 3000,
width: 200,
height: 200,
scrollLeftInterval: 0,
scrollTopInterval: 0,
}
},
methods: {
handleUpdate(e) {
this.scrollLeftInterval = e.scrollLeftInterval
this.scrollTopInterval = e.scrollTopInterval
}
}
}
</script>
See the Demo and the corresponding code
You can style the component with the margin
and border
, but please don't style it with padding
, because it behaves a little bit different than regular div. If you need a padding
, just make a div
as a direct child of this component, and set the width
and height
to 100%
and then you can put the padding
in this div
.
Example:
<template>
<VueFakeScroll class="outer" :scroll-width="1000" :scroll-height="1000">
<div class="inner">
... another child here
</div>
</VueFakeScroll>
</template>
<style scoped>
.outer {
width: 400px;
height: 400px;
margin: 50px;
border: 10px;
}
.inner {
padding: 50px;
}
</style>