@nutui/nutui-react-taro
Version:
京东风格的轻量级移动端 React 组件库,支持一套代码生成 H5 和小程序
122 lines (121 loc) • 4.7 kB
JavaScript
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
};