1、拖拽效果
需求:
1、鼠标可以在div上按下
2、div在鼠标按下时跟鼠标一起移动
3、鼠标松开后,div在最新的位置停止不动
回顾ES5的写法
// 构造函数
function Drag(selector) {
this.el = document.querySelector(selector)
this.init()
}
Drag.prototype.init = function () {
// this指向实例对象
// 按下鼠标
this.el.addEventListener('mousedown', (e) => {
// 鼠标对于该实例对象中的距离offset
let startX = e.offsetX
let startY = e.offsetY
let handler = (e) => {
// 鼠标对于本页面的距离page
let left = e.pageX - startX
let top = e.pageY - startY
// 边界检测
if (left < 0) {
left = 0
}
if (top < 0) {
top = 0
}
this.el.style.left = left + 'px'
this.el.style.top = top + 'px'
}
document.addEventListener('mousemove', handler)
document.addEventListener('mouseup', () => {
document.removeEventListener('mousemove', handler)
})
})
}
new Drag('div')
<-- 样式 -->
* {
padding: 0;
margin: 0;
}
div {
width: 100px;
height: 100px;
background-color: tomato;
position: absolute;
top: 10px;
left: 100px;
}
ES6语法
class Drag {
constructor(selector) {
this.el = document.querySelector(selector)
this.init()
}
init() {
this.el.addEventListener('mousedown', (e) => {
let startX = e.offsetX
let startY = e.offsetY
let handler = (e) => {
let left = e.pageX - startX
let top = e.pageY - startY
if (left < 0) {
left = 0
}
if (top < 0) {
top = 0
}
this.el.style.left = left + 'px'
this.el.style.top = top + 'px'
}
// 移动鼠标
document.addEventListener('mousemove', handler)
// 松开鼠标
document.addEventListener('mouseup', () => {
document.removeEventListener('mousemove', handler)
})
})
}
}
new Drag('div')
2、五星好评
需求
1、鼠标移入li,对应的li以及前面的li都高亮,后面的不亮
2、打几星分别显示不同的文字
3、鼠标点击li,对应的li以及前面的li都高亮,后面的不亮
4、鼠标移出ul时,li回到上一次点击时的效果
图片:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.star,
li {
list-style: none;
margin: 0;
padding: 0;
}
.star {
height: 30px;
}
li {
background: url('./imgs/star.gif') no-repeat;
float: left;
height: 28px;
width: 27px;
}
</style>
</head>
<body>
<div class="score">
<ul class="star">
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
<div class="text"></div>
</div>
</body>
<script>
class Score {
constructor(selector) {
// 评分的容器
let container = document.querySelector(selector)
this.ul = container.querySelector('ul')
this.liS = container.querySelectorAll('li')
this.text = container.querySelector('.text')
this.textArr = ['不推荐', '一般', '还可以', '推荐', '超级推荐']
// 记录被点击的li的下标索引
this.index = -1
this.init()
}
init() {
this.addMouseEnter()
this.addMouseClick()
this.addMouseLeave()
}
// 鼠标移入
addMouseEnter() {
for (let i = 0; i < this.liS.length; i++) {
this.liS[i].onmouseenter = () => {
for (let j = 0; j <= i; j++) {
this.liS[j].style.backgroundPosition = '0px -28px'
}
for (let j = i + 1; j < this.liS.length; j++) {
this.liS[j].style.backgroundPosition = '0px 0px'
}
// 显示文字
this.text.innerText = this.textArr[i]
this.index = i
}
}
}
// 鼠标点击
addMouseClick() {
for (let i = 0; i < this.liS.length; i++) {
this.liS[i].onclick = () => {
this.index = i
}
}
}
// 鼠标移出
addMouseLeave() {
this.ul.onmouseleave = () => {
for (let j = 0; j <= this.index; j++) {
this.liS[j].style.backgroundPosition = '0px -28px'
}
for (let j = this.index + 1; j < this.liS.length; j++) {
this.liS[j].style.backgroundPosition = '0px 0px'
}
this.text.innerText = this.textArr[this.index] ? this.textArr[this.index] : ''
}
}
}
new Score('.score')
</script>
</html>
3、无缝滚动
需求:
1、构造函数生成对象,对象可以根据指定的css选择器,把指定的元素无缝滚动
2、鼠标放入时滚动停止
3、鼠标移开后继续滚动
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
* {
padding: 0;
margin: 0;
}
.box {
width: 600px;
height: 200px;
border: 1px solid #ccc;
padding: 10px;
margin: 0 auto;
}
.wrapper {
width: 600px;
height: 200px;
position: relative;
overflow: hidden;
}
.box img {
width: 300px;
height: 200px;
display: block;
}
.box li {
list-style: none;
float: left;
}
.box ul {
width: 600%;
height: 200px;
position: absolute;
left: 0px;
}
</style>
</head>
<body>
<div class="box">
<div class="wrapper">
<ul class="imgs">
<li><img src="./imgs/a.jpg"></li>
<li><img src="./imgs/b.jpg"></li>
<li><img src="./imgs/c.jpg"></li>
<li><img src="./imgs/d.jpg"></li>
</ul>
</div>
</div>
<script>
class SwiperLoop {
constructor(selector) {
// 记录无缝滚动的容器
let container = document.querySelector(selector)
this.wrapper = container.querySelector('.wrapper')
this.ul = container.querySelector('ul')
this.liS = this.ul.children
this.timer = null
this.init()
}
init() {
for (let i = 0; i < 2; i++) {
let newLi = this.liS[i].cloneNode(true)
this.ul.appendChild(newLi)
}
this.move()
this.addMouseEnter()
this.addMouseLeave()
}
// 移动
move() {
this.timer = setInterval(() => {
// offsetLeft:返回当前元素距离某个父辈元素左边缘的距离
this.ul.style.left = this.ul.offsetLeft - 2 + 'px'
if (this.ul.offsetLeft <= -1200) {
this.ul.style.left = 0
}
}, 20)
}
// 鼠标放入
addMouseEnter() {
this.wrapper.onmouseenter = () => {
clearInterval(this.timer)
}
}
// 鼠标移开
addMouseLeave() {
this.wrapper.onmouseleave = () => {
this.move()
}
}
}
new SwiperLoop('.box')
</script>
</body>
</html>
图片:
4、购物车
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.container {
width: 430px;
padding: 10px;
border: 1px solid #ccc;
margin: 20px auto;
line-height: 30px;
}
.title {
font-size: 24px;
color: tomato;
font-weight: 800;
}
.container table {
color: #333;
font-size: 12px;
margin: 10px 0px;
}
.head {
background-color: azure;
}
tr img {
width: 50px;
height: 50px;
display: block;
float: left;
margin: 5px;
}
.container .num {
width: 50px;
}
.del,
.go {
cursor: pointer;
}
.total {
font-size: 24px;
font-weight: 900;
color: tomato;
}
</style>
</head>
<body>
<div class="container"></div>
<script>
class Shop {
constructor(data, selector) {
// 用于渲染购物车的元素dom
this.container = document.querySelector(selector)
// 数据
this.data = data
this.init()
}
init() {
this.render(this.data)
this.getTotal()
this.delEvent()
this.allEvent()
}
// 渲染数据到页面上
render(data) {
let htmlStr = ` <div class="title">全部商品${data.length}</div>
<table>
<tr class="head">
<td width="60px">
<input type="checkbox">
<span>全选</span>
</td>
<td width="160px">商品</td>
<td>单价</td>
<td>数量</td>
<td>小计</td>
<td>操作</td>
</tr>`
// 循环遍历data
data.forEach(item => {
htmlStr += ` <tr data-id="${item.id}">
<td><input type="checkbox" ${item.checked ? 'checked' : ''}></td>
<td>
<img src="${item.pic}" alt="">
<p>${item.name}</p>
</td>
<td>¥${item.price}</td>
<td>
<span>-</span>
<input class="num" type="number" value="${item.num}">
<span>+</span>
</td>
<td>¥${item.price * item.num}</td>
<td class="del">删除</td>
</tr>`
})
htmlStr += `
</table>
<div>
<span>总价:<div style="display:inline" class="total"></div></span>
<div class="go">结算</div>
</div>`
this.container.innerHTML = htmlStr
}
// 总价
getTotal() {
let sum = 0
// 拿到所有复选框(获取data-id属性下type=checkbox的复选框)
let allCheckBox = this.container.querySelectorAll('[data-id] [type=checkbox]')
// 循环每个复选框,查看他们的选中状态
for (let i = 0; i < allCheckBox.length; i++) {
if (allCheckBox[i].checked) {
// 找到复选框所在的tr
let tr = allCheckBox[i].parentNode.parentNode
// 获取该行单价
let price = tr.querySelectorAll('td')[2].innerText.trim().slice(1)
// console.log(price);
// 获取该行数量
let num = tr.querySelector('[type=number]').value
sum += (price * num)
}
}
this.container.querySelector('.total').innerHTML = sum
}
// 删除
delEvent() {
let delS = this.container.querySelectorAll('.del')
// 循环给每个del按钮绑定事件
for (let i = 0; i < delS.length; i++) {
delS[i].onclick = () => {
// 被删除的下标索引
// console.log(i);
// 删除
this.data.splice(i, 1)
// 重新渲染数据
this.init()
}
}
}
// 全选
allEvent() {
// 获取全选按钮
let btn = this.container.querySelector('.head input')
// 获取全部复选框
let checkS = this.container.querySelectorAll('[data-id] [type=checkbox]')
btn.onchange = () => {
for (let i = 0; i < checkS.length; i++) {
checkS[i].checked = btn.checked
}
// 重新计算总价
this.getTotal()
}
}
}
new Shop([
{ id: '1', pic: './imgs/a.jpg', name: '图1', price: 10, num: 3, checked: true },
{ id: '2', pic: './imgs/b.jpg', name: '图2', price: 40, num: 5, checked: true },
{ id: '3', pic: './imgs/c.jpg', name: '图3', price: 360, num: 8, checked: false },
{ id: '4', pic: './imgs/d.jpg', name: '图4', price: 100, num: 4, checked: true },
], '.container')
</script>
</body>
</html>