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]
  }
}
相关推荐
爱健身的小刘同学2 分钟前
安装 electron 依赖报错
前端·javascript·electron
耶啵奶膘3 分钟前
uniapp+vue2+uview2.0导航栏组件二次封装
前端·javascript·uni-app
布兰妮甜3 分钟前
如何使用 Tailwind CSS 构建响应式网站:详细指南
前端·css·tailwind css
MavenTalk5 分钟前
前端技术选型之uniapp
android·前端·flutter·ios·uni-app·前端开发
雨中奔跑的小孩8 分钟前
electron打包部署vue项目
javascript·vue.js·electron
paterWang8 分钟前
小程序-基于java+SpringBoot+Vue的美食推荐系统设计与实现
java·spring boot·小程序
《源码好优多》8 分钟前
基于Java Springboot餐饮美食分享平台
java·spring boot·美食
说书客啊12 分钟前
计算机毕业设计 | SpringBoot+vue美食推荐商城 食品零食购物平台(附源码+论文)
java·spring boot·node.js·vue·毕业设计·课程设计·美食
ZZZCY200320 分钟前
路由策略与路由控制实验
前端·网络
小宋102121 分钟前
实现java执行kettle并传参数
java·开发语言·etl