Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

原生JS实现轮播图 #120

Open
louzhedong opened this issue Jan 16, 2019 · 1 comment
Open

原生JS实现轮播图 #120

louzhedong opened this issue Jan 16, 2019 · 1 comment

Comments

@louzhedong
Copy link
Owner

轮播图是在前端交互中运用的非常多的一个功能,基本上所有的网站都会有类似的需求,而轮播图的实现方式也是有许许多多的,在这里我写一个我认为比较简单,而且效率比较高的轮播图功能。

实现原理

使用绝对定位,将图片分为四类,分别为前面,后面,左边,右边,四种类型的图片组成了一个环,每次图片循环时,改变对应图片的class,并在class中用css 加上过渡动画,实现一个循环播放的效果

在线demo

具体的实现代码

// html
<div class="music-carousal"></div>

// css
.music-carousal {
  height: 250px;
  position: relative;
	margin-top:30px;
}

.banner-list {
  position: absolute;
  width: 460px;
  height: 250px;
  left: 50%;
  margin-left: -230px;
  z-index: 3;
}

.banner-list .banner-item {
  position: absolute;
  width: 100%;
  height: 100%;
  transition: all 0.5s ease;
}

.banner-list .banner-item-out {
  transform: rotateY(0) translateX(0) translateZ(0) scale(.7);
  opacity: 0;
  z-index: -1;
}

.banner-list .banner-item-current {
  transform: rotateY(0) translateX(0) translateZ(0);
  z-index: 5;
}

.banner-list .banner-item-prev {
  z-index: 3;
  transform: rotateY(30deg) translate3d(-140px, -15px, -200px) scale(.7);
  opacity: 0.7;
}

.banner-list .banner-item-next {
  z-index: 3;
  transform: rotateY(-30deg) translate3d(140px, -15px, -200px) scale(.7);
  opacity: 0.7;
}

.banner-list .banner-item img {
  width: 100%;
  box-shadow: 0 8px 10px 0 rgba(88, 10, 0, 0.2);
  border-radius: 3px;
}

.pagination-box {
  position: absolute;
  bottom: 50px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 5;
}

.pagination-box .pagination-item {
  width: 8px;
  height: 8px;
  background: #E2E2E3;
  border-radius: 50%;
  display: inline-block;
  margin: 0 3px;
}

.pagination-box .pagination-item.active {
  background: #D71417;
}

// javascript
let currentIndex = 1; // 当前是在第几个
  let timer;

  const carousal = {
    init: function (object) {
      const { el, banners, interval } = object;

      // banner至少为3个
      const length = banners.length;
      if (length === 1) {
        banners.push(banners[0]);
        banners.push(banners[0])
      }
      if (length === 2) {
        banners.push(banners[0]);
      }
      this._render(el, banners);
      timer = setInterval(this._next.bind(this), interval);
      this.listenPaginationTouch.apply(this);
    },

    _render: function (el, banners) {
      const imgUl = document.createElement('div');
      imgUl.className = 'banner-list';
      let imgUlInnerHTML = '';

      const paginationBox = document.createElement('div');
      paginationBox.className = 'pagination-box';
      let paginationBoxInnerHTML = '';

      banners.forEach((item, index) => {
        imgUlInnerHTML += `<div class="banner-item ${index === 0 ? 'banner-item-prev' : ''} ${index === 1 ? 'banner-item-current' : ''} ${index === 2 ? 'banner-item-next' : ''} ${index > 2 ? 'banner-item-out' : ''}"><img src="${item.imageUrl}"></div>`;

        paginationBoxInnerHTML += `<div class="pagination-item index-${index} ${index === currentIndex ? 'active' : ''}"></div>`
      });
      imgUl.innerHTML = imgUlInnerHTML;
      paginationBox.innerHTML = paginationBoxInnerHTML;
      el.appendChild(imgUl);
      el.appendChild(paginationBox);
    },

    // 右边的那个图片变成当前的大图
    _next: function () {
      let bannerList = document.querySelectorAll('.banner-item');
      let length = bannerList.length;
      currentIndex = (currentIndex + 1) % length;
      this._changeNextOrder(currentIndex);
      this._renderPagination(currentIndex);
    },

    // 向右交换顺序
    _changeNextOrder: function (_currentIndex) {
      let bannerList = document.querySelectorAll('.banner-item');
      let length = bannerList.length;

      bannerList.forEach((item, index) => {
        if (index === _currentIndex) {
          item.className = 'banner-item banner-item-current'
        } else if (index === ((_currentIndex - 1 + length) % length)) {
          item.className = 'banner-item banner-item-prev'
        } else if (index === ((_currentIndex + 1) % length)) {
          item.className = 'banner-item banner-item-next'
        } else {
          item.className = 'banner-item banner-item-out'
        }
      })
    },

    _renderPagination: function (_currentIndex) {
      let paginationList = document.querySelectorAll('.pagination-item');
      paginationList.forEach((item, index) => {
        if (index === _currentIndex) {
          item.classList.add('active');
        } else {
          item.classList.remove('active');
        }
      })
    },

    // 监听小圆点按钮点击
    listenPaginationTouch: function () {
      let paginationBox = document.querySelector('.pagination-box');
      paginationBox.addEventListener('click', (event) => {
        const target = event.target;
        if (target.classList.contains('pagination-item')) {
          try {
            let className = target.classList[1];
            let index = Number(className.split('-')[1]);
            this._changeNextOrder(index);
            this._renderPagination(index);
            currentIndex = index;
            clearInterval(timer);
            timer = setInterval(this._next.bind(this), 5000);
          } catch (error) {
            throw new Error(error);
          }
        }
      })
    }
  }
	
const carousalDom = document.querySelector('.music-carousal');
const banners = [
	{
		imageUrl: "http://p1.music.126.net/nHJXJZVMsSpi3v1ee8B8XA==/109951163797188493.jpg"
	},
	{
		imageUrl: "http://p1.music.126.net/iCrkUC8x7ViQwLULtgqkqw==/109951163797194143.jpg"
	},
	{
		imageUrl: "http://p1.music.126.net/2Jih8vXjnTeIzxtPU-gQiw==/109951163797164224.jpg"
	},
	{
		imageUrl: "http://p1.music.126.net/c1OhLIjnd9zB8NBUc3Olqg==/109951163797172654.jpg"
	},
	{
		imageUrl: "http://p1.music.126.net/SWjJnQTGa6vhBOzKrkR6wA==/109951163797179161.jpg"
	},
	{
		imageUrl: "http://p1.music.126.net/Wa9ENrBphVjH46A6Kt8yiA==/109951163797159700.jpg"
	}
]
carousal.init({
	el: carousalDom,
  banners,
  interval: 5000
});
@sxbo
Copy link

sxbo commented Dec 31, 2019

image
牛逼,看这段尽然看懂了,bind和apply的作用,以及二者的微妙差别

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants