<template>
<div id="m-marquee" class="zzui-broadcast-window" :style="{height: height + 'px'}">
<ul class="zzui-broadcast-container" ref="container">
<slot></slot>
</ul>
<ul class="zzui-broadcast-container" ref="containerCopy">
<slot></slot>
</ul>
</div>
</template>
<script>
export default{
data (){
return {
height: '',
visibleLiNum:1,
length: 0,
currentIndex: 0
}
},
props: {
interval: {
type: Number,
default: 3000 //ms
},
duration: {
type: Number,
default: 600 //ms
},
liHeight: {
type: Number,
default: 0 //px
},
dHeight: {
type: Number,
default: 0 //px
},
direction: {
validator (val){
return val === 'up' || val === 'down';
},
default: 'up'
}
},
mounted (){
this.dealAppendNum();
},
methods: {
initScroll(){
let area = document.getElementById('m-marquee');
let ul1 = this.$refs.container;
let ul2 = this.$refs.containerCopy;
area.scrollTop= 0;
ul2.innerHTML = ul1.innerHTML;
},
/*
* 根据方向将第一个或最后一个item复制添加到列表最后或前面,保证下一次轮播连贯
* 将单个item高度设置为广播视窗高度
*/
fixList (){
let cloneNode,
firstItem = this.$refs.container.firstElementChild;
let children = this.makeArray(this.$refs.container.children);
let appendUpChildren = children.slice(0,this.visibleLiNum);
let appendDownChildren = children.slice(-this.visibleLiNum);
// 根据item高度设置视窗container高度
this.length = this.$refs.container.children.length;
if(this.direction === 'up'){
// 向上则clone第一个item置于列表末端
for(let i=0; i< appendUpChildren.length; i++ ){
cloneNode = appendUpChildren[i].cloneNode(true);
this.$refs.container.appendChild(cloneNode);
}
}else{
for(let i = appendDownChildren.length-1; i>=0; i-- ) {
// 向下则clone最后一个item置于列表首部
cloneNode = appendDownChildren[i].cloneNode(true);
this.$refs.container.insertBefore(cloneNode, firstItem);
}
}
this.$nextTick(()=>{
// 用总高度/length,减小较小
this.height = this.$refs.container.offsetHeight / (this.length + 1);
});
},
dealAppendNum(){
this.visibleLiNum = 1; //容器高度能放下几个li
if(this.liHeight && +this.liHeight>0) {
this.$nextTick(()=>{
// 用总高度/length,减小较小
});
this.visibleLiNum = parseInt((+this.dHeight)/(+this.liHeight)) ;
}
let children = this.$refs.container.children;
if (this.visibleLiNum >= children.length){
return; //内容较少,不需要滚动
}
else {
this.fixList();
this.start();
}
},
makeArray(obj){
return Array.prototype.slice.call(obj,0);
},
/*
* 启动轮播
*/
start (){
let currenTransitionTime,
currenTranslateY;
// 方向向下,列表初始时跳转到最后item
if(this.direction === 'down')this.quickJump(false);
setInterval(()=>{
if(this.direction === 'up'){
this.currentIndex += 1;
}else{
this.currentIndex -= 1;
}
// 正常轮播transition时间为用户设置duration时间
// 1.匀速
currenTransitionTime = 'transform ' + this.duration+ 'ms linear';
// 2.每条有停顿
// currenTransitionTime = 'transform ' + this.duration+ 'ms ease-in-out';
this.setTransition(this.$refs.container, currenTransitionTime);
// 正常轮播每次currenTranslateY增加一个item高度
if(this.direction === 'up'){
currenTranslateY = -this.currentIndex * this.height + 'px';
}else{
currenTranslateY = - (this.currentIndex + 1) * this.height + 'px';
}
this.setTransform(this.$refs.container, 'translate3d(0,' + currenTranslateY + ',0)');
// 当滑动到首尾边界替补item时,需即刻跳转到正确item位置
if(this.currentIndex == this.length){
setTimeout(()=>{
this.quickJump(true);
}, this.duration/2.5);
}else if(this.currentIndex == -1){
setTimeout(()=>{
this.quickJump(false);
}, this.duration/2.5);
}
}, this.interval + this.duration);
},
/*
* 设置transition 0ms,再设置translatet位置启动跳转
* 由于跳转前后展现的内容完全一样,肉眼看不到跳转过程
*/
quickJump (toFirst){
let currenTranslateY,
currenTransitionTime = 'transform 0ms linear';
// currenTransitionTime = 'transform 0ms ease-in-out';
this.setTransition(this.$refs.container, currenTransitionTime);
if(toFirst){
// 跳转到首个item
this.currentIndex = 0;
currenTranslateY = '0px';
}else{
this.currentIndex = this.length - 1;
currenTranslateY = - (this.currentIndex + 1) * this.height + 'px';
}
this.setTransform(this.$refs.container, 'translate3d(0,' + currenTranslateY + ',0)');
},
/*
* transition添加浏览器前缀
* transform同
*/
setTransition (ele, val){
ele.style.transition = val;
ele.style.WebkitTransition = '-webkit-' + val;
ele.style.MozTransition = '-moz-' + val;
ele.style.OTransition = '-o-' + val;
},
setTransform (ele, val){
ele.style.transform = val;
ele.style.WebkitTransform = val;
ele.style.MozTransform = val;
ele.style.OTransform = val;
}
}
}
</script>
<style lang="less">
.zzui-broadcast-window{
width: 100%;
overflow: hidden;
transform: translateZ(0);
height: 100%;
.zzui-broadcast-container{
padding: 0;
margin: 0;
width: 100%;
height: auto;
li{
margin: 0;
}
}
}
</style>