介绍
绘制公司大屏业务的时候,很多地方需要添加滚动动画,所以封装了一个方法用于动态添加,不需要每个页面写一次 css,方法支持自定义方向、动画播放模式等。
代码
/**
* 给元素设置 marquee 内容滚动效果,支持来回滚动,正常跑马灯,无限无缝滚动。
* 一般来说设置两层,滚动的区间就是父元素的大小。
* 若 #demo 高度小于 container,除非 loopType 设置 infinite,否则不会有动画。
* <div class="demo-container"><div id="#demo">...span.items...</div></div>
* @example
* marquee('#demo'); /// 默认横向正常滚动(loopType=normal)
* marquee('.demo-y', {direction: 'Y', loopType: 'infinite', speed: 3}); /// Y 轴无限无缝滚动,speed > 0 越小速度越快。
* marquee('.demo-x', {direction: 'X', loopType: 'origin', speed: 3, style: 'animation-delay:2s;', parentStyle: 'color:red;'}); /// X 轴无限来回滚动
* @param selector 选择器字符串
* @param options 动画配置
* @returns
*/
export function marquee(
selector: string,
options?: {
direction?: 'X' | 'Y';
loopType?: 'infinite' | 'normal' | 'origin';
speed?: number;
style?: string;
parentStyle?: string;
},
): void {
try {
const cssAnimation =
'@keyframes marquee-ANIMATION_NAME{0%{transform:translate3d(0,0,0);-webkit-transform:translate3d(0,0,0);-moz-transform:translate3d(0,0,0);-ms-transform:translate3d(0,0,0);-o-transform:translate3d(0,0,0)}50%{transform:translate3d(X_TEMP_VAL,Y_TEMP_VAL,0);-webkit-transform:translate3d(X_TEMP_VAL,Y_TEMP_VAL,0);-moz-transform:translate3d(X_TEMP_VAL,Y_TEMP_VAL,0);-ms-transform:translate3d(X_TEMP_VAL,Y_TEMP_VAL,0);-o-transform:translate3d(X_TEMP_VAL,Y_TEMP_VAL,0)}100%{transform:translate3d(X_END_VAL,Y_END_VAL,0);-webkit-transform:translate3d(X_END_VAL,Y_END_VAL,0);-moz-transform:translate3d(X_END_VAL,Y_END_VAL,0);-ms-transform:translate3d(X_END_VAL,Y_END_VAL,0);-o-transform:translate3d(X_END_VAL,Y_END_VAL,0)}}';
const tempId = selector.replace(/[.#]/g, '');
const styleElId = `style-${tempId}`;
const $animationStyle = document.getElementById(styleElId) ?? document.createElement('style');
$animationStyle.id = styleElId;
const $marqueeDom: any = document.querySelector(selector);
const noAnimation =
options?.loopType != 'infinite' && $marqueeDom?.clientHeight < $marqueeDom?.parentElement?.offsetHeight;
$marqueeDom?.setAttribute(
'style',
`overflow:visible;animation-name:marquee-${tempId};animation-timing-function:linear;animation-iteration-count:infinite;animation-duration:${
((options?.direction === 'Y' ? $marqueeDom.clientHeight : $marqueeDom.clientWidth) / 200) *
(options?.speed ?? 3) ?? 5
}s;${noAnimation ? 'animation-duration:0s;' : ''}${
options?.style ??
`${
options?.loopType === 'origin'
? options?.direction === 'Y'
? 'padding-bottom:12px;'
: 'padding-right:12px;'
: ''
}`
}`,
);
if (options?.direction === 'Y') {
$animationStyle.innerHTML = cssAnimation
.replace('ANIMATION_NAME', tempId)
.replace(/X_TEMP_VAL/g, '0')
.replace(
/Y_TEMP_VAL/g,
options.loopType === 'origin' ? `calc(-100% + ${$marqueeDom?.parentElement?.offsetHeight ?? 0}px)` : '-50%',
)
.replace(/X_END_VAL/g, '0')
.replace(/Y_END_VAL/g, options.loopType === 'origin' ? '0' : '-100%');
} else {
$animationStyle.innerHTML = cssAnimation
.replace('ANIMATION_NAME', tempId)
.replace(/Y_TEMP_VAL/g, '0')
.replace(
/X_TEMP_VAL/g,
options?.loopType === 'origin' ? `calc(-100% + ${$marqueeDom?.parentElement?.offsetWidth ?? 0}px)` : '-50%',
)
.replace(/Y_END_VAL/g, '0')
.replace(/X_END_VAL/g, options?.loopType === 'origin' ? '0' : '-100%');
}
$marqueeDom?.parentElement?.setAttribute('style', `overflow:hidden;${options?.parentStyle ?? ''}`);
if (options?.loopType === 'infinite') {
$marqueeDom.parentElement.innerHTML = $marqueeDom.outerHTML + $marqueeDom.outerHTML;
} else {
// $marqueeDom.parentElement.innerHTML = $marqueeDom.outerHTML;
}
!document.getElementById(styleElId) && document.getElementsByTagName('head')[0].appendChild($animationStyle);
} catch (e) {
console.log('js-xxx:marqueeError--->', e);
}
}
也可直接安装 js-xxx 工具库直接使用
// npm i js-xxx
import { marquee } from 'js-xxx';
marquee('#demo'); /// 默认横向正常滚动(loopType=normal)
marquee('.demo-y', {direction: 'Y', loopType: 'infinite', speed: 3}); /// Y 轴无限无缝滚动,speed > 0 越小速度越快。
marquee('.demo-x', {direction: 'X', loopType: 'origin', speed: 3, style: 'animation-delay:2s;', parentStyle: 'color:red;'}); /// X 轴无限来回滚动