马黑黑 发表于 2024-6-30 11:25

CSS关键帧动画文本效果:逐行出场(封装二)

<style>
        #papa { width: 200px; border: 1px solid gray; padding: 10px;position: relative; margin: 30px; }
        #papa p { position: relative; padding: 0; margin: 6px 0; font: normal 22px sans-serif; text-shadow: 1px 1px 1px gray; animation: 2s forwards; }
        #papa p:first-of-type { font-size: 26px; font-weight: bold; text-align: center; }
        #papa p:last-of-type { font-size: 16px; text-align: right; }
        @keyframes move { to { transform: translate(0); } }
</style>

<div id="papa"></div>

<script>

const textAni = (ar, ele, time = 10000) => {
        let tId = 0;
        const ps = [];
        const mkPs = (lineAr) => {
                ps.length = 0;
                ele.innerHTML = '';
                lineAr.forEach(line => {
                        let p = document.createElement('p');
                        p.innerHTML = line;
                        p.style.transform = `translate(${ele.offsetWidth}px)`;
                        ele.appendChild(p);
                        ps.push(p);
                });
                mkAni();
        };
        const mkAni = () => {
                ps.forEach((p, k) => {
                        p.onanimationend = () => {
                                ps[(k + 1) % ps.length].style.animationName = 'move';
                                if (k === ps.length - 1) setTimeout(() => reset(), time);
                        };
                });
                ps.style.animationName = 'move';
        };
        const reset = () => {
                getText();
                ps.forEach(p => {
                        p.style.animationName = '';
                        p.style.transform = 'translate(${ele.offsetWidth}px)';
                        setTimeout(() => {
                                ps.style.animationName = 'move';
                        }, 500);
                });
               
        };
        const getText = () => {
                const tstr = ar;
                const lines = tstr.split('\n').filter(i => i !== '');
                tId = (tId + 1) % ar.length;
                mkPs(lines);
        };
        getText();
};

var txtAr = [
`长相思
花似伊,柳似伊。
花柳青春人别离。
低头双泪垂。
长江东,长江西。
两岸鸳鸯两处飞。
相逢知几时。
——【宋】欧阳修`,
`长相思
山一程,水一程,
身向榆关那畔行,
夜深千帐灯。
风一更,雪一更,
聒碎乡心梦不成,
故园无此声。
--【清】纳兰性德`,
];

textAni(txtAr, papa);

</script>

马黑黑 发表于 2024-6-30 11:26

代码:
<style>
        #papa { width: 200px; border: 1px solid gray; padding: 10px;position: relative; margin: 30px; }
        #papa p { position: relative; padding: 0; margin: 6px 0; font: normal 22px sans-serif; text-shadow: 1px 1px 1px gray; animation: 2s forwards; }
        #papa p:first-of-type { font-size: 26px; font-weight: bold; text-align: center; }
        #papa p:last-of-type { font-size: 16px; text-align: right; }
        @keyframes move { to { transform: translate(0); } }
</style>

<div id="papa"></div>

<script>

const textAni = (ar, ele, time = 10000) => {
        let tId = 0;
        const ps = [];
        const mkPs = (lineAr) => {
                ps.length = 0;
                ele.innerHTML = '';
                lineAr.forEach(line => {
                        let p = document.createElement('p');
                        p.innerHTML = line;
                        p.style.transform = `translate(${ele.offsetWidth}px)`;
                        ele.appendChild(p);
                        ps.push(p);
                });
                mkAni();
        };
        const mkAni = () => {
                ps.forEach((p, k) => {
                        p.onanimationend = () => {
                                ps[(k + 1) % ps.length].style.animationName = 'move';
                                if (k === ps.length - 1) setTimeout(() => reset(), time);
                        };
                });
                ps.style.animationName = 'move';
        };
        const reset = () => {
                getText();
                ps.forEach(p => {
                        p.style.animationName = '';
                        p.style.transform = 'translate(${ele.offsetWidth}px)';
                        setTimeout(() => {
                                ps.style.animationName = 'move';
                        }, 500);
                });
               
        };
        const getText = () => {
                const tstr = ar;
                const lines = tstr.split('\n').filter(i => i !== '');
                tId = (tId + 1) % ar.length;
                mkPs(lines);
        };
        getText();
};

var txtAr = [
`长相思
花似伊,柳似伊。
花柳青春人别离。
低头双泪垂。
长江东,长江西。
两岸鸳鸯两处飞。
相逢知几时。
——【宋】欧阳修`,
`长相思
山一程,水一程,
身向榆关那畔行,
夜深千帐灯。
风一更,雪一更,
聒碎乡心梦不成,
故园无此声。
--【清】纳兰性德`,
];

textAni(txtAr, papa);

</script>

马黑黑 发表于 2024-6-30 11:37

本帖最后由 马黑黑 于 2024-6-30 11:43 编辑

本封装特色:

(一)支持多单元文本循环输出

每个单元的文本可按示例中的分行写法书写,也可以使用分行符 \n 衔接各行,例如:

var txtAr = [
    `长相思\n花似伊,柳似伊。\n花柳青春人别离。\n低头双泪垂。\n长江东,长江西。\n两岸鸳鸯两处飞。\n相逢知几时。\n——【宋】欧阳修`,
    `长相思\n山一程,水一程,\n身向榆关那畔行,\n夜深千帐灯。\n风一更,雪一更,\n聒碎乡心梦不成,\n故园无此声。\n--【清】纳兰性德`,
];

(二)实现功能使用嵌套函数完成,主函数名称为 textAni,其内有若干子函数。对于函数,除非特殊需求,可以不用管,甚至可以不用关心它的实现原理和机制。使用时要做的,仅是传递正确的参数,三个:

参数1 :必须,文本数组,例如上面(一)讨论的 txtAr,变量名可自定义,要求格式合法;
参数2 :必须,文本输出目标元素,可填入 id 名,或有效的其它标识;
参数3 :可选,下个单元出场的间隔时间,毫秒单位,默认 10000
其它说明:

CSS样式中:

#papa 选择器不是一定得这么命名,可以命名为其他的名称,然后,① 对应的 p 标签前面的选择器名跟着修改;② HTML使用该选择器名称做 id、JS调研函数参数使用盒子 id。该选择器的样式应根据需要修改、增删属性;

p 标签请保留 position、margin、padding 属性,可根据场景需要或审美需求更改 margin 和 padding 的属性值,但 position 属性请不要修改。

南无月 发表于 2024-6-30 11:39

封装了,更加好用。{:4_199:}

马黑黑 发表于 2024-6-30 11:45

南无月 发表于 2024-6-30 11:39
封装了,更加好用。

嵌套函数可以避免使用过多的全局变量,函数内的变量名称也不担心与页面的其他变量名重名,同时看起来也更清爽,对于开发者而言也有好处:逻辑关系更清晰、便于维护。

红影 发表于 2024-6-30 14:22

这个封装好,还特别设置了第一句和最后一句的格式呢,考虑很仔细{:4_199:}

红影 发表于 2024-6-30 14:32

文字是靠左的吧,应该也可以居中呢。特殊诗词可以的,比如一七令{:4_173:}

上海朝阳 发表于 2024-6-30 15:03

呵呵呵,我就是像看天书,这搬家轻松

南无月 发表于 2024-6-30 17:56

马黑黑 发表于 2024-6-30 11:45
嵌套函数可以避免使用过多的全局变量,函数内的变量名称也不担心与页面的其他变量名重名,同时看起来也更 ...

嵌套函数,这个嵌套之前听说过。。涵数又来吓我了,还组了个团。。

艾玛,赶紧跑去细看说明。。这句
“对于函数,除非特殊需求,可以不用管,甚至可以不用关心它的实现原理和机制。”
真是太友好了。。{:4_170:}

南无月 发表于 2024-6-30 17:58

马黑黑 发表于 2024-6-30 11:37
本封装特色:

(一)支持多单元文本循环输出


说明书太重要了。老师V5{:4_199:}细心又体贴。。

马黑黑 发表于 2024-6-30 17:58

南无月 发表于 2024-6-30 17:58
说明书太重要了。老师V5细心又体贴。。

{:4_173:}

马黑黑 发表于 2024-6-30 17:59

南无月 发表于 2024-6-30 17:56
嵌套函数,这个嵌套之前听说过。。涵数又来吓我了,还组了个团。。

艾玛,赶紧跑去细看说明。。这句


{:4_196:}

南无月 发表于 2024-6-30 18:17

马黑黑 发表于 2024-6-30 17:58


表情帝上朝了{:4_170:}

南无月 发表于 2024-6-30 18:18

马黑黑 发表于 2024-6-30 17:59


别笑得这样,我要开始看说明书了。。{:4_173:}

马黑黑 发表于 2024-6-30 18:18

南无月 发表于 2024-6-30 18:18
别笑得这样,我要开始看说明书了。。

说明文档很重要

马黑黑 发表于 2024-6-30 18:18

南无月 发表于 2024-6-30 18:17
表情帝上朝了

应该的

梦江南 发表于 2024-6-30 18:40

谢谢老师无私奉献!要好好好学习了!

南无月 发表于 2024-6-30 20:10

马黑黑 发表于 2024-6-30 18:18
应该的

有事开奏。。{:4_170:}

南无月 发表于 2024-6-30 20:11

马黑黑 发表于 2024-6-30 18:18
说明文档很重要

太重要了。。高手和小白的沟通桥梁{:4_173:}

马黑黑 发表于 2024-6-30 23:17

南无月 发表于 2024-6-30 20:11
太重要了。。高手和小白的沟通桥梁

这不存在谁和谁的问题
页: [1] 2
查看完整版本: CSS关键帧动画文本效果:逐行出场(封装二)