UNPKG

zarm

Version:

基于 React 的移动端UI库

114 lines (106 loc) 3.96 kB
import React, { useRef, useEffect, useCallback } from 'react'; import { createBEM } from '@zarm-design/bem'; import { DIRECTION_LEFT, DIRECTION_RIGHT, DIRECTION_UP, DIRECTION_DOWN } from './constants'; import { ConfigContext } from '../config-provider'; import { canUseDOM } from '../utils/dom'; var SPEED = 30; var DEFAULT_RECT = { top: 0, bottom: 0, width: 0, height: 0, left: 0, right: 0, x: 0, y: 0, toJSON: function toJSON() {} }; var CLIENT_RECT = canUseDOM && 'DOMRect' in window ? new window.DOMRect() : DEFAULT_RECT; var Marquee = /*#__PURE__*/React.forwardRef(function (props, ref) { var direction = props.direction, _props$speed = props.speed, speed = _props$speed === void 0 ? SPEED : _props$speed, delay = props.delay, height = props.height, width = props.width, children = props.children, className = props.className; var dir = direction.toLowerCase(); var container = useRef(null); var scrollItem = useRef(null); var containerBoundingRect = useRef(CLIENT_RECT); var boundingRect = useRef(CLIENT_RECT); var marqueeRef = ref || /*#__PURE__*/React.createRef(); var _React$useContext = React.useContext(ConfigContext), prefixCls = _React$useContext.prefixCls; var bem = createBEM('marquee', { prefixCls: prefixCls }); var style = props.style; style = style || {}; style.width = width; style.height = height; var setAnimationProperty = useCallback(function () { var transformX = 0; var transformY = 0; var distanceX = 0; var distanceY = 0; var distance = 0; var rect = boundingRect.current; switch (dir) { case DIRECTION_LEFT: transformX = containerBoundingRect.current.width; distanceX = -boundingRect.current.width; distance = boundingRect.current.width + containerBoundingRect.current.width; break; case DIRECTION_RIGHT: transformX = -rect.width; distanceX = containerBoundingRect.current.width; distance = boundingRect.current.width + containerBoundingRect.current.width; break; case DIRECTION_UP: transformY = +(height || 0); distanceY = -boundingRect.current.height; distance = boundingRect.current.height + containerBoundingRect.current.height; break; case DIRECTION_DOWN: transformY = -rect.height; distanceY = containerBoundingRect.current.height; distance = boundingRect.current.height + containerBoundingRect.current.height; break; default: transformX = rect.width; distanceX = boundingRect.current.width; distance = boundingRect.current.width + containerBoundingRect.current.width; } container.current.style.setProperty('--transform-x', "".concat(transformX, "px")); container.current.style.setProperty('--transform-y', "".concat(transformY, "px")); container.current.style.setProperty('--distance-x', "".concat(distanceX, "px")); container.current.style.setProperty('--distance-y', "".concat(distanceY, "px")); container.current.style.animationDelay = "".concat(delay, "ms"); container.current.style.animationDuration = "".concat(distance / speed * 1000, "ms"); }, [dir, height, speed, delay]); useEffect(function () { containerBoundingRect.current = container.current.getBoundingClientRect(); boundingRect.current = scrollItem.current.getBoundingClientRect(); setAnimationProperty(); }, [setAnimationProperty]); return /*#__PURE__*/React.createElement("div", { className: bem([className]), ref: marqueeRef }, /*#__PURE__*/React.createElement("div", { className: bem('body'), ref: container, style: style }, /*#__PURE__*/React.createElement("div", { className: bem('content'), ref: scrollItem }, children))); }); Marquee.displayName = 'Marquee'; Marquee.defaultProps = { direction: 'left', speed: 30, delay: 0 }; export default Marquee;