JavaScript小案例

烟花

html

html 复制代码
<body>
    <div id="box"></div>
    <script src="./move.js"></script>
    <script src="./fire.js"></script>
</body>
js代码
fire.js
javascript 复制代码
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

javascript 复制代码
/**
 * @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)
  }
}

放大镜

html
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>

css

html 复制代码
*{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

javascript 复制代码
// 定义一个空构造函数
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]
  }
}
相关推荐
崔庆才丨静觅1 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
曹牧2 小时前
Spring Boot:如何测试Java Controller中的POST请求?
java·开发语言
passerby60612 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了2 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅2 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅3 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
爬山算法3 小时前
Hibernate(90)如何在故障注入测试中使用Hibernate?
java·后端·hibernate
kfyty7253 小时前
集成 spring-ai 2.x 实践中遇到的一些问题及解决方案
java·人工智能·spring-ai
猫头虎3 小时前
如何排查并解决项目启动时报错Error encountered while processing: java.io.IOException: closed 的问题
java·开发语言·jvm·spring boot·python·开源·maven
李少兄3 小时前
在 IntelliJ IDEA 中修改 Git 远程仓库地址
java·git·intellij-idea