碰到个及其恶心的需求,需要文本溢出后水平滚动但是还要无缝;
辅助函数
export const getTextWidth = (text: string, size: number) => { const span = document.createElement('span'); span.style.position = 'absolute'; span.style.visibility = 'hidden'; span.style.whiteSpace = 'nowrap'; span.style.fontSize = size + 'px'; span.textContent = text; document.body.appendChild(span); const width = span.offsetWidth; document.body.removeChild(span); return width; }
|
实现函数
import { getTextWidth } from "@/utils";
interface ScrollXAnimationOptions { selector: string; scrollSpeed?: number; spacing?: number; }
const useScrollXAnimation = ({ selector, scrollSpeed = 1 }: ScrollXAnimationOptions) => { const animationIds = new Map<HTMLElement, number>();
const rs = document.querySelectorAll(selector) as NodeListOf<HTMLElement>;
rs.forEach((el) => { const content = el.innerHTML; const style = window.getComputedStyle(el); const fontSize = style.getPropertyValue('font-size'); const size = fontSize.split('px')[0]; const textWidth = getTextWidth(el.textContent as string, +size);
el.innerHTML += `<span style="width:${textWidth * 0.2}px; display:inline-block;height:${size}px;"></span>${content}`;
let start = 0; const elWidth = textWidth + (textWidth * 0.2);
const animate = () => { start -= scrollSpeed;
if (start <= -elWidth) { start = 0; }
el.style.transform = `translateX(${start}px)`;
animationIds.set(el, requestAnimationFrame(animate)); };
animate();
const handleMouseEnter = () => { const id = animationIds.get(el); if (id) { cancelAnimationFrame(id); animationIds.delete(el); } };
const handleMouseLeave = () => { if (!animationIds.has(el)) { animate(); } };
el.addEventListener('mouseenter', handleMouseEnter); el.addEventListener('mouseleave', handleMouseLeave);
return () => { el.removeEventListener('mouseenter', handleMouseEnter); el.removeEventListener('mouseleave', handleMouseLeave);
const id = animationIds.get(el); if (id) { cancelAnimationFrame(id); animationIds.delete(el); } }; });
return () => { animationIds.forEach((id) => cancelAnimationFrame(id)); animationIds.clear(); }; };
export default useScrollXAnimation;
|
使用方法如下
在合适的地方调用此hook(需要能访问到 .scroll-x-anmin
)有此类名就会水平滚动;
import useScrollXAnimation from "@/hook/event/useTextScroll";
useScrollXAnimation({ selector: ".scroll-x-anmin", scrollSpeed: 1 });
<div className="w-[435px] overflow-hidden relative mx-auto text-[13px]"> <div className={ getTextWidth(item?.title, 13)>434 ? "scroll-x-anmin" : "" } > {item.title}</div> </div>
|