JavaScript 基础
Document
运算符
深入数据和类型
函数进阶
原型、继承
类
浏览器存储
Web API
事件
错误处理
异步编程
网络请求
模块
练习
实例
工具与规范
软件架构模式
设计模式
$$demo <div class="carousel"> <div class="container"></div> <div class="shift"> <div class="btn left"><</div> <div class="btn right">></div> </div> <div class="bottom"></div> </div>
<script> const model = { images: [ "https://3yya.com/examples/assets/诸葛亮.jpg", "https://3yya.com/examples/assets/进击.jpg", "https://3yya.com/examples/assets/进击-大.jpg", ], // 循环播放 timerID: null, // 当前显示的图片序号 _index: 0, get imageAmount() { // 图片的数量 return this.images.length }, set index(value) { if (value < 0) { this._index = this.imageAmount - 1 } else if (value >= this.imageAmount) { this._index = 0 } else { this._index = value }
view.render()
},
get index() {
return this._index
},
}
function resetWrapper(func) {
// 装饰器,每次重置自动滚动
return function (...args) {
if (model.timerID) {
clearInterval(model.timerID)
}
model.timerID = controller.run()
return func(...args)
}
}
const controller = {
init() {
// 自动滚动
model.timerID = this.run()
document.querySelector(".carousel .left").onclick = this.leftShift
document.querySelector(".carousel .right").onclick = this.rightShift
},
leftShift: resetWrapper(() => {
model.index -= 1
}),
rightShift: resetWrapper(() => {
model.index += 1
}),
setIndex: resetWrapper((idx) => {
model.index = idx
}),
run() {
return setInterval(() => {
model.index++
}, 3000)
},
}
const view = {
init() {
// 添加图片
const container = document.querySelector(".carousel .container")
for (let url of model.images) {
const image = document.createElement("img")
image.src = url
container.append(image)
}
this.render()
},
render: function () {
carousel = document.querySelector(".carousel")
carousel.querySelector(".container").style.left = `${
model.index * carousel.clientWidth * -1
}px`
const bottom = carousel.querySelector(".bottom")
// 重置底部按钮
bottom.innerHTML = ""
for (let i = 0; i < model.imageAmount; i++) {
// 创建底部指示器
const indicator = document.createElement("div")
indicator.classList.add("indicator")
if (i === model.index) {
// 当前图片指示器
indicator.classList.add("activate")
}
indicator.onclick = () => controller.setIndex(i)
bottom.append(indicator)
}
},
}
controller.init()
view.init()
</script>
<style> .carousel { width: 800px; height: 400px;
margin: 0 auto;
overflow: hidden;
position: relative;
}
.carousel .container {
width: 100%;
height: 100%;
display: flex;
position: relative;
left: 0;
transition: left 1s;
}
.carousel .container img {
width: 100%;
height: 100%;
object-fit: cover;
flex-shrink: 0;
}
.carousel .shift .btn {
background-color: teal;
color: white;
font-size: 40px;
font-weight: bold;
width: 50px;
height: 50px;
line-height: 50px;
text-align: center;
border-radius: 8px;
opacity: 0.5;
cursor: pointer;
position: absolute;
/* 垂直居中 */
top: 0;
bottom: 0;
margin: auto;
}
.carousel .shift .left {
left: 30px;
}
.carousel .shift .right {
right: 30px;
}
.carousel:hover .btn {
/* 悬浮时显示按钮 */
opacity: 1;
}
.carousel .bottom {
position: absolute;
bottom: 20px;
left: 0;
right: 0;
margin: auto;
width: max-content;
display: flex;
gap: 10px;
}
.carousel .bottom .indicator {
height: 5px;
width: 40px;
background-color: teal;
opacity: 0.5;
cursor: pointer;
}
.carousel:hover .bottom .indicator {
/* 悬浮时显示按钮 */
opacity: 1;
}
.carousel .bottom .indicator.activate {
background-color: pink;
}
</style>
$$
$$answer
<div class="carousel">
<div class="container"></div>
<div class="shift">
<div class="btn left"><</div>
<div class="btn right">></div>
</div>
<div class="bottom"></div>
</div>
<script>
const model = {
images: [
"https://3yya.com/examples/assets/诸葛亮.jpg",
"https://3yya.com/examples/assets/进击.jpg",
"https://3yya.com/examples/assets/进击-大.jpg",
],
// 循环播放
timerID: null,
// 当前显示的图片序号
_index: 0,
get imageAmount() {
// 图片的数量
return this.images.length
},
set index(value) {
if (value < 0) {
this._index = this.imageAmount - 1
} else if (value >= this.imageAmount) {
this._index = 0
} else {
this._index = value
}
view.render()
},
get index() {
return this._index
},
}
function resetWrapper(func) {
// 装饰器,每次重置自动滚动
return function (...args) {
if (model.timerID) {
clearInterval(model.timerID)
}
model.timerID = controller.run()
return func(...args)
}
}
const controller = {
init() {
// 自动滚动
model.timerID = this.run()
document.querySelector(".carousel .left").onclick = this.leftShift
document.querySelector(".carousel .right").onclick = this.rightShift
},
leftShift: resetWrapper(() => {
model.index -= 1
}),
rightShift: resetWrapper(() => {
model.index += 1
}),
setIndex: resetWrapper((idx) => {
model.index = idx
}),
run() {
return setInterval(() => {
model.index++
}, 3000)
},
}
const view = {
init() {
// 添加图片
const container = document.querySelector(".carousel .container")
for (let url of model.images) {
const image = document.createElement("img")
image.src = url
container.append(image)
}
this.render()
},
render: function () {
carousel = document.querySelector(".carousel")
carousel.querySelector(".container").style.left = `${
model.index * carousel.clientWidth * -1
}px`
const bottom = carousel.querySelector(".bottom")
// 重置底部按钮
bottom.innerHTML = ""
for (let i = 0; i < model.imageAmount; i++) {
// 创建底部指示器
const indicator = document.createElement("div")
indicator.classList.add("indicator")
if (i === model.index) {
// 当前图片指示器
indicator.classList.add("activate")
}
indicator.onclick = () => controller.setIndex(i)
bottom.append(indicator)
}
},
}
controller.init()
view.init()
</script>
<style>
.carousel {
width: 800px;
height: 400px;
margin: 0 auto;
overflow: hidden;
position: relative;
}
.carousel .container {
width: 100%;
height: 100%;
display: flex;
position: relative;
left: 0;
transition: left 1s;
}
.carousel .container img {
width: 100%;
height: 100%;
object-fit: cover;
flex-shrink: 0;
}
.carousel .shift .btn {
background-color: teal;
color: white;
font-size: 40px;
font-weight: bold;
width: 50px;
height: 50px;
line-height: 50px;
text-align: center;
border-radius: 8px;
opacity: 0.5;
cursor: pointer;
position: absolute;
/* 垂直居中 */
top: 0;
bottom: 0;
margin: auto;
}
.carousel .shift .left {
left: 30px;
}
.carousel .shift .right {
right: 30px;
}
.carousel:hover .btn {
/* 悬浮时显示按钮 */
opacity: 1;
}
.carousel .bottom {
position: absolute;
bottom: 20px;
left: 0;
right: 0;
margin: auto;
width: max-content;
display: flex;
gap: 10px;
}
.carousel .bottom .indicator {
height: 5px;
width: 40px;
background-color: teal;
opacity: 0.5;
cursor: pointer;
}
.carousel:hover .bottom .indicator {
/* 悬浮时显示按钮 */
opacity: 1;
}
.carousel .bottom .indicator.activate {
background-color: pink;
}
</style>
$$