UNPKG

naive-ui

Version:

A Vue 3 Component Library. Fairly Complete, Theme Customizable, Uses TypeScript, Fast

117 lines 3.93 kB
import { repeat } from 'seemly'; import { computed, defineComponent, h, nextTick, ref } from 'vue'; import { VResizeObserver } from 'vueuc'; import { useConfig, useTheme } from "../../_mixins/index.mjs"; import { marqueeLight } from "../styles/index.mjs"; import { marqueeProps } from "./props.mjs"; import style from "./styles/index.cssr.mjs"; export default defineComponent({ name: 'Marquee', props: marqueeProps, setup(props) { const { mergedClsPrefixRef } = useConfig(props); useTheme('Marquee', '-marquee', style, marqueeLight, props, mergedClsPrefixRef); const containerElRef = ref(null); const contentWidthRef = ref(-1); const containerWidthRef = ref(-1); const playStateRef = ref('running'); const repeatCountInOneGroupRef = computed(() => { if (!props.autoFill) return 1; const { value: contentWidth } = contentWidthRef; const { value: containerWidth } = containerWidthRef; if (contentWidth === -1 || containerWidth === -1) return 1; return Math.ceil(containerWidthRef.value / contentWidth); }); const durationRef = computed(() => { const { value: contentWidth } = contentWidthRef; if (contentWidth === -1) return 0; return contentWidth * repeatCountInOneGroupRef.value / props.speed; }); const animationCssVarsRef = computed(() => { return { '--n-play': playStateRef.value, '--n-direction': 'normal', '--n-duration': `${durationRef.value}s`, '--n-delay': '0s', '--n-iteration-count': 'infinite', '--n-min-width': 'auto' }; }); function resetScrollState() { playStateRef.value = 'paused'; nextTick().then(() => { var _a; void ((_a = containerElRef.value) === null || _a === void 0 ? void 0 : _a.offsetTop); playStateRef.value = 'running'; }); } function handleContainerResize(entry) { containerWidthRef.value = entry.contentRect.width; } function handleContentResize(entry) { contentWidthRef.value = entry.contentRect.width; } function handleAnimationIteration() { resetScrollState(); } return { mergedClsPrefix: mergedClsPrefixRef, animationCssVars: animationCssVarsRef, containerElRef, repeatCountInOneGroup: repeatCountInOneGroupRef, handleContainerResize, handleContentResize, handleAnimationIteration }; }, render() { const { $slots, mergedClsPrefix, animationCssVars, repeatCountInOneGroup, handleAnimationIteration } = this; const originalNode = h(VResizeObserver, { onResize: this.handleContentResize }, h("div", { class: `${mergedClsPrefix}-marquee__item ${mergedClsPrefix}-marquee__original-item` }, $slots)); const mirrorNode = h("div", { class: `${mergedClsPrefix}-marquee__item` }, $slots); if (this.autoFill) { return h(VResizeObserver, { onResize: this.handleContainerResize }, h("div", { class: `${mergedClsPrefix}-marquee ${mergedClsPrefix}-marquee--auto-fill`, ref: "containerElRef", style: animationCssVars }, h("div", { class: `${mergedClsPrefix}-marquee__group`, onAnimationiteration: handleAnimationIteration }, originalNode, repeat(repeatCountInOneGroup - 1, mirrorNode)), h("div", { class: `${mergedClsPrefix}-marquee__group` }, repeat(repeatCountInOneGroup, mirrorNode)))); } else { return h("div", { class: [`${mergedClsPrefix}-marquee`], ref: "containerElRef", style: animationCssVars }, h("div", { class: `${mergedClsPrefix}-marquee__group`, onAnimationiteration: handleAnimationIteration }, originalNode), h("div", { class: `${mergedClsPrefix}-marquee__group` }, mirrorNode)); } } });