console
class Carousel{
current = 0
arr = []
default = {
width: 150,
height: 150,
padding: 25,
previewCount: 5,
speed: 200,
datas: null
}
constructor (selector, options) {
if (!selector) {
return
}
Object.assign(this.default,options)
this.$ele = document.querySelector(selector)
}
init () {
if (this.default.datas.length < this.default.previewCount) {
return
}
this._optimize()
this._createDom()
this._initDom()
}
_optimize () {
const length = this.default.datas.length
const fix = parseInt(this.default.previewCount / 2)
const prefixs = this.default.datas.slice(length - fix,length)
let count = length - this.default.previewCount
let suffixs = []
if (count < fix) {
suffixs = this.default.datas.slice(0, fix - count)
}
this.current = Math.ceil((fix + this.default.previewCount) / 2)
this.$fix = fix
this.default.datas = [...prefixs,...this.default.datas,...suffixs]
}
_createDom () {
const width = (this.default.width + this.default.padding * 2) * this.default.previewCount
this.$ele.style.width = `${width}px`
this.$ele.style.position = 'relative'
this.$ele.style.overflow = 'hidden'
this.$ele.style.padding = '100px 0'
this._createUl()
const length = this.default.datas.length
for (let i = 0; i < length; i++) {
const li = this._createLi(i)
li.appendChild(this._createImg(i))
if (i === this.current) {
li.firstChild.style.filter = 'grayscale(0)'
li.firstChild.style.transform = 'scale(2)'
const bg = li.getAttribute('data-bg')
this.$ele.style.backgroundImage = `url('${bg}')`
this.$ele.style.backgroundRepeat = 'no-repeat'
}
this.$ul.appendChild(li)
}
this.$ele.appendChild(this.$ul)
}
_createUl () {
const width = (this.default.width + this.default.padding * 2) * this.default.datas * 2
this.$ul = document.createElement('ul')
this.$ul.style.width = `${width}px`
this.$ul.style.height = `${this.default.height}px`
this.$ul.style.position = 'relative'
this.$ul.style.listStyleType = 'none'
}
_createLi (index) {
const offset = index - this.$fix
const boxWidth = this.default.width + this.default.padding * 2
this.$offset = boxWidth
const li = document.createElement('li')
li.style.cssFloat = 'left'
li.style.cursor = 'pointer'
li.style.padding = `${this.default.padding}px`
li.style.position = 'absolute'
li.style.top = '0'
li.style.left = `${ offset * boxWidth}px`
li.setAttribute('data-bg',this.default.datas[index].bg)
li.setAttribute('data-index', index)
const self = this
li.addEventListener('click',function () {
const left = parseInt(li.style.left)
const currentLeft = parseInt(self.arr[self.current].style.left)
if (left > currentLeft) {
self.nextMove((left - currentLeft) / self.$offset)
} else if (currentLeft > left){
self.preMove((currentLeft - left) / self.$offset)
}
})
return li
}
_createImg (index) {
const img = document.createElement('img')
img.style.width = `${this.default.width}px`
img.style.height = `${this.default.height}px`
img.style.filter = 'grayscale(1)'
img.style.transform = 'scale(1)'
img.setAttribute('src', this.default.datas[index].src)
return img
}
_initDom () {
const lis = document.querySelectorAll('li')
const length = lis.length
for (let i = 0;i < length; i ++) {
this.arr[i] = lis[i]
}
}
preMove (step = 1) {
let loop = 0
const target = 1
while(loop < step){
loop ++
const dom = this.arr.pop()
dom.style.left = `${- (loop + this.$fix) * this.$offset}px`
this.arr.unshift(dom)
}
this._setUp(target * loop)
}
nextMove (step = 1) {
let loop = 0
const target = -1
while(loop < step){
const dom = this.arr.shift()
dom.style.left = `${(this.default.datas.length + loop - this.$fix) * this.$offset}px`
this.arr.push(dom)
loop ++
}
this._setUp(target * loop)
}
_setUp (target) {
for (let i = 0; i < this.arr.length; i ++) {
this.$ul.appendChild(this.arr[i])
}
for (let i = 0; i < this.arr.length; i ++) {
this._move(this.arr[i], target, i)
}
}
_move (dom, target = -1, index) {
const self = this
clearInterval(dom.timer)
const left = parseFloat(dom.style.left)
let scale = parseFloat(dom.firstChild.style.transform.substring(6, 7))
let gray = parseFloat(dom.firstChild.style.filter.substring(10, 11))
let offset = 0
const sign = parseInt(scale) === 1 ? 1 : -1
const offsetVal = target * this.default.speed / 30
const scaleVal = sign * 1 / 30
let stop = false
if (self.current === index) {
const bg = dom.getAttribute('data-bg')
this.$ele.style.backgroundImage = `url('${bg}')`
this.$ele.style.backgroundRepeat = 'no-repeat'
}
dom.timer = setInterval(function () {
offset += offsetVal
if (sign < 0 || self.current === index) {
scale += scaleVal
gray -= scaleVal
}
if (Math.abs(offset) >= Math.abs(target * self.$offset)) {
offset = target * self.$offset
if (self.current === index) {
scale = 2
gray = 0
} else {
scale = 1
gray = 1
}
stop = true
}
dom.style.left = `${left + offset}px`
dom.firstChild.style.transform = `scale(${scale})`
dom.firstChild.style.filter = `grayscale(${gray})`
if (stop) {
clearInterval(dom.timer)
}
}, 30)
}
auto () {
const self = this
setInterval(function () {
self.preMove(2)
}, 5000)
}
}
window.onload = function () {
const carousel = new Carousel('#carousel',{
datas: [
{bg: './images/b1.jpg', src: './images/1.png'},
{bg: './images/b2.jpg', src: './images/2.png'},
{bg: './images/b3.jpg', src: './images/3.png'},
{bg: './images/b4.jpg', src: './images/4.png'},
{bg: './images/b5.jpg', src: './images/5.png'},
{bg: './images/b6.jpg', src: './images/6.png'},
]
})
carousel.init()
}
<!DOCTYPE html>
<html lang="zh-cmn-Hans">
<head>
<meta charset="UTF-8">
<title>轮播图</title>
<link href="./index.css" rel="stylesheet">
</head>
<body>
<div id="carousel"></div>
<script src="./index.js"></script>
</body>
</html>
* {
margin: 0;
padding: 0;
}
body {
margin: 0;
padding: 0;
display:flex;
align-items:center;
justify-content: center;
height: 100vh;
width: 100vw;
}