需求
封装一个使用 css3 动画帧的上下滚动文字的组件,代码如下
html
<template>
<div class="scroll_box" @mouseenter="stopScroll" @mouseleave="startScroll" ref="scroll_box">
<span v-for="(item,index) in text" :key="index">
{{item}}
<br />
</span>
</div>
</template>
js
methods: {
stopScroll(e) {
if (!e.target.style.animationPlayState) {
e.target.style.animationPlayState = 'paused'
}
},
startScroll(e) {
e.target.style.animationPlayState = ''
}
}
css
<style lang="less" scoped>
.scroll_box {
width: 100%;
text-align: justify;
animation: moveTxt 1s 1 linear forwards;
animation: moveTxt 45s infinite linear;
@keyframes moveTxt {
from {
transform: translateY(200px);
}
to {
transform: translateY(-2880px);
}
}
}
</style>
封装痛点
需要动态获取盒子高度,设置到 css 中的 @keyframes 中
问题:
- 通过绑定 ref 获取 DOM的style 对象,但是没有 @keyframes 属性,更没有 from to 等可以设置。
查询百度,发现通过 js 设置 @keyframes 需要通过 document.styleSheet[] 的 item 遍历操作,但是 vue 中不太好操作。转为通过给 css 设置变量,然后 js 动态设置 css 的变量
css 变量
--xx
定义变量 var(--xx)
使用变量
变量必须写在 .xxx{}
内,不能直接在 <style>
下设置变量
css
<style lang="less" scoped>
.scroll_box {
--scrollheight: 200px; //定义变量
width: 100%;
text-align: justify;
animation: moveTxt 1s 1 linear forwards;
animation: moveTxt 45s infinite linear;
@keyframes moveTxt {
from {
transform: translateY(200px);
}
to {
transform: translateY(var(--scrollheight)) //使用变量
}
}
}
</style>
js 控制变量
this.$refs.refName.style.setProperty('变量名', 值 )
mounted() {
let height = this.$refs.scroll_box.offsetHeight
this.$refs.scroll_box.style.setProperty('--scrollheight', -height+'px' )
console.log(this.$refs.scroll_box.style.getPropertyValue('--scrollheight'))
}
通过调试发现设置上了,但是动画不生效,必须鼠标移入移除后才能正常执行动画,并有卡顿
解决:模拟鼠标事件,在设置上 css 后出发鼠标进入移除事件,触发 css 更新
js
mounted() {
let height = this.$refs.scroll_box.offsetHeight
this.$refs.scroll_box.style.setProperty('--scrollheight', -height + 'px')
console.log(this.$refs.scroll_box.style.getPropertyValue('--scrollheight'))
// this.$forceUpdate()
var oMouseenter = document.createEvent('MouseEvent')
oMouseenter.initEvent('mouseenter', false, false)
this.$refs.scroll_box.dispatchEvent(oMouseenter)
oMouseenter.initEvent('mouseleave', false, false)
setTimeout(() => {
this.$refs.scroll_box.dispatchEvent(oMouseenter)
}, 50)
}
PS:
强制刷新 vue 组件: this.$forceUpdate()
个人总结
- css/less/sass 等变量知识空缺
- 模拟事件知识空缺
- 事件相关函数知识空缺