vue实现弧形轮播图,动态数据,固定元素个数

实现弧形轮播图,无论多少数据,都在固定的几个元素上切换,不影响渲染性能

只考虑数据在六个以上,六个以下的需要自己考虑。

<template>
  <div class="venue-wrap">
    <div class="nav-wrap">
      <span
        class="prev"
        @click="prevItem"
      ></span>
      <span
        class="next"
        @click="nextItem"
      ></span>
      <ul
        class="nav-list"
        ref="nav"
      >
        <li
          v-for="(item, index) in showData"
          :key="index"
          class="item"
          :class="'item'+index"
        >
          {{showData[index].name}}
        </li>
      </ul>
    </div>
  </div>
</template>

<script>
export default {
  components: {

  },
  props: {

  },
  data () {
    return {
      navList: [
        {
          name: '场馆1',
          id: 1
        },
        {
          name: '场馆2',
          id: 2
        },
        {
          name: '场馆3',
          id: 3
        },
        {
          name: '场馆4',
          id: 4
        },
        {
          name: '场馆5',
          id: 5
        },
        {
          name: '场馆6',
          id: 6
        },
        {
          name: '场馆7',
          id: 7
        },
        {
          name: '场馆8',
          id: 8
        },
        {
          name: '场馆9',
          id: 9
        },
        {
          name: '场馆10',
          id: 10
        }
      ],
      showData: [],
      positionArr: [],
      itemArr: [],
      num: 0,
      preActive: 6,
      nextActive: 0
    };
  },
  computed: {

  },
  created () {

  },
  mounted () {
    this.nextActive = this.navList.length;
    // this.navList = [...this.navList, ...this.navList];
    this.showData = Array.from(this.navList.filter((item, index) => {
      if (index < 6) {
        return item;
      }
    }));
    this.$nextTick(() => {
      this.init();
    });
  },
  watch: {

  },
  methods: {
    init () {
      this.positionArr = [];
      let oPic = this.$refs.nav;
      this.itemArr = oPic.getElementsByTagName('li');
      for (let i = 0; i < this.itemArr.length; i++) {
        this.positionArr.push([
          parseInt(this.getStyle(this.itemArr[i], 'left')),
          parseInt(this.getStyle(this.itemArr[i], 'top')),
          parseFloat(this.getStyle(this.itemArr[i], 'opacity')),
          this.itemArr[i].offsetWidth
        ]);
      }
    },
    getStyle (obj, name) {
      if (obj.currentStyle) {
        return obj.currentStyle[name];
      } else {
        return getComputedStyle(obj, false)[name];
      }
    },
    prevItem () {
      if (this.num === this.showData.length) {
        this.num = 0;
      }
      if (this.preActive === this.navList.length) {
        this.preActive = 0;
      }
      if (this.nextActive === this.navList.length) {
        this.nextActive = 0;
      }
      this.showData.splice(this.num, 1, this.navList[this.preActive]);
      this.num++;
      this.preActive++;
      this.nextActive++;
      this.$nextTick(() => {
        this.positionArr.unshift(this.positionArr[this.positionArr.length - 1]);
        this.positionArr.pop();
        for (let i = 0; i < this.itemArr.length; i++) {
          this.startMove(this.itemArr[i], {
            left: this.positionArr[i][0],
            top: this.positionArr[i][1],
            opacity: this.positionArr[i][2]
          });
        }
      });
    },
    nextItem () {
      if (this.num === 0) {
        this.num = this.showData.length;
      }
      if (this.nextActive === 0) {
        this.nextActive = this.navList.length;
      }
      if (this.preActive === 0) {
        this.preActive = this.navList.length;
      }
      this.num--;
      this.preActive--;
      this.nextActive--;
      this.showData.splice(this.num, 1, this.navList[this.nextActive]);
      this.$nextTick(() => {
        this.positionArr.push(this.positionArr[0]);
        this.positionArr.shift();
        for (let i = 0; i < this.itemArr.length; i++) {
          this.startMove(this.itemArr[i], {
            left: this.positionArr[i][0],
            top: this.positionArr[i][1],
            opacity: this.positionArr[i][2]
          });
        }
      });
    },
    startMove (obj, json) {
      for (let attr in json) {
        let cur = 0;
        if (attr === 'opacity') {
          cur = Math.round(parseFloat(this.getStyle(obj, attr)) * 100);
        } else {
          cur = parseInt(this.getStyle(obj, attr));
        }
        let speed = (json[attr] - cur);
        speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed);
        if (attr === 'opacity') {
          obj.style.opacity = cur + speed;
        } else {
          obj.style[attr] = cur + speed + 'px';
        }
      }
    }
  }
};
</script>

<style scoped lang="scss">
$url: '~@/assets/images/importantEvent/';
.venue-wrap {
  position: relative;
  z-index: 10;
  height: 100%;
  .nav-wrap {
    position: relative;
    height: 100%;
    padding-top: 268px;
    .prev,
    .next {
      position: absolute;
      width: 66px;
      height: 66px;
      top: 450px;
      background: rgba(0, 186, 255, 0.1);
      border-radius: 50%;
      background-repeat: no-repeat no-repeat;
      background-position: center center;
      border: 1px solid transparent;
      cursor: pointer;
      &:hover {
        border-color: #00baff;
      }
    }
    .prev {
      background-image: url($url+'home/icon_banner_left.png');
      left: 150px;
    }
    .next {
      background-image: url($url+'home/icon_banner_right.png');
      right: 150px;
    }
    .nav-list {
      position: relative;
      width: 1202px;
      height: 100%;
      margin: 0 auto;
      overflow: hidden;
    }
    .item {
      position: absolute;
      width: 263px;
      height: 324px;
      background-image: url($url+'venueSecurity/border_out.png');
      background-repeat: no-repeat no-repeat;
      background-size: 100% 100%;
      transition: all 0.5s;
      left: -313px;
      top: 424px;
      opacity: 0;
      &.item0 {
        left: -313px;
        top: 424px;
        opacity: 0;
      }
      &.item1 {
        left: 0;
        top: 82px;
        opacity: 1;
      }
      &.item2 {
        left: 313px;
        top: 0;
        opacity: 1;
      }
      &.item3 {
        left: 626px;
        top: 0;
        opacity: 1;
      }
      &.item4 {
        left: 939px;
        top: 82px;
        opacity: 1;
      }
      &.item5 {
        left: 1252px;
        top: 424px;
        opacity: 0;
      }
    }
  }
}
</style>

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。