UNPKG

@nutui/nutui-react-taro

Version:

京东风格的轻量级移动端 React 组件库,支持一套代码生成 H5 和小程序

122 lines (121 loc) 4.7 kB
import { _ as __rest, a as __awaiter } from "./tslib.es6-iWu3F_1J.js"; import React__default, { useRef, useImperativeHandle, useEffect } from "react"; import classNames from "classnames"; import { View } from "@tarojs/components"; import { C as ComponentDefaults } from "./typings-DV9RBfhj.js"; import { g as getRectByTaro } from "./get-rect-by-taro-D0h6aiDr.js"; const defaultProps = Object.assign(Object.assign({}, ComponentDefaults), { list: [], interval: 500, loop: true, duration: 3e3, rows: 3, gapY: 10 }); const classPrefix = `nut-barrage`; const InternalBarrage = (props, ref) => { const _a = Object.assign(Object.assign({}, defaultProps), props), { className, interval, loop, list, duration, rows, gapY } = _a, restProps = __rest(_a, ["className", "interval", "loop", "list", "duration", "rows", "gapY"]); const barrageBody = useRef(null); const barrageContainer = useRef(null); const barrageCWidth = useRef(0); const timer = useRef(0); const domTimer = useRef(0); const index = useRef(0); const times = useRef([]); const historyIndex = useRef(-1); const classes = classNames(classPrefix, className); useImperativeHandle(ref, () => ({ add: (word) => { const _index = index.current % list.length; if (!loop && index.current === list.length) { list.splice(list.length, 0, word); } else { list.splice(_index, 0, word); } } })); const getNodeWidth = (node_1, ...args_1) => __awaiter(void 0, [node_1, ...args_1], void 0, function* (node, type = "width") { if (node) { const refe = yield getRectByTaro(node); return Math.ceil(type === "height" ? refe.height : refe.width); } return 0; }); const clearDomTimeout = () => { if (domTimer.current) { clearTimeout(domTimer.current); domTimer.current = 0; } }; useEffect(() => { const init = () => __awaiter(void 0, void 0, void 0, function* () { var _a2; if (barrageBody.current) { barrageCWidth.current = yield getNodeWidth(barrageBody.current); (_a2 = barrageBody.current) === null || _a2 === void 0 ? void 0 : _a2.style.setProperty("--move-distance", `-${barrageCWidth.current}px`); index.current = 0; run(); } }); domTimer.current = window.setTimeout(() => { init(); }, 300); return () => { clearDomTimeout(); }; }, [list]); const run = () => { clearTimeout(timer.current); let intervalCache = interval; const _index = (loop ? index.current % list.length : index.current) % rows; const result = times.current[_index] - rows * interval; if (result > 0) { intervalCache += result; } timer.current = window.setTimeout(() => { play(); }, intervalCache); }; const setStyle = (el, currentIndex) => __awaiter(void 0, void 0, void 0, function* () { try { if (el) { const refe = yield getRectByTaro(el); const width = refe.width; const height = refe.height; el.classList.add("move"); const elScrollDuration = Math.round(width / barrageCWidth.current * duration); times.current[currentIndex] = elScrollDuration; el.style.animationDuration = `${duration + elScrollDuration}ms`; el.style.top = `${currentIndex * (height + gapY) + 20}px`; el.style.width = `${width}px`; } } catch (error) { console.log("异常自动流转到下一个", error); barrageContainer.current.removeChild(el); } el.addEventListener("animationend", () => { barrageContainer.current.removeChild(el); }); }); const play = () => { if (!loop && index.current >= list.length) { return; } const _index = loop ? index.current % list.length : index.current; const el = document.createElement(`View`); let currentIndex = _index % rows; if (currentIndex <= historyIndex.current || historyIndex.current === 3 && currentIndex !== 0 || Math.abs(currentIndex - historyIndex.current) !== 1) { currentIndex = historyIndex.current + 1 >= rows ? 0 : historyIndex.current + 1; } historyIndex.current = currentIndex; el.innerHTML = list[_index]; barrageContainer.current.appendChild(el); el.classList.add("barrage-item"); requestAnimationFrame(() => setStyle(el, currentIndex)); index.current++; run(); }; return React__default.createElement( View, Object.assign({ className: classes, ref: barrageBody }, restProps), React__default.createElement(View, { ref: barrageContainer, className: "bContainer" }) ); }; const Barrage = React__default.forwardRef(InternalBarrage); Barrage.displayName = "NutBarrage"; export { Barrage as B };