Skip to content

1. 作业

1.1 购物车案例

javascript
// 1. 进入页面之后渲染数据
const arr = JSON.parse(localStorage.getItem('car')) || dataArr
const box = document.querySelector('.tbody')
// 封装一个render函数
const render = function(){
  const trArr = arr.map(function(el, i){
    return `
      <div class="tr">
          <div class="td"><input type="checkbox" ${el.isChecked ? 'checked': ''} /></div>
          <div class="td"><img src="${el.icon}" alt="" /></div>
          <div class="td">${el.price}</div>
          <div class="td">
            <div class="my-input-number">
              <button class="decrease"> - </button>
              <span class="my-input__inner">${el.num}</span>
              <button class="increase"> + </button>
            </div>
          </div>
          <div class="td">${el.price * el.num}</div>
          <div class="td"><button class="del" data-id="${i}">删除</button></div>
        </div> 
    `
  })
  // 把map方法返回的数组,转为字符串拼接
  box.innerHTML = trArr.join('')
}
render()

// 2. 删除
box.addEventListener('click', function(e){
  if (e.target.className === 'del'){
    console.log(e.target.dataset.id)

    const res = confirm('你确定要删除吗')
    if (res) {
      arr.splice(e.target.dataset.id, 1)
      render()
      localStorage.setItem('car', JSON.stringify(arr))
    }
  } // end if 
})

1.2 微博发布案例

javascript
// 1. 进入页面获取本地存储的数据
const arr = JSON.parse(localStorage.getItem('weibo')) || []

// 2. 渲染评论
const list = document.querySelector('#list')
function render(){
  const newArr = arr.map(function(el,i){
    return `
    <li>
      <div class="info">
        <img class="userpic" src="${el.img}" />
        <span class="username">${el.name}</span>
        <p class="send-time">发布于 ${el.time}</p>
      </div>
      <div class="content">${el.msg}</div>
      <span class="the_del" data-id="${i}">X</span>
    </li>
    `
  })
  list.innerHTML = newArr.join('')
}
render()

// 3. 发布评论,新增数据
const btn = document.querySelector('#send')
const area = document.querySelector('#area')

btn.addEventListener('click', function(){
  // 1. 随机获取头像和名字
  const random = Math.floor(Math.random() * dataArr.length)

  arr.unshift({
    img: dataArr[random].imgSrc,
    name: dataArr[random].uname,
    msg: area.value,
    time: new Date().toLocaleString()
  })
  console.log(arr)
  // 渲染
  render()
  area.value = ''
  // 存到本地
  localStorage.setItem('weibo', JSON.stringify(arr))
})


// 3. 删除功能 事件委托
list.addEventListener('click', function(e){
  if (e.target.className === 'the_del'){
    // console.log(e.target.dataset.id)
    arr.splice(e.target.dataset.id, 1)
    render()
    localStorage.setItem('weibo', JSON.stringify(arr))
  } // end
})

2. 放大镜案例

2.1 鼠标经过小图片,左侧中图片跟随变化

  1. 在这个案例中,所有的盒子用的img都是一样的,中等盒子,小盒子,大盒子中img 同一张
  2. 使用mouseover给公共父元素绑定事件,mouseover有事件冒泡
  3. 判断谁触发的事件的时候,判断的是IMG,为什么?因为这样我们可以更方便的获取到触发图片的src,待会儿要使用,赋值给中等盒子的图片
  4. 怎么获取中等盒子里面的img元素,这里使用了 children 获取子元素,注意是一个伪数组,还要用下标才能取到img
  5. 排他的时候,是给小图片的父元素 li标签添加active类名,注意 parentNode
javascript
// 1. 获取元素
const middle = document.querySelector('.middle')
const small = document.querySelector('.small') // 公共父元素
// 2. 给公共父元素绑定事件 mouseover => 它有事件冒泡
small.addEventListener('mouseover', function(e){
  console.log(e.target)
  if (e.target.tagName === 'IMG'){
    // 2.1 给当前小图片的父元素li标签添加active
    small.querySelector('.active').classList.remove('active')
    e.target.parentNode.classList.add('active')

    // 2.2 取到小盒子中的图片,给左侧中等盒子
    console.log(e.target.src)
    console.log(middle.children)
    middle.children[0].src = e.target.src

  } // end if 
})

2.2 鼠标经过中盒子,显示右侧大盒子和遮罩层

javascript
// 鼠标经过中等盒子,显示右侧大盒子和黑色遮罩层
// 1. 获取元素
const large = document.querySelector('.large')
const mask = document.querySelector('.layer')
// 2. 注册事件,给middle盒子注册 经过和离开 mouseenter / mouseleave

middle.addEventListener('mouseenter', function(){
  large.style.display = 'block'
  large.style.backgroundImage = `url(${middle.children[0].src})`
  mask.style.display = 'block'
})
middle.addEventListener('mouseleave', function(){
  large.style.display = 'none'
  mask.style.display = 'none'
})

2.3 黑色遮罩层跟随鼠标移动

e.offsetX, e.offsetY 可以获取鼠标相对于盒子的坐标 把这个坐标赋值给mask,当鼠标移动的时候,遮罩层也就移动了 (注意mask有定位,才能设置left, top)

javascript
// 黑色遮罩层,跟随鼠标移动(鼠标在middle盒子中移动)
middle.addEventListener('mousemove', function(e){
  console.log(e.offsetX, e.offsetY)
  // 声明x,y 表示黑色遮罩层的x,y坐标
  let x = e.offsetX 
  let y = e.offsetY

  mask.style.left = x + 'px'
  mask.style.top = y + 'px'
})
  • 鼠标移动的时候,有闪动的情况,是因为,offsetX可能会取到鼠标相当于黑色遮罩层的位置,也可能取到鼠标相对于middle盒子的位置,赋值给mask,就会出现问题
  • 我们要做的就是不让获取鼠标相对于黑色盒子的坐标,可以通过css将黑色遮罩层的鼠标事件设置为none
css
/* 解决闪动的问题 */
/* 不对鼠标事件做出反应 */
pointer-events: none;

/* 让鼠标变为移动的图标 */
cursor:move  ==> 给middle盒子加

2.4 让鼠标位于遮罩层中心

image.png

  1. 鼠标距离中等盒子的坐标 e.offsetX, e.offsetY => 鼠标的位置
  2. 遮罩层的横坐标和纵坐标 ,我们用 x, y 表示

思考? 遮罩层的横坐标x 和 鼠标的位置e.offsetX的关系

x = e.offsetX - 遮罩层宽度的一半 => 可以让鼠标位于遮罩层中心

=> 通过鼠标在中等盒子中的坐标,求到黑色遮罩层在中等盒子中的坐标

javascript
// 黑色遮罩层,跟随鼠标移动(鼠标在middle盒子中移动)
middle.addEventListener('mousemove', function(e){
  console.log(e.offsetX, e.offsetY)
  // 声明x,y 表示黑色遮罩层的x,y坐标
  // 让e.offsetX当前鼠标的位置 - 遮罩层宽度的一半 得到的x赋值给遮罩层,
  let x = e.offsetX - mask.offsetWidth / 2 
  let y = e.offsetY - mask.offsetHeight / 2

  mask.style.left = x + 'px'
  mask.style.top = y + 'px'
})

2.5 限定黑色遮罩层移动的位置

javascript
    // 黑色遮罩层,跟随鼠标移动(鼠标在middle盒子中移动)
    middle.addEventListener('mousemove', function(e){
      console.log(e.offsetX, e.offsetY)
      // 声明x,y 表示黑色遮罩层的x,y坐标
      // 让e.offsetX当前鼠标的位置 - 遮罩层宽度的一半 得到的x赋值给遮罩层,
      // let x = e.offsetX
      // let y = e.offsetY
      let x = e.offsetX - mask.offsetWidth / 2 
      let y = e.offsetY - mask.offsetHeight / 2

      const maxX = middle.offsetWidth - mask.offsetWidth
      const maxY = middle.offsetHeight - mask.offsetHeight
      console.log(x, y)
      // 怎么让黑色遮罩层限制在中等盒子中移动
      x = x < 0 ? 0 : x
      x = x > maxX ? maxX : x
      y = y < 0 ? 0 : y
      y = y > maxY ? maxY : y

      mask.style.left = x + 'px'
      mask.style.top = y + 'px'
      // 让大盒子背景图片跟随遮罩层扫过的位置移动
    })

2.6 大图片背景图跟随鼠标移动

中等盒子 宽高 400 * 400 大盒子背景图 800 * 800 当黑色遮罩层在中等盒子移动1px, 大盒子背景图应该移动2px,存在一个2倍关系 另外,鼠标往右移动,背景图应该是往左移动的,所以需要加负号

javascript
    // 黑色遮罩层,跟随鼠标移动(鼠标在middle盒子中移动)
    middle.addEventListener('mousemove', function(e){
  	
    	// 省略 。。。。
      
      // 如果黑色遮罩层在中等盒子中移动了1px, 那么右侧大盒子中的背景图相对要走2px
      // large.style.backgroundPositionX = - 2 * x + 'px'
      // large.style.backgroundPositionY = - 2 * y + 'px'
      large.style.backgroundPosition = `${- 2 * x}px ${- 2 * y}px`
    })