横向
组件代码
<!--
* @Author:
* @Date: 2024-03-21 19:21:58
* @LastEditTime: 2024-03-21 20:31:50
* @LastEditors: Please set LastEditors
* @Description: 消息左右滚动
-->
<template>
<div
id="textScroll"
class="text-scroll"
@mousemove="inBox"
@mouseleave="leaveBox"
>
<div
v-for="i in 2"
:id="'scrollItem' + i"
:key="'scrollItem' + i"
class="scroll-item"
:style="{ display: i === 1 ? 'flex' : 'none' }"
>
<slot></slot>
</div>
</div>
</template>
<script>
export default {
components: {},
data() {
return {
left: 0,
textScrollDiv: null,
timer: null,
scrollItemWidth: 0,
isScroll: false,
};
},
computed: {},
destroyed() {
clearInterval(this.timer);
},
mounted() {
const that = this;
this.$nextTick(() => {
// 父盒子
that.textScrollDiv = document.querySelector("#textScroll");
// 滚动盒子宽度
that.scrollItemWidth = document.querySelector("#scrollItem1").clientWidth;
// 父盒子宽度
const outerBoxWidth = that.textScrollDiv.clientWidth;
// 如果滚动内容超长 则开始滚动
if (outerBoxWidth < that.scrollItemWidth) {
this.isScroll = true;
// 将父盒子的宽度变成 滚动内容盒子的两倍 刚好显示两个滚动内容盒子
that.textScrollDiv.style.width = `${that.scrollItemWidth * 2}px`;
// 设置定时开始滚动
that.timer = setInterval(function () {
that.moveLeft();
}, 30);
// 显示滚动内容第二个
document.querySelector("#scrollItem2").style.display = "flex";
}
});
},
methods: {
moveLeft() {
if (this.textScrollDiv) {
this.left -= 1;
if (Math.abs(this.left) > this.scrollItemWidth) {
this.left = 0;
}
this.textScrollDiv.style.transform = `translate(${this.left}px, 0px)`;
}
},
// 鼠标划入区域
inBox() {
if (this.isScroll) {
clearInterval(this.timer);
this.timer = null;
}
},
// 鼠标离开区域
leaveBox() {
if (this.isScroll) {
const that = this;
this.timer = setInterval(function () {
that.moveLeft();
}, 30);
}
},
},
};
</script>
<style lang="less" scoped>
.text-scroll {
display: flex;
flex-wrap: nowrap;
transition: all 0ms ease-in 0s;
.scroll-item {
display: flex;
flex-wrap: nowrap;
}
}
</style>
纵向
组件代码
<!--
* @Author:
* @Date: 2024-03-21 19:21:58
* @LastEditTime: 2024-03-21 20:31:50
* @LastEditors: Please set LastEditors
* @Description: 消息左右滚动
-->
<template>
<div class="scroll-box" :class="{ boxScroll: enterBoxFlag }">
<div
id="textScrollVertical"
class="text-scroll"
@mouseleave="leaveBox"
@mouseenter="enterBox"
>
<div
v-for="i in 2"
:id="'scrollVerticalItem' + i"
:key="'scrollVerticalItem' + i"
class="scroll-item"
:style="{ display: i === 1 ? 'flex' : 'none' }"
>
<slot></slot>
</div>
</div>
</div>
</template>
<script>
export default {
components: {},
data() {
return {
top: 0,
textScrollDiv: null,
timer: null,
scrollItemHeight: 0,
isScroll: false,
enterBoxFlag: false,
};
},
computed: {},
destroyed() {
clearInterval(this.timer);
},
mounted() {
const that = this;
this.$nextTick(() => {
// 父盒子
that.textScrollDiv = document.querySelector("#textScrollVertical");
// 滚动盒子宽度
that.scrollItemHeight = document.querySelector(
"#scrollVerticalItem1"
).clientHeight;
// 父盒子宽度
const outerBoxHeight = that.textScrollDiv.clientHeight;
console.log(that.scrollItemHeight, outerBoxHeight);
// 如果滚动内容超长 则开始滚动
if (outerBoxHeight < that.scrollItemHeight) {
this.isScroll = true;
// 将父盒子的宽度变成 滚动内容盒子的两倍 刚好显示两个滚动内容盒子
that.textScrollDiv.style.heigh = `${that.scrollItemHeight * 2}px`;
// 设置定时开始滚动
that.timer = setInterval(function () {
that.moveTop();
}, 30);
// 显示滚动内容第二个
document.querySelector("#scrollVerticalItem2").style.display = "flex";
}
});
},
methods: {
moveTop() {
if (this.textScrollDiv) {
this.top -= 1;
if (Math.abs(this.top) > this.scrollItemHeight) {
this.top = 0;
}
this.textScrollDiv.style.transform = `translate(0px, ${this.top}px)`;
}
},
// 鼠标划入区域
// inBox() {
// if (this.isScroll) {
// clearInterval(this.timer);
// this.timer = null;
// }
// },
// 鼠标hover出现滚动条 滚动暂停 鼠标移除 重新开始滚动
enterBox() {
console.log("enterbox");
this.enterBoxFlag = true;
if (this.isScroll) {
clearInterval(this.timer);
this.timer = null;
}
},
// 鼠标离开区域
leaveBox() {
console.log("leaveBox");
this.enterBoxFlag = false;
if (this.isScroll) {
const that = this;
this.timer = setInterval(function () {
that.moveTop();
}, 30);
}
},
},
};
</script>
<style lang="less" scoped>
.text-scroll {
display: flex;
flex-wrap: nowrap;
height: 100%;
flex-direction: column;
transition: all 0ms ease-in 0s;
.scroll-item {
display: flex;
flex-direction: column;
flex-wrap: nowrap;
}
}
.scroll-box {
width: 100%;
height: 500px;
border: 1px solid red;
overflow: hidden;
.info-item {
position: relative;
margin-right: 32px;
font-weight: 500;
height: 60px;
white-space: nowrap;
&:hover {
color: rgba(0, 128, 255, 1);
cursor: pointer;
}
}
}
.boxScroll {
overflow-y: auto !important;
}
</style>
使用代码
<template>
<div class="change-cls">
<div class="title">
无缝滚动 相比于swiper组件使用的vue-seamless-scroll 这个来说更好用
</div>
<div class="title">
自动判断超出滚动 不超出不滚动 以及可以不被截取不需要设置最小滚动数量
</div>
<div v-if="noticeInfo && noticeInfo.length > 0" class="notice-plate">
<div class="plate-body">
<div class="plate-icon">
<i></i> // 这里可以放个小图标
</div>
<div class="plate-info" @click="handleInfo($event)">
<textScroll>
<div
v-for="(item, i) in noticeInfo"
:key="'notice' + i"
class="info-item"
:data-my-id="item.id"
>
{{ item.title }}
<div v-if="i < noticeInfo.length - 1" class="line-split"></div>
</div>
</textScroll>
</div>
</div>
</div>
<div v-if="noticeInfo && noticeInfo.length > 0" class="notice-plate">
<textScrollVertical>
<div
v-for="(item, i) in noticeInfo"
:key="'notice' + i"
class="info-item"
:data-my-id="item.id"
>
<div class="item">
{{ item.title }}
</div>
</div>
</textScrollVertical>
</div>
</div>
</template>
<script>
import textScroll from "../../components/text-scroll/index.vue";
import textScrollVertical from "../../components/text-scroll/vertical-index.vue";
export default {
name: "",
components: { textScroll, textScrollVertical },
mixins: [],
props: {},
computed: {},
watch: {},
data() {
return {
value1: "",
noticeInfo: [
{
title: "啊啊啊啊啊啊啊啊啊啊啊啊1",
},
{
title: "啊啊啊啊啊啊啊啊啊啊啊啊2",
},
{
title: "啊啊啊啊啊啊啊啊啊啊啊啊3",
},
{
title: "啊啊啊啊啊啊啊啊啊啊啊啊4",
},
{
title: "啊啊啊啊啊啊啊啊啊啊啊啊5",
},
{
title: "啊啊啊啊啊啊啊啊啊啊啊啊6",
},
{
title: "啊啊啊啊啊啊啊啊啊啊啊啊7",
},
{
title: "啊啊啊啊啊啊啊啊啊啊啊啊8",
},
{
title: "啊啊啊啊啊啊啊啊啊啊啊啊9",
},
{
title: "啊啊啊啊啊啊啊啊啊啊啊啊10",
},
{
title: "啊啊啊啊啊啊啊啊啊啊啊啊11",
},
{
title: "啊啊啊啊啊啊啊啊啊啊啊啊12",
},
{
title: "啊啊啊啊啊啊啊啊啊啊啊啊13",
},
],
};
},
created() {},
mounted() {},
methods: {
handleInfo(e) {
console.log("handleInfo", e);
},
},
};
</script>
<style lang="scss" scoped>
/* stylelint-disable */
.change-cls {
height: 100%;
}
.title {
font-size: 18px;
font-weight: 600;
margin-bottom: 20px;
}
.notice-plate {
width: 1328px;
margin: 0 auto;
margin-top: 24px;
.plate-body {
display: flex;
align-items: flex-start;
width: 100%;
height: 48px;
padding: 10px 16px;
margin-left: -64px;
background: white;
border: 1px solid rgba(0, 0, 0, 0.1);
border-radius: 4px 4px 4px 4px;
.plate-icon {
width: 28px;
height: 28px;
margin-right: 16px;
line-height: 28px;
color: rgba(255, 143, 31, 1);
text-align: center;
background: rgb(255, 247, 241);
border-radius: 4px 4px 4px 4px;
}
.plate-info {
width: calc(100% - 112px);
height: 28px;
overflow: hidden;
line-height: 28px;
.info-item {
position: relative;
margin-right: 32px;
font-weight: 500;
white-space: nowrap;
&:hover {
color: rgba(0, 128, 255, 1);
cursor: pointer;
}
}
.line-split {
position: absolute;
top: 6px;
right: -16px;
width: 2px;
height: 12px;
border-right: 1px solid rgba(217, 217, 217, 1);
}
}
.plate-more {
height: 28px;
margin-left: 16px;
font-size: 14px;
line-height: 28px;
color: red;
cursor: pointer;
i {
margin-left: 4px;
}
}
}
.scroll-box {
width: 100%;
height: 32px;
border: 1px solid red;
overflow: hidden;
.info-item {
position: relative;
margin-right: 32px;
font-weight: 500;
height: 32px;
white-space: nowrap;
line-height: 32px;
&:hover {
color: rgba(0, 128, 255, 1);
cursor: pointer;
}
}
}
}
</style>