Vue Isolated Scroll directive
by ChangJoo Park
HTML
<script src="https://unpkg.com/[email protected]/dist/vue.js"></script>
<div id="app">
<div>
<div
class="content-wrapper"
v-isolated-scroll
>
<h1>Hello</h1>
<h1>Hello</h1>
</div>
<div
class="content-wrapper"
v-isolated-scroll="{ isolateX: false, isolateY: true }"
>
<h1>Hello</h1>
<h1>Hello</h1>
<h1>Hello</h1>
<h1>Hello</h1>
<h1>Hello</h1>
<h1>Hello</h1>
<h1>Hello</h1>
<h1>Hello</h1>
</div>
</div>
</div>
CSS
#app {
width: 100vw;
height: 100vh;
}
.content-wrapper {
width: 200px;
height: 200px;
margin-top: 100px;
margin-left: auto;
margin-right: auto;
background-color: tomato;
overflow-x: auto;
overflow-y: auto;
}
JavaScript
Vue.directive('isolated-scroll', {
bind: function (el, binding, vnode) {
var defaultOptions = {
whenOnlyHasScrollbar: false,
isolateX: true,
isolateY: true
};
var options = binding.value || defaultOptions;
// TODO: 없는 옵션 채우기
Object.keys(defaultOptions).forEach(function(option) {
if (!options.hasOwnProperty(option)) {
options[option] = defaultOptions[option];
}
});
console.log('최종 옵션 : ', options)
el.addEventListener('wheel', function (event) {
var scrollWidth = el.scrollWidth;
var scrollHeight = el.scrollHeight;
var clientWidth = el.clientWidth;
var clientHeight = el.clientHeight;
var hasScrollX = scrollWidth !== clientWidth;
var hasScrollY = scrollHeight !== clientHeight;
if (options.whenOnlyHasScrollbar && (!hasScrollX || !hasScrollY)) {
return;
}
var isHorizontalScroll = event.deltaX !== 0
var isVerticalScroll = event.deltaY !== 0;
var isIsolatedScroll = false;
// TODO: 기본 옵션에 따른 작동 정하기
// TODO: 좌우 스크롤 막기
if (isHorizontalScroll && options.isolateX) {
var scrollLeft = el.scrollLeft;
var meetLeft = scrollLeft === 0;
var meetRight = (scrollWidth - clientWidth) === scrollLeft;
var isLeft = event.deltaX < 0;
isIsolatedScroll = (meetLeft && isLeft) || (meetRight && !isLeft);
console.log(isIsolatedScroll)
}
if (isVerticalScroll && options.isolateY) {
var scrollTop = el.scrollTop;
var meetTop = scrollTop === 0;
var meetBottom = (scrollHeight - clientHeight) === scrollTop;
var isUpward = event.deltaY < 0;
isIsolatedScroll = (meetBottom && !isUpward) || (meetTop && isUpward);
}
if (isIsolatedScroll) {
event.preventDefault();
event.stopPropagation();
}
})
},
unbind: function (el, binding, vnode) {
el.removeEventListener('wheel', function () {
...