javaScript期中期末小案例

面向对象案例

烟花

效果分析

结构分析
  1. 大盒子做夜空
  2. 点击的时候生成一个小烟花
  3. 小烟花升空后生成很多小烟花
  4. 让很多小烟花移动到一个随机位置
效果分析
  1. 大盒子点击事件
  2. 生成小烟花,设置在大盒子最底部,横向位置是鼠标所点的位置。放到大盒子中,调用运动函数移动到鼠标所在高度
  3. 将小烟花删掉,并生成很多小烟花,设置成圆形,位置就是鼠标所点击的位置,随机颜色
  4. 让生成的很多小烟花移动到随机位置,移动后将很多小烟花从大盒子删除

代码实现:

html结构
<body>
    <div id="box"></div>
    <script src="./move.js"></script>
    <script src="./fire.js"></script>
</body>
js代码
fire.js
function Fire(){
  // 获取box盒子
  this.box = document.querySelector('#box')  
}
// 火花启动
Fire.prototype.init = function(){
  // 给box设置样式并绑定点击事件
  setStyle(this.box,{
    width:'1000px',
    height:'600px',
    background:'#000',
    border:'10px solid pink',
    position:'relative'
  })
  this.box.onclick = ()=>{
    // 访问方法创建小烟花
    this.click()
  }
}
// 盒子点击创建小烟花
Fire.prototype.click = function(e){
  // 获取鼠标点击的坐标
  e = e || window.event
  let x = e.offsetX
  let y = e.offsetY
  // 生成一个小烟花并设置样式
  let div = document.createElement('div')
  setStyle(div,{
    width:'10px',
    height:'10px',
    position:'absolute',
    left:x+'px',
    bottom:0,
    background: getColor()
  })
  this.box.appendChild(div)
  // 调用toUP方法让烟花升空
  this.toUp(div,x,y)
}
Fire.prototype.toUp = function(ele,x,y){
  move(ele,{top:y},()=>{    
    this.box.removeChild(ele)
    // 调用createManyFire方法 在这个位置 生成很多小烟花
    this.createManyFire(x,y)
  })
}
// 生成许多小烟花
Fire.prototype.createManyFire = function(x,y){
  let num = getNum(25,30)
  // 循环创建多个小烟花
  for (let i = 0; i < num; i++) {
    let div = document.createElement('div')
    // 设置小烟花的样式
    setStyle(div,{
      width:'10px',
      height:'10px',
      background:getColor(),
      borderRadius:'50%',
      position:'absolute',
      left:x+'px',
      top:y+'px'
    })
    this.box.appendChild(div)
    // 调用boom方法 让小烟花炸开
    this.boom(div)    
  }
}
// 烟花炸开
Fire.prototype.boom = function(ele){
  move(ele,{
    left:getNum(0,this.box.clientWidth-ele.clientWidth),
    top:getNum(0,this.box.clientHeight-ele.clientHeight)
  },()=>{
    this.box.removeChild(ele)
  })
}
// 实例化对象
let fire = new Fire()
fire.init()

// 设置元素样式函数
function setStyle(ele,obj){
  for (const attr in obj) {
      ele.style[attr] = obj[attr]
  }
}

// 生成随机颜色
function getColor(){
  let rgb1 = getNum(0,255)
  let rgb2 = getNum(0,255)
  let rgb3 = getNum(0,255)
  return `rgb(${rgb1},${rgb2},${rgb3})`
}

// 生成随机数
function getNum(a,b){
  return Math.floor(Math.random()*(b-a+1))+a
}
move.js
/**
 * @description:封装运动函数 
 * @param {Object} ele 运动元素
 * @param {Object} obj  运动目标属性和值  {left:100,top:300,opacity:0.5}
 * @param {function} fn 运动结束后执行的函数
 */
function move(ele,obj,fn=null){
  let timerObj = {}
  for(let attr in obj){
    let currentStyle = parseInt(getStyle(ele,attr))
    let target = obj[attr]
    if(attr == 'opacity'){
      currentStyle = currentStyle*100
      target = target*100
    }
    timerObj[attr] = setInterval(function(){
      let speed = (target-currentStyle)/10
      speed = speed>0?Math.ceil(speed):Math.floor(speed)
      currentStyle += speed
      if(currentStyle == target){
        clearInterval(timerObj[attr])
        delete timerObj[attr]
        let k = 0
        for(let i in timerObj){
          k++
        }
        if(k == 0 ){
          // 运动结束
          if(fn){fn()}
        }        
      }else{
        if(attr == 'opacity'){
          ele.style[attr] = currentStyle/100
        }else{
          ele.style[attr] = currentStyle + 'px'
        }
      }
    },30)
  }
}
/**  
 * @description: 获取元素属性
 * @param {Object} ele
 * @param {string} attr
 * @return {string}
 */
function getStyle(ele,attr){
  if(window.getComputedStyle){
    return window.getComputedStyle(ele)[attr];
  }else{
    return ele.currentStyle(atrr)
  }
}

放大镜

效果分析

组成结构分析
  1. 一个容器大盒子 - div.box
  2. 一个放中等图片的盒子 - div.middleBox
    • 一张中等图片
    • 一个遮罩 - div.shade
  3. 一个放小图片的盒子 - div.smallBox
    • 两张小图
  4. 一个放大图的盒子 - div.bigBox
布局分析
  1. 大盒子box设置相对定位
  2. 中等盒子middleBox设置相对定位
  3. 遮罩shade设置绝对定位在中等盒子中,隐藏
  4. 放大图的盒子bigBox设置绝对定位,定位到大盒子box的右边,大图作为放大图的盒子的背景
效果分析
  1. 点击小图片,大图随着小图更换
  2. 鼠标移动大中等盒子上
    • 遮罩出现,并可以在中等盒子上移动
    • 遮罩移动的过程中大盒子的背景图也跟随移动
  3. 鼠标离开大盒子
    • 遮罩隐藏,放大图的盒子也隐藏,并将移动事件注销
规律分析
  1. 中等盒子和遮罩的比例,是大图和放大图的盒子的比例
  2. 遮罩移动过的距离和中等盒子的比例,是大图移动的距离和大图的比例

代码实现

html结构
<div class="box">
    <div class="middleBox">
      <img src="./images/middle1.jpg">
      <div class="shade"></div>
    </div>
    <div class="smallBox">
     <img src="./images/small1.jpg" middleImg='./images/middle1.jpg' bigImg='./images/big1.jpg' class="active">
     <img src="./images/small2.jpg" middleImg='./images/middle2.jpg' bigImg='./images/big2.jpg'>
    </div>
    <div class="bigBox"></div>
  </div>
样式代码
*{margin: 0;padding: 0;}
.middleBox{
  width: 400px;
  height: 400px;
  border: 1px solid #000;
  position: relative;
}
.middleBox img{
  width: 400px;
  height: 400px;
}
.shade {
  width: 200px;
  height: 200px;
  background: yellow;
  position: absolute;
  left: 0;
  top: 0;
  opacity: 0.5;
  display: none;
}
.shade:hover{
  cursor: move;
}
.smallBox {
  margin-top: 10px;
}
.smallBox img {
  border: 1px solid #000;
  margin-left: 5px;
}
.smallBox img.active{
  border-color: red;
}
.box {
  width: 402px;
  margin: 50px;
  position: relative;
}
.bigBox {
  width: 400px;
  height: 400px;
  border: 1px solid #000;
  position: absolute;
  top: 0;
  left: 110%;
  background-image: url('./images/big1.jpg');
  background-position: 0 0;
  background-repeat: no-repeat;
  background-size: 800px 800px;
  display: none;
}
js代码
// 定义一个空构造函数
function Enlarge(){
  // 获取需要操作的元素并绑定到对象的属性上
  this.box = document.querySelector('.box')
  this.middleBox = this.box.querySelector('.middleBox')
  this.middleImg = this.box.querySelector('.middleBox img')
  this.shade = this.box.querySelector('.shade')
  this.smallImgs = this.box.querySelectorAll('.smallBox img')
  this.bigBox = this.box.querySelector('.bigBox')
}
// 给需要操作的元素绑定事件
Enlarge.prototype.bind = function(){
  // 中等盒子绑定鼠标移入事件
  this.middleBox.onmouseover = ()=>{
    // 鼠标移入显示遮罩层
    this.shade.style.display = 'block'
    // 鼠标移动遮罩层移动
    this.middleBox.onmousemove = ()=>{
      // 调用移动方法
      this.move()
    }
  }
  // 中等盒子绑定鼠标移出事件
  this.middleBox.onmouseleave = ()=>{
    this.shade.style.display = 'none'
    this.bigBox.style.display = 'none'
    this.middleBox.onmousemove = null
  }
  // 点击小图切换图片是
  for (let i = 0; i < this.smallImgs.length; i++) {
    this.smallImgs[i].onclick = ()=>{
      // 访问tab方法实现切换图片
      this.tab(this.smallImgs[i])
    }
  }
}

// 鼠标在盒子上的移动事件
Enlarge.prototype.move = function(e){
  e = e || window.event
  // 鼠标相对于浏览器窗口左上角的坐标
  let x = e.clientX
  let y = e.clientY
  // 遮罩层的宽高的一半
  let shadeWidthBan = this.shade.clientWidth/2
  let shadeHeightBan = this.shade.clientHeight/2
  // 限定x和y在左上角最小的位置坐标
  if(x<this.box.offsetLeft+shadeWidthBan){
    x = this.box.offsetLeft+shadeWidthBan
  }
  if(y<this.box.offsetTop+shadeHeightBan){
    y = this.box.offsetTop+shadeHeightBan
  }
  // 限定x和y在右下角最大的位置坐标
  if(x>this.box.offsetLeft+this.middleBox.clientWidth-shadeWidthBan){
    x = this.box.offsetLeft+this.middleBox.clientWidth - shadeWidthBan
  }
  if(y>this.box.offsetTop+this.middleBox.clientHeight-shadeHeightBan){
    y = this.box.offsetTop+this.middleBox.clientHeight-shadeHeightBan
  }
  // 给遮罩层设置left和top,让遮罩层移动起来
  this.shade.style.left = x - this.box.offsetLeft - shadeWidthBan + 'px'
  this.shade.style.top = y - this.box.offsetTop - shadeHeightBan + 'px'
  // 调用bigMove方法让大图移动
  this.bigMove()
}

// 移动遮罩层让大图移动
Enlarge.prototype.bigMove = function(){
  this.bigBox.style.display = 'block'
  // 遮罩层移动的距离/中盒子大小 ===  大图移动距离/大图的大小
  // 计算 遮罩层移动的距离/中盒子大小 的比例
  let xPercent = this.shade.offsetLeft/this.middleBox.clientWidth
  let yPercent = this.shade.offsetTop/this.middleBox.clientHeight
  // 获取大图的大小
  // 获取大盒子的背景图的尺寸 background-size
  let bigImgSize = getStyle(this.bigBox,'background-size')
  // 获取出来是字符串,通过字符串方法获取到背景图的宽高数值
  let bigImgWidth = parseInt(bigImgSize.split(' ')[0])
  let bigImgHeight = parseInt(bigImgSize.split(' ')[1])
  // 计算大图移动的距离
  let xMove = bigImgWidth*xPercent
  let yMove = bigImgHeight*yPercent
  // 把大图要移动的距离,赋值到大图的背景图定位上 background-position
  this.bigBox.style.backgroundPosition = `-${xMove}px -${yMove}px`
}

// 点击小图片切换中图和大图
Enlarge.prototype.tab = function(smallImg){
  // 获取小图元素中的middleImg和bigImg属性
  let middleImg = smallImg.getAttribute('middleImg')
  let bigImg = smallImg.getAttribute('bigImg')
  console.log(middleImg,bigImg);
  // 将中图和大图的图片地址替换
  this.middleImg.setAttribute('src',middleImg)
  this.bigBox.style.backgroundImage = `url(${bigImg})`
  // 去除小图片的active类名,给点击的这个加上active
  for (let i = 0; i < this.smallImgs.length; i++) {
    this.smallImgs[i].className = ''
  }
  smallImg.className = 'active'
}
// 实例化对象
let enlarge = new Enlarge()
enlarge.bind()

// 获取样式函数
function getStyle(ele,attr){
  if(window.getComputedStyle){
    return window.getComputedStyle(ele)[attr]
  }else{
    return ele.currentStyle[attr]
  }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值