UNPKG

@opensig/opendesign

Version:

<p align="center"><img src="../docs/public/opendesign-logo-light.png"/></p> <h1 align="center">opendesign</h1> <p align="center">一个 Vue 3 组件库</p> <p align="center"><b>皮肤可定制,使用 TypeScript</b></p>

207 lines (206 loc) 6.45 kB
import { defineComponent, computed, ref, watch, onMounted, withDirectives, createElementBlock, openBlock, normalizeClass, createElementVNode, renderSlot, withModifiers, normalizeStyle, unref } from "vue"; import { vOnResize } from "../directives/on-resize.mjs"; const _sfc_main = /* @__PURE__ */ defineComponent({ __name: "ScrollbarRail", props: { direction: { default: "y" }, thumbRate: {}, offsetRate: { default: 0 }, notStepJump: { type: Boolean }, size: { default: "medium" } }, emits: ["scroll"], setup(__props, { emit: __emit }) { const props = __props; const emits = __emit; const isY = computed(() => props.direction === "y"); const isDarggingBar = ref(false); const barRef = ref(null); const thumbRef = ref(null); const trackLength = ref(0); const thumbSize = computed(() => { if (trackLength.value && props.thumbRate) { return Math.round(trackLength.value * props.thumbRate); } return 0; }); const thumbSizeStyle = computed(() => { return `${thumbSize.value}px`; }); const maxOffset = computed(() => trackLength.value - thumbSize.value); const sizeProp = computed(() => { return isY.value ? "height" : "width"; }); const offsetProp = computed(() => { return isY.value ? "translateY" : "translateX"; }); const offset = ref(0); watch( () => [props.offsetRate, trackLength.value], (val) => { if (!isDarggingBar.value) { offset.value = Math.round(val[1] * val[0]); } }, { immediate: true } ); const offsetStyle = computed(() => { return `${offsetProp.value}(${offset.value}px)`; }); const adjustOffset = (pos) => { if (pos < 0) { return 0; } if (pos > maxOffset.value) { return maxOffset.value; } return pos; }; onMounted(() => { if (!barRef.value) { return; } const { offsetHeight, offsetWidth } = barRef.value; trackLength.value = props.direction === "x" ? offsetWidth : offsetHeight; }); let s = 0; let oldOffset = 0; const onMouseMove = (e) => { const pos = isY.value ? e.clientY : e.clientX; const v = oldOffset + pos - s; const of = adjustOffset(v); if (of !== offset.value) { offset.value = of; emits("scroll", offset.value / trackLength.value); } }; const onMouseUp = () => { isDarggingBar.value = false; window.removeEventListener("mousemove", onMouseMove); window.removeEventListener("mouseup", onMouseUp); window.removeEventListener("contextmenu", onMouseUp); }; const onThumbMouseDown = (e) => { e.preventDefault(); e.stopPropagation(); isDarggingBar.value = true; s = isY.value ? e.clientY : e.clientX; oldOffset = offset.value; window.addEventListener("mousemove", onMouseMove); window.addEventListener("mouseup", onMouseUp); window.addEventListener("contextmenu", onMouseUp); }; const onTrackClick = (e) => { e.preventDefault(); if (!thumbRef.value || !barRef.value) { return; } const pos = isY.value ? e.clientY : e.clientX; let v = 0; if (props.notStepJump) { const bc = barRef.value.getBoundingClientRect(); v = pos - (isY.value ? bc.top : bc.left) - thumbSize.value / 2; } else { const bc = thumbRef.value.getBoundingClientRect(); const isPlus = pos > (isY.value ? bc.top : bc.left); v = offset.value + thumbSize.value * (isPlus ? 1 : -1); } const of = adjustOffset(v); if (of !== offset.value) { offset.value = of; emits("scroll", offset.value / trackLength.value); } }; const onResize = () => { if (!barRef.value) { return; } const { offsetHeight, offsetWidth } = barRef.value; trackLength.value = props.direction === "x" ? offsetWidth : offsetHeight; }; return (_ctx, _cache) => { return withDirectives((openBlock(), createElementBlock( "div", { ref_key: "barRef", ref: barRef, class: normalizeClass(["o-scrollbar-rail", [ `o-scrollbar-${props.direction}`, `o-scrollbar-${props.size}`, { "o-scrollbar-dragging": isDarggingBar.value } ]]), onClick: onTrackClick }, [ createElementVNode( "div", { ref_key: "thumbRef", ref: thumbRef, class: normalizeClass(["o-scrollbar-thumb", [ `o-scrollbar-${props.direction}-thumb`, { [`o-scrollbar-${props.direction}-thumb-dragging`]: isDarggingBar.value } ]]), style: normalizeStyle({ [sizeProp.value]: thumbSizeStyle.value, transform: offsetStyle.value }), onClick: _cache[0] || (_cache[0] = withModifiers(() => { }, ["stop"])), onMousedown: onThumbMouseDown }, [ renderSlot(_ctx.$slots, "thumb", { direction: props.direction, dragging: isDarggingBar.value }, () => [ createElementVNode( "div", { class: normalizeClass([ `o-scrollbar-${props.direction}-thumb-bar`, { "is-dragging": isDarggingBar.value } ]) }, null, 2 /* CLASS */ ) ]) ], 38 /* CLASS, STYLE, NEED_HYDRATION */ ), renderSlot(_ctx.$slots, "track", { direction: props.direction }, () => [ createElementVNode( "div", { class: normalizeClass(["o-scrollbar-track", [`o-scrollbar-${props.direction}-track`]]) }, null, 2 /* CLASS */ ) ]) ], 2 /* CLASS */ )), [ [unref(vOnResize), onResize] ]); }; } }); export { _sfc_main as default };