Vue.js 文本交替滚动
1.前言
当一段文本需要单行显示,但是又限于容器宽度无法完全展示时,我们需要对其滚动展示,所以就有了这个插件,如图:
2.封装思路
- 使用js模拟循环滚动的动画,容器宽度固定且超出隐藏,文本元素禁止换行,为其动态设定位移
- 通过Vue指令开启该效果
- 对比容器宽度和文本宽度,当文本宽度大于容器宽度是,开启定时器为文本元素动态设定位移,定时器id可以存储到容器标签中
- 位移的终点位于取决于文本宽度与容器宽度的差值
- 当指令的值发生变动时,要重新计算容器宽度和文本宽度,重置定时器
3.代码
- 项目地址:v-scroll-demo
function autoScroll(el) {
//找到容器装载文本的容器
var content_box = el.querySelector('span')
//计算容器宽度
var wrap_width = el.clientWidth
//console.log('容器宽度 = ', wrap_width)
//console.log('文本宽度 = ', content_box.clientWidth)
//判断内容是否溢出
if (content_box.clientWidth > wrap_width) {
//如果内容移除
//外层容器超出隐藏
el.style.overflow = 'hidden'
var now_position = 0 //当前位置 默认0
var direction = 'left' //移动方向 一开始向左移动,到顶后向右移动
var target = wrap_width - content_box.clientWidth //向左移动时,到哪个位置就返回
var rest_time = 40 //动画暂停时间
//使用定时器实时修改位移
var timer = setInterval(() => {
//判断是否处于暂停状态 只有不是暂时状态才进行移动
if (rest_time <= 0) {
//方向判断
if (direction == 'left') {
now_position--
} else {
now_position++
}
//如果左移到底 则调转方向向右
if (now_position < target) {
direction = 'right'
//重置暂停动画的时间
rest_time = 20
}
//如果右移到底 则调转方向向左 并暂停一段时间
if (now_position > 0) {
direction = 'left'
//重置暂停动画的时间
rest_time = 40
}
//更新位置
content_box.style.transform = `translateX(${now_position}px)`
}
//减少暂时状态的时间
if(rest_time > 0){
rest_time--
}
}, 50)
//console.log('定时器id = ', timer)
//将定时器id挂载到容器中
el.scroll_id = timer
} else {
//定时器id
el.scroll_id = null
}
}
//Vue指令注册
Vue.directive('scroll', {
// 当被绑定的内容插入到 DOM 中时……
inserted: function (el, binding) {
//创建容器装载文本
var content_box = document.createElement('span')
content_box.style.display = 'inline-block'
//不允许换行
content_box.style.whiteSpace = 'nowrap'
//将内容填入容器中
content_box.innerHTML = binding.value
//将文本容器添加到元素中
el.appendChild(content_box)
//开启功能
autoScroll(el)
},
update: function (el, binding) {
//找到定时器id
var timer = el.scroll_id
console.log('定时器id = ', timer)
//清除定时器
clearInterval(timer)
//找到容器装载文本的容器
var content_box = el.querySelector('span')
//文本替换
content_box.innerHTML = binding.value
//样式重置
content_box.style.transform = `translateX(0)`
//开启功能
autoScroll(el)
}
})
4.使用方法
- 当前标签使用v-scroll指令传值
- 设定固定的容器宽度,当前标签不要设定padding,如果需要,那就在外面再包一层
<div v-scroll="msg" style="width:200px;"></div>