先看效果

刚开始的需求是,制作一个类似电视广告字幕的效果,我没什么思路,后来看了字幕的实现方式,就是用css动画的移动实现,于是我开始了对这段动画的驾驭。

技术:万能的vue.js html5 css3

首先我们要提取到一个html文件中,在文件中引用需要的CDN

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><title>demo</title>
</head>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
<script src="https://unpkg.com/element-ui/lib/index.js"></script>
<style lang='scss' scoped></style><body><div id="app"></div>
</body>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script src="https://code.jquery.com/jquery-3.6.0.slim.js"integrity="sha256-HwWONEZrpuoh951cQD1ov2HUK5zA5DwJ1DNUXaM6FsY=" crossorigin="anonymous"></script>
<script>new Vue({el: '#app',data: function () {return {}},mounted() {},methods: {}})
</script></html>

我们写一个外面的块,宽度是100%,再写一个里面的块,再里面的块里放置内容。内容部分暂且不管,我主要讲实现思路。

<body><div id="app"><template><div class="marquee-outer-wrapper"><div class="marquee-inner-wrapper"><div class="span first-marquee"><div class="item" v-for="item in cionList" :key="item.id"><img :src="item.icon" alt="" class="icon" /><div class="title">{{item.name}}</div><div class="text">[{{item.crypto}}]</div><div class="pre">${{item.a}}</div><div :class="item.isRed > 0 ? 'green' : 'red'"><i:class="item.isRed > 0 ? 'el-icon-caret-top' : 'el-icon-caret-bottom'">{{item.isRed}}%</i></div></div></div></div></div></template></div>
</body>
.marquee-outer-wrapper {width: 100%;overflow: hidden;position: absolute;top: 0;left: 0;}.marquee-inner-wrapper {background: #1D2330;height: 50px;line-height: 50px;margin: 0 auto;white-space: nowrap;position: relative;}.marquee-inner-wrapper .span {position: absolute;top: 0;left: 100%;/* right: 100%; */height: 100%;display: flex;flex-direction: row;justify-content: space-evenly;}.item {display: flex;flex-direction: row;justify-content: start;}.first-marquee {-webkit-animation: 20s first-marquee linear infinite normal;animation: 20s first-marquee linear infinite normal;padding-left: 20%;}.icon {width: 22px;height: 22px;margin-top: 14px;margin-left: 20px;}.title {line-height: 50px;font-size: 14px;color: #2D74C4;margin-left: 6px;}.text {line-height: 50px;font-size: 12px;color: #939494;margin-left: 4px;}.pre {line-height: 50px;font-size: 14px;color: white;font-weight: bold;margin-left: 6px;}.red {line-height: 50px;font-size: 10px;color: #E5541E;margin-left: 4px;}.green {line-height: 50px;font-size: 10px;color: #049E62;margin-left: 4px;}@keyframes first-marquee {0% {-webkit-transform: translate3d(0, 0, 0);transform: translate3d(0, 0, 0);}/* 向左移动 */100% {-webkit-transform: translate3d(-200%, 0, 0);transform: translate3d(-200%, 0, 0);display: none;}}

这里的思路主要是把里面的div放在屏幕的最右侧,然后设置向左迅速运动的动画,达到字幕滚动的效果。

但是问题来了,动画只运行一次,结束后才运行第二次。功能达到了但是效果不够完美。

于是,我想再写一个里面的div,但是是在第一个div先运行一段时间后再跑起来,思路有了,开始实现。

<body><div id="app"><template><div class="marquee-outer-wrapper"><div class="marquee-inner-wrapper"><div class="span first-marquee"><div class="item" v-for="item in cionList" :key="item.id"><img :src="item.icon" alt="" class="icon" /><div class="title">{{item.name}}</div><div class="text">[{{item.crypto}}]</div><div class="pre">${{item.a}}</div><div :class="item.isRed > 0 ? 'green' : 'red'"><i:class="item.isRed > 0 ? 'el-icon-caret-top' : 'el-icon-caret-bottom'">{{item.isRed}}%</i></div></div></div><div class="span second-marquee"><div class="item" v-for="item in cionList" :key="item.crypto"><img :src="item.icon" alt="" class="icon" /><div class="title">{{item.name}}</div><div class="text">[{{item.crypto}}]</div><div class="pre">${{item.a}}</div><div :class="item.isRed > 0 ? 'green' : 'red'"><i:class="item.isRed > 0 ? 'el-icon-caret-top' : 'el-icon-caret-bottom'">{{item.isRed}}%</i></div></div></div></div></div></template></div>
</body>
.second-marquee {-webkit-animation: 20s first-marquee linear 8s infinite normal;animation: 20s first-marquee linear 8s infinite normal;padding-left: 20%;}

在原有的基础上,又添加了一个类是span的div。不同的是它运行的动画是.second-marquee。这个动画和原有的动画区别就在于,这个动画相对上一个动画延时8s播放,达到一前一后的效果。

现在动画动起来了,但是需求又增加了。

大致内容就是在地址栏输入参数,根据参数的值可以修改一些属性,比如整体的高度,滚动条的颜色,运行的速度,运行的方向,甚至字体的大小。那么先来处理参数。

getParams() {let str = window.location.hrefif (str.indexOf("?") == -1) {return} else {let params = str.split('?')[1]let paramsList = params.split('&')let paramsObj = {}for (let i = 0; i < paramsList.length; i++) {const item = paramsList[i];paramsObj[item.split('=')[0]] = item.split('=')[1]}// console.log(paramsObj);this.params = paramsObjthis.size = this.params.size}}

这时,我们不知道传来的参数都是什么,除了size,因为是后加的,我就直接提取了出来。

那么接下来考虑的是怎么改这些属性。因为这些属性都是写在样式里面的,我首先想到vue和jquery混写,但是网上都说尽量避免这种写法。那就另辟蹊径,利用document.styleSheets获取当前文件的所有css,再利用deleteRule方法和insertRule方法修改。继续实现。

setStyle() {if (!this.params) {return} else {console.log(document.styleSheets[1]);var style = document.styleSheets[1];// 控制向左向右if (!this.params.direction) {return} else if (this.params.direction == "left") {style.deleteRule(2)style.insertRule(".marquee-inner-wrapper .span { position: absolute; top: 0px; left: 100%; height: 100%; display: flex; flex-direction: row; justify-content: space-evenly; }", 2);style.deleteRule(12)style.insertRule("@keyframes first-marquee { \n  0% { transform: translate3d(0px, 0px, 0px); }\n  100% { transform: translate3d(-200%, 0px, 0px); display: none; }\n}", 12)} else {style.deleteRule(2)style.insertRule(".marquee-inner-wrapper .span { position: absolute; top: 0px; right: 100%; height: 100%; display: flex; flex-direction: row; justify-content: space-evenly; }", 2);style.deleteRule(12)style.insertRule("@keyframes first-marquee { \n  0% { transform: translate3d(0px, 0px, 0px); }\n  100% { transform: translate3d(200%, 0px, 0px); display: none; }\n}", 12)}// 控制高度if (!this.params.height) {return} else {style.deleteRule(11)style.insertRule(".green { line-height: " + this.params.height + "px; font-size: " + this.size * 0.7 + "px; color: rgb(4, 158, 98); margin-left: 4px; }", 11)style.deleteRule(10)style.insertRule(".red { line-height: " + this.params.height + "px; font-size: " + this.size * 0.7 + "px; color: rgb(229, 84, 30); margin-left: 4px; }", 10)style.deleteRule(9)style.insertRule(".pre { line-height: " + this.params.height + "px; font-size: " + this.size + "px; color: white; font-weight: bold; margin-left: 6px; }", 9)style.deleteRule(8)style.insertRule(".text { line-height: " + this.params.height + "px; font-size: " + this.size * 0.8 + "px; color: rgb(147, 148, 148); margin-left: 4px; }", 8)style.deleteRule(7)style.insertRule(".title { line-height: " + this.params.height + "px; font-size: " + this.size + "px; color: rgb(45, 116, 196); margin-left: 6px; }", 7)style.deleteRule(6)style.insertRule(".icon { width: " + this.size * 1.5 + "px; height: " + this.size * 1.5 + "px; margin-top: " + (this.params.height - this.size * 1.5) / 2 + "px; margin-left: 20px; }", 6)style.deleteRule(1)style.insertRule(".marquee-inner-wrapper { background: rgb(29, 35, 48); height: " + this.params.height + "px; line-height: " + this.params.height + "px; margin: 0px auto; white-space: nowrap; position: relative; }", 1)}// 控制背景颜色if (!this.params.backgroundColor) {return} else {document.getElementsByClassName("marquee-inner-wrapper")[0].style.backgroundColor = "rgb(" + this.params.backgroundColor + ")"}// 控制速度if (!this.params.speed) {return} else {style.deleteRule(4)style.insertRule(".first-marquee { animation: " + this.params.speed + "s linear 0s infinite normal none running first-marquee; padding-left: 20%; }", 4)style.deleteRule(5)style.insertRule(".second-marquee { animation: " + this.params.speed + "s linear " + (this.params.speed) / 2 + "s infinite normal none running first-marquee; padding-left: 20%; }", 5)}}}

这里应该是有优化的空间,我说一下我这种写法的坑。注意一下控制高度的地方,这里顺序是从高到低,为什么这样操作呢,因为当你使用deleteRule方法后,样式的数量会减少,下标也会随之变化,那为什么要用deleteRule方法呢,因为insertRule方法是插入一条,覆盖之前的,这样我们就先发制人,先删除再插入就ok了。

再来说一下insertRule后面跟的字符串就是这个样式的并行字符串,非常容易写错,怎么办呢,就是打印document.styleSheets,这里面每个样式都写的一清二楚,复制过来再把变量替换进去就ok啦。

现在是两列“小火车”交替行进,如何控制他们的距离呢,也就是两列小火车的距离,就在这里

.first-marquee {-webkit-animation: 0s first-marquee linear infinite normal;animation: 0s first-marquee linear infinite normal;padding-left: 20%;}.second-marquee {-webkit-animation: 0s first-marquee linear 0s infinite normal;animation: 0s first-marquee linear 0s infinite normal;padding-left: 20%;}

注意看这个padding-left: 20%;,你可以试试其他的值有什么意想不到的效果。

这里也是经历了我的魔改最后实现一个完美的效果。

最后再来看一遍成品

最后的最后,这个数据接口还是自己找吧,网络上应该不少,或者使用假数据练习。

能读到这的都是大牛,哈哈哈哈我废话贼多


拓展

你觉得这种滚动效果可以做什么有趣的功能呢?

鼠标悬停可以暂停动画,配合点击事件,做一个小小的播放器怎么样。

放一些链接进去,点击之后在小窗里面显示网页内容。

还能怎么玩?

制作一个广告字幕滚动效果的网页的心路历程相关推荐

  1. 【web前端特效源码】使用HTML5+CSS3制作一个会促销广告滚动字幕3D动画效果~~适合初学者~超简单~ |前端开发|IT软件

    b站视频演示效果: [web前端特效源码]使用HTML5+CSS3制作一个会促销广告滚动字幕3D动画效果~~适合初学者~超简单~ |前端开发|IT软件 效果图: 完整代码: <!DOCTYPE ...

  2. 字幕滚动c语言程序,MFC实现字幕滚动效果

    本文实例为大家分享了MFC实现字幕滚动效果的具体代码,供大家参考,具体内容如下 1.创建对话框工程 这一步很简单,可以参考我之前的博客.这里可以先放出我程序运行的效果图.如果不是你所需要的可以直接关闭 ...

  3. 用html和js制作一个控制灯泡开关效果

    用html和js制作一个控制灯泡开关效果 **用css样式来控制div图片和文本的位置,然后用js里面onclick点击事件来控制图片的更换效果来实现当前运行图的效果** 1.以下是运行的效果图 2. ...

  4. 使用css实现字幕滚动效果

    使用css实现字幕滚动效果 最近业务需要,让电子屏上面的横幅能够自动的滚动,但是用js加requireanimation实现的话感觉有点浪费,转念想到了用css 的animation似乎也能够实现大致 ...

  5. 用Python实现音频卷积,并制作一个简单的HRTF效果

    用Python实现音频卷积,并制作一个简单的HRTF效果 作为一个刚刚入门Python的小白用户,写出这篇文章还是废了我很大的力气,不过幸运的是,在网上到处东拼西凑,我还是把它给做出来了. 废话不多说 ...

  6. Unity中用shader graph制作一个简单的传送门效果

    Unity中用shader graph制作一个简单的传送门效果 一.配置渲染管线 1.通过菜单"Asset" --> "Create" --> &q ...

  7. VB6实现字幕滚动效果

    VB6实现字幕滚动效果 设置Timer1的Interval值,每隔Interval会执行一次Timer()过程 Private Sub Form_Load() '设置前进时间,单位是毫秒 Timer1 ...

  8. 一个单片机学徒过渡到嵌入式工程师的心路历程,教你精准避开内卷

    一个单片机学徒过渡到嵌入式工程师的心路历程,教你精准避开内卷 工作经历 读书路过福州那会儿参加了一个招聘会,在福州大学大礼堂.招聘方打着省科技厅的名号,看起来是个牛气的公司.在宣讲会上列了几个863计 ...

  9. android+广告栏效果,Android自定义控件之广告条滚动效果

    在一些电子商务网站上经常能够看到一些滚动的广告条,许多软件在首次使用时也有类似的广告条,如图: 其实在github上有实现这种效果的控件,不过这东西做起来也是很简单,我们今天就来看看该怎么做. 先来看 ...

最新文章

  1. ibtmp1文件过大
  2. network 学习笔记
  3. 微信公众平台前端开发技巧分享
  4. SAP Spartacus CurrentProductService返回的null对象
  5. RedisTemplate value序列化导致的问题
  6. erp系统开源_自行构建的开源ERP系统
  7. echart itemStyle属性设置
  8. RequestDispatcher对象的应用-请求包含
  9. AcWing 789. 数的范围 (整数二分)
  10. Skip level 1 on 1
  11. vs2017添加引用出错:对COM组件的调用返回了错误HRESULT E_FAIL
  12. Linux查找link文件,Linux下查找一个文件的所有软硬链接
  13. 数据恢复工具(minitool power data recovery 8) v8.8(含64位32位)
  14. 复制出来的虚拟机加入域提示试图加入域的SID与本计算机的SID相同解决方法
  15. 数组方法的增删等19种操作:unshift 、shift,push、pop、splice等等...!
  16. 产品体验报告:Keep
  17. 【汇正财经】上证50逆势收涨,大盘健康震固
  18. 面向医疗数据的差分隐私保护
  19. String类菜鸟级教程(字符串常量池及不可变,StringBuffer 和 StringBuilder)
  20. MAX31865 RTD温度转换---专业版调试器

热门文章

  1. 六层板层叠结构设计方案
  2. kbengine源码_KBEngine源码:组件方案
  3. 快递鸟API接口技术规范说明文档
  4. 74HC595芯片实现原理及跑马灯数码管应用程序-----day2
  5. Win32高DPI编程总结
  6. 《猜画小歌》背后趣事
  7. 傅里叶变化互易对称性
  8. 进度条上的起伏_进度条(ProgressBar)的功能与用法
  9. matlab 随机掷骰子,随机投掷骰子.PPT
  10. python mysql 10061_python中的“无法在'localhost'(10061)'上连接到MySQL服务器”错误...