参照element-ui的el-scroll自己实现了一个自定义组件,代码如下:
<template>
<div class="c-scroll-box" ref="scrollBox" unselectable="on" onselectstart="return false;" style="-moz-user-select:none;">
<div class="c-scroll-container" @scroll="containerScroll" ref="scrollContainer">
<div class="c-scroll-view" ref="scrollViewBox">
<slot></slot>
</div>
</div>
<!-- 右侧滚动条 -->
<div class="c-scroll-vertical-box c-scroll-bar" :style="verticalStyle" ref="verticalBox" @mousedown="vBoxDown"></div>
<!-- 下方滚动条 -->
<!-- <div class="c-scroll-horizontal-box c-scroll-bar" :style="horizontalStyle" ref="horizontalBox"></div> -->
</div>
</template>
<script>
import { domResize } from "./domResize.js";
export default {
data() {
return {
verticalStyle: {
height: "60px",
top: 0,
transform: 'translateY(0)'
},
horizontalStyle: {
width: "10px",
left: 0
},
viewHeight: 0,
viewWidth: 0,
vBarPageY: 0,
vBarTranslateY: 0,
hBarPageX: 0,
vMouseFlag: false
};
},
watch: {},
mounted() {
this.domResizeListener();
},
methods: {
/**
* @name vBoxDown
* @description 竖直滚动条鼠标按下
* @author cjs1992
* @date 2018-10-25 13:57
*/
vBoxDown(event) {
document.removeEventListener("mousemove", this.vBoxMove);
document.removeEventListener("mouseup", this.vBoxUp);
this.vBarPageY = event.pageY;
this.vMouseFlag = true;
document.addEventListener("mousemove", this.vBoxMove);
document.addEventListener("mouseup", this.vBoxUp);
},
/**
* @name vBoxUp
* @description 竖直滚动条鼠标放开
* @author cjs1992
* @date 2018-10-25 13:57
*/
vBoxUp(event) {
event.preventDefault();
event.stopPropagation()
this.vMouseFlag = false;
},
/**
* @name vBoxMove
* @description 竖直滚动条鼠标移动
* @author cjs1992
* @date 2018-10-25 13:57
*/
vBoxMove(event) {
if (!this.vMouseFlag) {
return;
}
let scrollBox = this.$refs.scrollBox;
let verticalBox = this.$refs.verticalBox;
let scrollContainer = this.$refs.scrollContainer;
let scrollViewBox = this.$refs.scrollViewBox;
let num = event.pageY - this.vBarPageY;
this.vBarPageY = event.pageY;
// let t_top = parseFloat(this.verticalStyle.top) + num;
/**>>>> */
let t_top = parseFloat(this.vBarTranslateY) + num;
let max_top =
scrollBox.clientHeight - parseFloat(this.verticalStyle.height);
// 判断是否超出滚动范围
if (t_top <= 0) {
t_top = 0;
} else if (max_top <= t_top) {
t_top = max_top;
}
// this.verticalStyle.top = t_top + "px";
/**>>>>>> */
this.verticalStyle.transform = "translateY(" + t_top + "px)";
this.vBarTranslateY = t_top;
if (scrollContainer.scrollTo) {
scrollContainer.scrollTo(
this.horizontalStyle.left,
(t_top * scrollViewBox.clientHeight) / scrollBox.clientHeight
);
} else {
scrollContainer.scrollTop = (t_top * scrollViewBox.clientHeight) / scrollBox.clientHeight;
}
},
/**
* @name containerScroll
* @description scroll
*/
containerScroll() {
let scrollContainer = this.$refs.scrollContainer;
let scrollBox = this.$refs.scrollBox;
let scrollViewBox = this.$refs.scrollViewBox;
// this.verticalStyle.top =
// (scrollBox.clientHeight * scrollContainer.scrollTop) /
// scrollViewBox.clientHeight +
// "px";
/**>>>>>> */
this.verticalStyle.transform = "translateY(" + (scrollBox.clientHeight * scrollContainer.scrollTop) / scrollViewBox.clientHeight + "px)";
this.vBarTranslateY = (scrollBox.clientHeight * scrollContainer.scrollTop) / scrollViewBox.clientHeight;
},
/**
* @name setBarHeight
* @description 获取滚动条高度
* @author cjs1992
* @date 2018-10-25 10:56
*/
setBarHeight() {
let scrollBox = this.$refs.scrollBox;
let scrollViewBox = this.$refs.scrollViewBox;
let scrollContainer = this.$refs.scrollContainer;
// 滚动条的高度
let rate = scrollBox.clientHeight / scrollViewBox.clientHeight;
if (rate >= 1) {
this.verticalStyle.height = 0;
} else {
this.verticalStyle.height = scrollBox.clientHeight * rate + "px";
// 计算滚动条的位置
// this.verticalStyle.top =
// (scrollBox.clientHeight * scrollContainer.scrollTop) /
// scrollViewBox.clientHeight +
// "px";
/**>>>>>> */
this.verticalStyle.transform = "translateY(" + (scrollBox.clientHeight * scrollContainer.scrollTop) / scrollViewBox.clientHeight + "px)";
this.vBarTranslateY = (scrollBox.clientHeight * scrollContainer.scrollTop) / scrollViewBox.clientHeight;
}
},
/**
* @name domResizeListener
* @description dom元素的resize方法
* @author cjs1992
* @date 2018-10-25 11:34
* */
domResizeListener() {
domResize(this.$refs.scrollViewBox, ele => {
if (ele) {
let { contentRect: cont } = ele;
if (cont.height !== this.viewHeight) {
this.viewHeight = cont.height;
this.verticalBarChange();
} else if (cont.width !== this.viewWidth) {
}
}
});
},
/**
* @name verticalVBarChange
* @description 右侧滚动条变化事件
*/
verticalBarChange() {
this.setBarHeight();
},
/**
* @name horizontalBarChange
* @description 底部滚动条变化事件
*/
horizontalBarChange() {
console.log(this.viewWidth);
}
}
};
</script>
<style scoped>
.c-scroll-box {
/* width: 100%; */
height: 100%;
overflow: hidden;
box-sizing: border-box;
position: relative;
}
.c-scroll-container {
/* width: 100%; */ /*请注意,这里不能width: 100%;如果需要设置margin-right: -17px的话*/
height: 100%;
margin-right: -17px;
margin-bottom: -17px;
margin-top: 0;
overflow: scroll;
overflow-x: hidden;
}
.c-scroll-view {
width: 100%;
}
.c-scroll-bar {
position: absolute;
border-radius: 5px;
z-index: 1;
background: #70ad47;
}
/* 竖直滚动条 */
div.c-scroll-vertical-box {
width: 10px;
right: 2px;
}
div.c-scroll-horizontal-box {
height: 10px;
}
</style>
domResize.js 如下:
import ResizeObserver from 'resize-observer-polyfill'; const listeners = (entries) => { for (let item of entries) { if (item.target && item.target.resizeListeners && item.target.resizeListeners.length) { for (let func of item.target.resizeListeners) { func(item); } } } } export const domResize = (ele, func) => { if (!ele.resizeListeners) { ele.resizeListeners = []; const myObserver = new ResizeObserver(listeners); myObserver.observe(ele); } ele.resizeListeners.push(func); }
这里的domResize.js是element官方实现的,目的是为了监测一个容器大小发生变化,其实还在网上找到了另一种实现思路(也可以实现监听容器尺寸发生变化),代码如下:
/** * Created by taozh on 2017/5/6. * taozh1982@gmail.com */ var EleResize = { _handleResize: function (e) { var ele = e.target || e.srcElement; var trigger = ele.__resizeTrigger__; if (trigger) { var handlers = trigger.__z_resizeListeners; if (handlers) { var size = handlers.length; for (var i = 0; i < size; i++) { var h = handlers[i]; var handler = h.handler; var context = h.context; handler.apply(context, [e]); } } } }, _removeHandler: function (ele, handler, context) { var handlers = ele.__z_resizeListeners; if (handlers) { var size = handlers.length; for (var i = 0; i < size; i++) { var h = handlers[i]; if (h.handler === handler && h.context === context) { handlers.splice(i, 1); return; } } } }, _createResizeTrigger: function (ele) { var obj = document.createElement('object'); obj.setAttribute('style', 'display: block; position: absolute; top: 0; left: 0; height: 100%; width: 100%; overflow: hidden;opacity: 0; pointer-events: none; z-index: -1;'); obj.onload = EleResize._handleObjectLoad; obj.type = 'text/html'; ele.appendChild(obj); obj.data = 'about:blank'; return obj; }, _handleObjectLoad: function (evt) { this.contentDocument.defaultView.__resizeTrigger__ = this.__resizeElement__; this.contentDocument.defaultView.addEventListener('resize', EleResize._handleResize); } }; if (document.attachEvent) {//ie9-10 EleResize.on = function (ele, handler, context) { var handlers = ele.__z_resizeListeners; if (!handlers) { handlers = []; ele.__z_resizeListeners = handlers; ele.__resizeTrigger__ = ele; ele.attachEvent('onresize', EleResize._handleResize); } handlers.push({ handler: handler, context: context }); }; EleResize.off = function (ele, handler, context) { var handlers = ele.__z_resizeListeners; if (handlers) { EleResize._removeHandler(ele, handler, context); if (handlers.length === 0) { ele.detachEvent('onresize', EleResize._handleResize); delete ele.__z_resizeListeners; } } } } else { EleResize.on = function (ele, handler, context) { var handlers = ele.__z_resizeListeners; if (!handlers) { handlers = []; ele.__z_resizeListeners = handlers; if (getComputedStyle(ele, null).position === 'static') { ele.style.position = 'relative'; } var obj = EleResize._createResizeTrigger(ele); ele.__resizeTrigger__ = obj; obj.__resizeElement__ = ele; } handlers.push({ handler: handler, context: context }); }; EleResize.off = function (ele, handler, context) { var handlers = ele.__z_resizeListeners; if (handlers) { EleResize._removeHandler(ele, handler, context); if (handlers.length === 0) { var trigger = ele.__resizeTrigger__; if (trigger) { trigger.contentDocument.defaultView.removeEventListener('resize', EleResize._handleResize); ele.removeChild(trigger); delete ele.__resizeTrigger__; } delete ele.__z_resizeListeners; } } } } export default EleResize;
