使用 VueJS 中的按钮水平滚动



我希望使用 VueJS 中的按钮实现水平滚动。我有一个容器,其中有几个水平堆叠的div,我想使用按钮滚动浏览它们。

这是 SO 上用于 JQuery 的相同线程。此演示是 JQuery 中的解决方案。它应该说明我所追求的效果。

如何使用 VueJS 实现这种效果?

我已经看过的一些库包括 vue-scroll-to 和 jump。

  • Vue-scroll-to 要求用户指定要滚动到的元素,而我想在特定元素内水平滚动一定数量的像素。

  • 跳转允许在定义的像素量上滚动,但只能垂直工作,并且似乎只在窗口上滚动。

编辑:我找到了一个在VanillaJS中完成此操作的小库:https://github.com/tarun-dugar/easy-scroll

我为此做了一个沙盒:在这里看到它

逻辑是这样的:

scroll_left() {
let content = document.querySelector(".wrapper-box");
content.scrollLeft -= 50;
},
scroll_right() {
let content = document.querySelector(".wrapper-box");
content.scrollLeft += 40;
}

您有一个包装器,并且您增加/减少scrollLeft属性

完整的代码可以在这里找到

你只能使用 JavaScript,使用你给出的示例 我只将其转换为 JavaScript,这是它的 Codepen。

https://codepen.io/immad-hamid/pen/yEmayr

这是可以替换您发送的示例的 JavaScript。

const rightBtn = document.querySelector('#right-button');
const leftBtn = document.querySelector('#left-button');
const content = document.querySelector('#content');
rightBtn.addEventListener("click", function(event) {
content.scrollLeft += 300;
event.preventDefault();
});
leftBtn.addEventListener("click", function(event) {
content.scrollLeft -= 300;
event.preventDefault();
});

对于动画,您必须使用一些东西...你能做到吗?

如果你正在寻找JavaScript本身的水平平滑滚动动画,而不使用任何库。

scrollTobehavior: 'smooth'一起使用

Vue.config.devtools = false;
Vue.config.productionTip = false;
new Vue({
el: '#app',
data: {
scrollAmount: 0,
},
methods: {
scrollLeft: function () {
const menu = this.$refs.menu
menu.scrollTo({
left: this.scrollAmount += 200,
behavior: 'smooth',
})
},
scrollRight: function () {
const menu = this.$refs.menu
menu.scrollTo({
left: this.scrollAmount -= 200,
behavior: 'smooth',
})
}
},
mounted() {}
})
body {
margin: 3em;
}
* {
padding: 0;
margin: 0;
} 
.menu-wrapper {
position: relative;
max-width: 310px;
height: 100px;
margin: 1em auto;
border: 1px solid black;
overflow-x: hidden;
overflow-y: hidden;
}
.menu   {
height: 120px;
background: #f3f3f3;
box-sizing: border-box;
white-space: nowrap;
overflow-x: auto;
overflow-y: hidden;
}

.item {
display: inline-block;
width: 100px;
height: 100%;
outline: 1px dotted gray;
padding: 1em;
box-sizing: border-box;
}

.paddle {
position: absolute;
top: 0;
bottom: 0;
width: 3em;
}
.left-paddle {
left: 0;
}
.right-paddle {
right: 0;
}
.hidden {
display: none;
}
.print {
margin: auto;
max-width: 500px;
}

span {
display: inline-block;
width: 100px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app" class="menu-wrapper">
<ul class="menu" ref="menu">
<li class="item">1</li>
<li class="item">2</li>
<li class="item">3</li>
<li class="item">4</li>
<li class="item">5</li>
<li class="item">6</li>
<li class="item">7</li>
<li class="item">8</li>
<li class="item">9</li>
<li class="item">10</li>
<li class="item">11</li>
<li class="item">12</li>
<li class="item">13</li>
</ul>

<div class="paddles">
<button class="left-paddle paddle" @click="scrollRight"> -
</button>

<button class="right-paddle paddle" @click="scrollLeft">
>
</button>
</div>

</div>

还有这个来自 codepen 的例子

$ Here's the linkhttps://codepen.io/wa23/pen/pObyrq

以下是重要事项: HTML (pug(

link(href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:200,300,400" rel="stylesheet")

h1 Vue Carousel
script#v-carousel(type="x/template")
.card-carousel-wrapper
.card-carousel--nav__left(
@click="moveCarousel(-1)"
:disabled="atHeadOfList"
)
.card-carousel
.card-carousel--overflow-container
.card-carousel-cards(:style="{ transform: 'translateX' + '(' + currentOffset + 'px' + ')'}")
.card-carousel--card(v-for="item in items")
img(src="https://placehold.it/200x200")
.card-carousel--card--footer
p {{ item.name }}
p.tag(v-for="(tag,index) in item.tag" :class="index > 0 ? 'secondary' : ''") {{ tag }}
.card-carousel--nav__right(
@click="moveCarousel(1)"
:disabled="atEndOfList"
)
#app 
carousel

Css (Scss(

$vue-navy: #2c3e50;
$vue-navy-light: #3a5169;
$vue-teal: #42b883;
$vue-teal-light: #42b983;
$gray: #666a73;
$light-gray: #f8f8f8;

body {
background: $light-gray;
color: $vue-navy;
font-family: 'Source Sans Pro', sans-serif; 
}
.card-carousel-wrapper {
display: flex;
align-items: center;
justify-content: center;
margin: 20px 0 40px;
color: $gray;
}
.card-carousel {
display: flex;
justify-content: center;
width: 640px;

&--overflow-container {
overflow: hidden;
}

&--nav__left,
&--nav__right {
display: inline-block;
width: 15px;
height: 15px;
padding: 10px;
box-sizing: border-box;
border-top: 2px solid $vue-teal;
border-right: 2px solid $vue-teal;
cursor: pointer;
margin: 0 20px;
transition: transform 150ms linear;
&[disabled] {
opacity: 0.2;
border-color: black;
}
}

&--nav__left {
transform: rotate(-135deg);
&:active {
transform: rotate(-135deg) scale(0.9);
}
}

&--nav__right {
transform: rotate(45deg);
&:active {
transform: rotate(45deg) scale(0.9);
}
}
}
.card-carousel-cards {
display: flex;
transition: transform 150ms ease-out;
transform: translatex(0px);

.card-carousel--card {
margin: 0 10px;
cursor: pointer;
box-shadow: 0 4px 15px 0 rgba(40,44,53,.06), 0 2px 2px 0 rgba(40,44,53,.08);
background-color: #fff;
border-radius: 4px;
z-index: 3;
margin-bottom: 2px;

&:first-child {
margin-left: 0;
}

&:last-child {
margin-right: 0;
}

img {
vertical-align: bottom;
border-top-left-radius: 4px;
border-top-right-radius: 4px;
transition: opacity 150ms linear;
user-select: none;

&:hover {
opacity: 0.5;
}
}

&--footer {
border-top: 0;
padding: 7px 15px;

p {
padding: 3px 0;
margin: 0;
margin-bottom: 2px;
font-size: 19px;
font-weight: 500;
color: $vue-navy;
user-select: none;

&.tag {
font-size: 11px;
font-weight: 300;
padding: 4px;
background: rgba(40,44,53,.06);
display: inline-block;
position: relative;
margin-left: 4px;
color: $gray;

&:before {
content:"";
float:left;
position:absolute;
top:0;
left: -12px;
width:0;
height:0;
border-color:transparent rgba(40,44,53,.06) transparent transparent;
border-style:solid;
border-width:8px 12px 12px 0;
}
&.secondary {
margin-left: 0;
border-left: 1.45px dashed white;
&:before {
display: none !important;
}
}

&:after {
content:"";
position:absolute;
top:8px;
left:-3px;
float:left;
width:4px;
height:4px;
border-radius: 2px;
background: white;
box-shadow:-0px -0px 0px #004977;
}
}
}
}
}
}
h1 {
font-size: 3.6em;
font-weight: 100;
text-align: center;
margin-bottom: 0;
color: $vue-teal;
}

.JS

Vue.component("carousel", {
template: "#v-carousel",
data() {
return {
currentOffset: 0,
windowSize: 3,
paginationFactor: 220,
items: [
{name: 'Kin Khao', tag: ["Thai"]},
{name: 'Jū-Ni', tag: ["Sushi", "Japanese", "$$$$"]},
{name: 'Delfina', tag: ["Pizza", "Casual"]},
{name: 'San Tung', tag: ["Chinese", "$$"]},
{name: 'Anchor Oyster Bar', tag: ["Seafood", "Cioppino"]},
{name: 'Locanda', tag: ["Italian"]},
{name: 'Garden Creamery', tag: ["Ice cream"]},
]
}
},
computed: {
atEndOfList() {
return this.currentOffset <= (this.paginationFactor * -1) * (this.items.length - this.windowSize);
},
atHeadOfList() {
return this.currentOffset === 0;
},
},
methods: {
moveCarousel(direction) {
// Find a more elegant way to express the :style. consider using props to make it truly generic
if (direction === 1 && !this.atEndOfList) {
this.currentOffset -= this.paginationFactor;
} else if (direction === -1 && !this.atHeadOfList) {
this.currentOffset += this.paginationFactor;
}
},
}
});
new Vue({
el:"#app"
});

编辑:很抱歉没有尽快回答,因为这些天我很忙

最新更新