在VueJS中使用按钮进行水平滚动

时间:2018-07-07 10:01:10

标签: javascript html css vue.js scroll

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

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

如何使用VueJS达到这种效果?

我已经看过的一些库包括vue-scroll-tojump

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

  • 跳转允许用户滚动显示一定数量的像素,但只能垂直显示,并且只能在窗口上滚动。

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

3 个答案:

答案 0 :(得分:3)

  

我为此做了一个沙盒:see it here

逻辑是这样的:

var heading = google.maps.geometry.spherical.computeHeading(pos1, pos2);

var directionIcon = {
  path: google.maps.SymbolPath.FORWARD_OPEN_ARROW,
  scale: 5,
  rotation: heading
};
if (!endArrowMarker) {
  endArrowMarker = new Marker({
    position: pos2,
    clickable: false,
    icon: directionIcon,
    map: map
  });
} else {
  endArrowMarker.setIcon(directionIcon);
}

您有一个包装,并且您增加/减少了scroll_left() { let content = document.querySelector(".wrapper-box"); content.scrollLeft -= 50; }, scroll_right() { let content = document.querySelector(".wrapper-box"); content.scrollLeft += 40; } 属性

完整代码可在here

中找到

答案 1 :(得分:2)

您只能使用JavaScript,在您给我的示例中,我仅将其转换为JavaScript,这是它的代码笔。

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

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

const rightBtn = document.querySelector('#right-button');
const leftBtn = document.querySelector('#left-button');

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

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

对于动画,您必须使用某些东西...可以做到吗?

答案 2 :(得分:1)

codepen 还有这个例子

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

这里是重要的事情: HTML(哈巴狗)

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"
});

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