<template>
<div>
<div class="demo">
<notice-bar :text="text"></notice-bar>
</div>
</div>
</template>
<script>
import NoticeBar from "./components/notice-bar"
export default {
components: {
NoticeBar,
},
data() {
return {
text: "在代码阅读过程中人们说脏话的频率是衡量代码质量的唯一标准。而开始一不舒服在大黄蜂很纠结的好哦尽量降低妇女 啊hi弗拉啊发来拉动房价弗里达解放军尽快。"
}
}
}
</script>
<style scoped>
.demo {
width: 800px;
margin: 0 auto;
}
</style>
通过开启定时器setInterval配合css3的 transfrom: translateX()实现。
<template>
<div class="my-outbox" ref="wrap">
<div class="my-inbox" ref="content">
<div class="my-list">
{{ text }}
</div>
</div>
</div>
</template>
<script>
export default {
name: "NoticeBar",
props: {
text: {
Type: String,
default: ""
}
},
data() {
return {
wrapWidth: 0,
contentWidth: 0,
};
},
activated() {
// keep-alive 缓存的组件,在重新激活的时候,必须要重新触发滚动,不然会停止不动了。
this.start();
},
created() {},
mounted() {
this.start();
},
methods: {
start() {
const { wrap, content } = this.$refs;
this.wrapWidth = wrap.getBoundingClientRect().width;
this.contentWidth = content.getBoundingClientRect().width;
this.animateFn();
},
animateFn() {
const { content } = this.$refs;
let distance = this.wrapWidth;
content.style.transform = "translateX(" + distance + "px)"; //初始值
let that = this
setInterval(function() {
distance = distance - 1;
if (-distance >= that.contentWidth) {
distance = that.wrapWidth;
}
content.style.transform = "translateX(" + distance + "px)";
}, 20); //控制速度
}
},
// 更新的时候运动
updated: function() {
this.animateFn();
}
};
</script>
<style lang="scss" scoped>
.my-outbox {
color: #d7bc8d;
overflow: hidden;
height: 35px;
background: #422b02;
position: relative;
.my-inbox {
white-space: nowrap;
position: absolute;
font-size: 0;
.my-list {
margin-right: 25px;
display: inline-block;
font-size: 13px;
height: 35px;
line-height: 35px;
}
}
}
</style>
通过window.requestAnimationFrame配合transform:translateX()实现,
当然了,该组件并未彻底完成,插槽,未添加。
<template>
<div ref="wrap" class="bar-wrap" :style="barStyle" role="marquee">
<div
ref="content"
class="content"
:style="contentStyle"
@transitionend="onTransitionEnd"
>
{{ text }}
</div>
</div>
</template>
<script>
var lastTimeStamp = new Date().getTime();
function fallback(fn) {
let currTimeStamp = new Date().getTime();
let delay = Math.max(0, 16 - (currTimeStamp - lastTimeStamp));
let handle = setTimeout(function() {
fn(currTimeStamp);
}, delay);
lastTimeStamp = currTimeStamp;
return handle;
}
function doubleRaf(fn) {
raf(() => {
raf(fn);
});
}
function raf(fn) {
// 在requestAnimationFrame不可用的时候,使用自定义的fallback来模拟
const iRaf = window.requestAnimationFrame || fallback;
return iRaf.call(window, fn);
}
export default {
name: "NoticeBar",
props: {
text: {
type: String,
default: ""
},
color: {
type: String,
default: "#000"
},
leftIcon: {
type: String,
default: ""
},
background: {
type: String,
default: ""
},
delay: {
type: [Number, String],
default: 1
},
speed: {
type: [Number, String],
default: 50
}
},
data() {
return {
show: true,
offset: 0,
duration: 0,
wrapWidth: 0,
contentWidth: 0,
};
},
computed: {
barStyle() {
return {
color: this.color,
background: this.background
};
},
contentStyle() {
return {
transform: this.offset ? `translateX(${this.offset}px)` : "",
transitionDuration: this.duration + "s",
transitionTimingFunction: "linear"
};
}
},
watch: {
scrollable: "start",
text: {
handler: "start",
immediate: true
}
},
activated() {
// this.start();
},
created() {
this.start();
},
mounted() {},
methods: {
onTransitionEnd() {
this.offset = this.wrapWidth;
this.duration = 0;
// wait for Vue to render offset
this.$nextTick(() => {
// use double raf to ensure animation can start
doubleRaf(() => {
this.offset = -this.contentWidth;
this.duration = (this.contentWidth + this.wrapWidth) / this.speed;
this.$emit("replay");
});
});
},
reset() {
this.offset = 0;
this.duration = 0;
this.wrapWidth = 0;
this.contentWidth = 0;
},
start() {
const delay = this.delay * 1000;
this.reset();
setTimeout(() => {
const { wrap, content } = this.$refs;
if (!wrap || !content) {
return;
}
const wrapWidth = wrap.getBoundingClientRect().width;
const contentWidth = content.getBoundingClientRect().width;
if (contentWidth > wrapWidth) {
doubleRaf(() => {
this.offset = -contentWidth;
this.duration = contentWidth / this.speed;
this.wrapWidth = wrapWidth;
this.contentWidth = contentWidth;
});
}
}, delay);
}
}
};
</script>
<style lang="scss" scoped>
.bar-wrap {
height: 35px;
overflow: hidden;
position: relative;
background: #422b02;
line-height: 35px;
}
.content {
white-space: nowrap;
position: absolute;
color: #d7bc8d;
}
</style>