| | |
| | | <template> |
| | | <el-scrollbar ref="scrollContainer" :vertical="false" class="scroll-container" @wheel.prevent="handleScroll"> |
| | | <slot /> |
| | | </el-scrollbar> |
| | | </template> |
| | | <script setup name="ScrollPane"> |
| | | import { ref, computed, onMounted, onBeforeUnmount, nextTick } from "vue"; |
| | | |
| | | <script> |
| | | import { defineComponent } from 'vue'; |
| | | const $emit = defineEmits(["scroll"]); |
| | | const tagAndTagSpacing = 0; // tagAndTagSpacing |
| | | const left = ref(0); |
| | | const scrollContainer = ref(); |
| | | const props = defineProps({ |
| | | tagRefs: { |
| | | type: Array, |
| | | default: () => [], |
| | | }, |
| | | }); |
| | | |
| | | const tagAndTagSpacing = 4; // tagAndTagSpacing |
| | | const wrap = computed(() => { |
| | | return scrollContainer.value.wrapRef; |
| | | }); |
| | | |
| | | export default defineComponent({ |
| | | name: 'ScrollPane', |
| | | data() { |
| | | return { |
| | | left: 0 |
| | | }; |
| | | }, |
| | | computed: { |
| | | scrollWrapper() { |
| | | return this.$refs.scrollContainer.$refs.wrapRef; |
| | | } |
| | | }, |
| | | mounted() { |
| | | if (this.scrollWrapper) { |
| | | this.scrollWrapper.addEventListener('scroll', this.emitScroll, true); |
| | | } |
| | | }, |
| | | beforeUnmount() { |
| | | if (this.scrollWrapper) { |
| | | this.scrollWrapper.removeEventListener('scroll', this.emitScroll); |
| | | } |
| | | }, |
| | | methods: { |
| | | handleScroll(e) { |
| | | function handleScroll(e) { |
| | | const eventDelta = e.wheelDelta || -e.deltaY * 40; |
| | | const $scrollWrapper = this.scrollWrapper; |
| | | $scrollWrapper.scrollLeft = $scrollWrapper.scrollLeft + eventDelta / 4; |
| | | }, |
| | | emitScroll() { |
| | | this.$emit('scroll'); |
| | | }, |
| | | moveToTarget(currentTag) { |
| | | const $container = this.$refs.scrollContainer.$el; |
| | | scrollContainer.value.scrollLeft = wrap.scrollLeft + eventDelta / 4; |
| | | } |
| | | function emitScroll() { |
| | | $emit("scroll"); |
| | | } |
| | | function moveToTarget(currentTag) { |
| | | // const $container = $refs.scrollContainer.$el; |
| | | const $container = scrollContainer.value.$el; |
| | | const $containerWidth = $container.offsetWidth; |
| | | const $scrollWrapper = this.scrollWrapper; |
| | | const tagList = this.$parent.$refs.tag; |
| | | // const $scrollWrapper = scrollWrapper; |
| | | const $scrollWrapper = scrollContainer.value; |
| | | // const tagList = $parent.$refs.tag; |
| | | const tagList = props.tagRefs; |
| | | |
| | | let firstTag = null; |
| | | let lastTag = null; |
| | |
| | | $scrollWrapper.scrollLeft = $scrollWrapper.scrollWidth - $containerWidth; |
| | | } else { |
| | | // find preTag and nextTag |
| | | const currentIndex = tagList.findIndex(item => item === currentTag); |
| | | const currentIndex = tagList.findIndex((item) => item === currentTag); |
| | | const prevTag = tagList[currentIndex - 1]; |
| | | const nextTag = tagList[currentIndex + 1]; |
| | | |
| | | // the tag's offsetLeft after of nextTag |
| | | const afterNextTagOffsetLeft = nextTag.$el.offsetLeft + nextTag.$el.offsetWidth + tagAndTagSpacing; |
| | | const afterNextTagOffsetLeft = |
| | | nextTag.$el.offsetLeft + nextTag.$el.offsetWidth + tagAndTagSpacing; |
| | | |
| | | // the tag's offsetLeft before of prevTag |
| | | const beforePrevTagOffsetLeft = prevTag.$el.offsetLeft - tagAndTagSpacing; |
| | |
| | | } |
| | | } |
| | | } |
| | | } |
| | | defineExpose({ |
| | | moveToTarget, |
| | | }); |
| | | </script> |
| | | <template> |
| | | <el-scrollbar |
| | | ref="scrollContainer" |
| | | :vertical="false" |
| | | class="scroll-container" |
| | | > |
| | | <!-- @wheel.prevent="handleScroll" --> |
| | | <slot /> |
| | | </el-scrollbar> |
| | | </template> |
| | | |
| | | <style lang="less" scoped> |
| | | .scroll-container { |
| | |
| | | position: relative; |
| | | overflow: hidden; |
| | | width: 100%; |
| | | |
| | | :deep(.el-scrollbar__bar) { |
| | | bottom: 0px; |
| | | } |
| | | |
| | | :deep(.el-scrollbar__wrap) { |
| | | height: 49px; |
| | | overflow-x: hidden; |
| | | } |
| | | } |
| | | |
| | | .scroll-container::-webkit-scrollbar { |
| | | height: 0; |
| | | } |
| | | |
| | | .scroll-container::-webkit-scrollbar-thumb { |
| | | /* 滚动条里面小方块 */ |
| | | border-radius: 10px; |
| | | -webkit-box-shadow: none; |
| | | background: none; |
| | | } |
| | | .scroll-container::-webkit-scrollbar-track { |
| | | /* 滚动条里面轨道 */ |
| | | -webkit-box-shadow: none; |
| | | border-radius: 10px; |
| | | background: none; |
| | | } |
| | | </style> |