几大API与对象的使用,实现复制粘贴上传,拖拽上传点击打开文件管理器上传图片,并滚轮实现大小变化

958 阅读5分钟

我正在参加「掘金·启航计划」

前言

本期是对JS的File对象、DataTransfer对象、Clipboard API,URL.createObjectURL(file) 或 FileReader.readAsDataURL(file)的了解和使用,并基于其基础上,实现实现复制粘贴上传,拖拽上传点击打开文件管理器上传图片,并滚轮实现改变图片的大小的功能。

JS的File对象

在 HTML 文档中 <input type="file"> 标签每出现一次,一个 FileUpload 对象就会被创建。 该元素包含一个文本输入字段,用来输入文件名,还有一个按钮,用来打开文件选择对话框以便图形化选择文件。该元素的 value 属性保存了用户指定的文件的名称,但是当包含一个 file-upload 元素的表单被提交的时候,浏览器会向服务器发送选中的文件的内容而不仅仅是发送文件名。

dataTransfer对象

拖放事件 拖放的过程中被拖放的对象被称为源对象,过拖放过程中间经过的其他对象被称为过程对象,最终到达的对象称作目标对象。 在所有的拖放事件中都提供了一个数据传输对象dataTransfer,主要是用于在源对象和目标对象之间传递数据。

Clipboard API

剪贴板Clipboard API提供了响应剪贴板命令(剪切、复制和粘贴)与异步读写系统剪贴板的能力。 获取权限之后,才能访问剪贴板内容;如果用户没有授予权限,则不允许读取或更改剪贴板内容。

URL.createObjectURL()

简单来说:URL.createObjectURL()处理后生成了一个临时的链接,直接赋值给src就行。

FileReader.readAsDataURL(file)

FileReader 对象允许Web应用程序异步读取存储在用户计算机上的文件(或原始数据缓冲区)的内容, 使用 File 或 Blob 对象指定要读取的文件或数据。简单来说:异步读取指定的Blob中的内容,一旦完成,会返回一个data: URL格式的字符串以表示所读取文件的内容。

这些简单了解一下即可,剩下的主要是实战,废话不多说,直接上代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>上传图片</title>
    <link rel="stylesheet" href="./uploadPic.css">
    <link rel="stylesheet" href="./font/iconfont.css">
    <link rel="stylesheet" href="../Task2/font2/iconfont.css">
    <link rel="stylesheet" href="./font next-pre/iconfont.css">
    <script src="./uploadPic.js"></script>
</head>
<body id="scroll">
    <div class="previewBox">
        <div id="preBtn"><span class="iconfont icon-pre"></span></div>
        <div id="nextBtn"><span class="iconfont icon-next"></span></div>
        <div class="preview">
            <div id="closeBtn"><span class="iconfont icon-close"></span></div>
            <div class="picBox">
                <img src="https://ts1.cn.mm.bing.net/th/id/R-C.a902a2666359a8cdfdb4a5073d402423?rik=%2fOAi8FFhylA5IQ&riu=http%3a%2f%2fimg.ewebweb.com%2fuploads%2f20191203%2f19%2f1575371671-fMmhxsnHNX.jpg&ehk=R7dew66vN%2bgvvyJL3I8BL00tsQwYL%2bv8PIqeUSKgzk4%3d&risl=&pid=ImgRaw&r=0" alt="" id="previewPic">
            </div>
            
        </div>
    </div>
    <input type="file" id="openFile">
    <div id="openBtn">点击上传图片</div>
    <div id="picWall" contenteditable="true">
      <div class="pic">
        <img class="upPic" src="https://ts1.cn.mm.bing.net/th/id/R-C.a902a2666359a8cdfdb4a5073d402423?rik=%2fOAi8FFhylA5IQ&riu=http%3a%2f%2fimg.ewebweb.com%2fuploads%2f20191203%2f19%2f1575371671-fMmhxsnHNX.jpg&ehk=R7dew66vN%2bgvvyJL3I8BL00tsQwYL%2bv8PIqeUSKgzk4%3d&risl=&pid=ImgRaw&r=0" alt="">
        <div class="shadowBox">
            <div class="previewBtn"><span class="iconfont icon-fangdajing1-xianxing"></span></div>
            <div class="deleteBtn"><span class="iconfont icon-lajixiang"></span></div>
        </div>
      </div>
    </div>
</body>
</html>

CSS

.previewBox {
  display: none;
  position: fixed;
  top: 0;
  left: 0;
  z-index: 100;
  width: 100%;
  height: 100vh;
  background-color: rgba(63, 60, 60, 0.7);
}
.previewBox #preBtn {
  position: absolute;
  left: 196px;
  top: 200px;
  width: 40px;
  height: 70px;
  color: aliceblue;
  border-top-left-radius: 8px;
  border-bottom-left-radius: 8px;
  background-color: #dcc6f5;
  line-height: 70px;
  text-align: center;
  cursor: pointer;
}
.previewBox #preBtn span {
  font-size: 18px;
}
.previewBox #nextBtn {
  position: absolute;
  right: 196px;
  top: 200px;
  width: 40px;
  height: 70px;
  color: aliceblue;
  border-top-right-radius: 8px;
  border-bottom-right-radius: 8px;
  background-color: #dcc6f5;
  line-height: 70px;
  text-align: center;
  cursor: pointer;
}
.previewBox #nextBtn span {
  font-size: 30px;
}
.previewBox .preview {
  position: relative;
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  display: flex;
  align-items: center;
  justify-content: center;
  width: 470px;
  height: 450px;
  padding: 10px;
  padding-top: 30px;
  background-color: aliceblue;
}
.previewBox .preview .picBox {
  max-width: 470px;
  max-height: 450px;
  overflow: hidden;
}
.previewBox .preview #previewPic {
  width: 200px;
  height: 200px;
}
.previewBox .preview #closeBtn {
  position: absolute;
  right: 10px;
  top: 5px;
  cursor: pointer;
}
#openFile {
  display: none;
}
#openBtn {
  width: 120px;
  height: 80px;
  margin: 10px auto;
  border-radius: 10px;
  border: 1px solid #bcff5f;
  background-color: #84dcbf;
  color: white;
  font-size: 18px;
  line-height: 80px;
  text-align: center;
  cursor: pointer;
}
#picWall {
  display: flex;
  flex-wrap: wrap;
  align-self: flex-start;
  width: 640px;
  height: 600px;
  margin: 60px auto;
  border: 1px solid skyblue;
  padding: 20px;
  padding-right: 10px;
  outline: none;
}
#picWall .pic {
  position: relative;
  width: 150px;
  height: 150px;
  border-radius: 8px;
  margin-right: 10px;
  margin-bottom: 10px;
}
#picWall .pic:hover .shadowBox {
  transition: 0.3s;
  background-color: rgba(82, 76, 76, 0.5);
}
#picWall .pic:hover .shadowBox span {
  transition: 0.3s;
  opacity: 1;
}
#picWall .pic img {
  width: 150px;
  height: 150px;
  border-radius: 8px;
}
#picWall .pic .shadowBox {
  display: flex;
  align-items: center;
  justify-content: center;
  position: absolute;
  top: 0;
  width: 150px;
  height: 150px;
  border-radius: 8px;
  background-color: rgba(81, 76, 76, 0);
}
#picWall .pic .shadowBox span {
  opacity: 0;
  cursor: pointer;
  color: white;
}
#picWall .pic .shadowBox span:nth-child(1) {
  margin-right: 10px;
}

JS

window.onload = function(){

    // $符号操作dom
  function $(vArg) {
    //通过获取css选择器第一位符号判断
     switch (vArg[0]) {
        case "#":
            return document.getElementById(vArg.substring(1));
             break;
        case ".":
            return elementByClassName(document,vArg.substring(1))
             break;
        default:
        //对参数前五个字符进行判断
            var str =vArg.substring(0,5);
            if (str == "name=") {
                return document.getElementsByName(vArg.substring(5))
            } else {//tagName
                return document.getElementsByTagName(vArg)
            }
             break;
     }
 }
 function elementByClassName(parent,classStr) {
     var nodes = parent.getElementsByTagName('*');
     var result = [];
     for (var i = 0; i < nodes.length; i++) {
        if (nodes[i].className == classStr) {
            result.push(nodes[i]);
        } 
     }
     return result;
 }

//  获取打开文件按钮
var openBtn = $("#openBtn")
// 获取input标签
var openFile = $("#openFile")
// 获取图片墙
var picWall = $("#picWall")
// 获取删除图片按钮
var deleteBtn = $(".deleteBtn")
// 获取图片盒子
var pic = $(".pic")
// 获取预览按钮
var previewBtn = $(".previewBtn")
// 获取关闭预览页面按钮
var closeBtn = $("#closeBtn")
// 获取预览图片
var previewPic = $("#previewPic")
// 获取预览图片页面
var previewBox = $(".previewBox")[0]
// 获取上传的图片
var upPic = $(".upPic")
// body元素
var scroll = $("#scroll")
// 获取上一张图片按钮
var nextBtn = $("#nextBtn")
var preBtn = $("#preBtn")
// 获取下一张图片按钮

updateFun()

// 点击打开上传图片
openBtn.onclick = function(){
    openFile.click()
}
openFile.onchange = function(){
    var  newUrl = window.URL.createObjectURL(this.files[0])
    picWall.innerHTML += `      
   <div class="pic">
    <img class="upPic"  src=${newUrl} alt="">
    <div class="shadowBox">
        <div class="previewBtn"><span class="iconfont icon-fangdajing1-xianxing"></span></div>
        <div class="deleteBtn"><span class="iconfont icon-lajixiang"></span></div>
    </div>
  </div> 
`
  updateFun()
}
//被拖拽元素在目标元素上移动时触发,必须阻止默认事件,否则拖拽不生效
picWall.ondragover = () => false
    /* 阻止图片默认拖拽链接--start*/
document.ondragover = () => false
    /* 阻止图片默认拖拽链接--end*/
document.ondrop = () => false

picWall.ondrop = (e) => {

    let file = e.dataTransfer.files[0];//获取上传的文件
    let reader = new FileReader();//创建FileReader读取文件
    //读取成功后触发函数
    reader.onload = () => {
       
        var newUrl = reader.result;//图片地址
        console.log(newUrl)
        picWall.innerHTML += `      
       <div class="pic">
         <img class="upPic" src=${newUrl} alt="">
         <div class="shadowBox">
             <div class="previewBtn"><span class="iconfont icon-fangdajing1-xianxing"></span></div>
             <div class="deleteBtn"><span class="iconfont icon-lajixiang"></span></div>
         </div>
       </div> 
     `
    updateFun()  
    };
    //设置读取方式 ,这里读取的结果会在 reader.onload回调中reader显示
    reader.readAsDataURL(file)
}

// 照片墙粘贴触发事件
picWall.onpaste = function(e){
  var data = e.clipboardData.items[0].getAsFile()
  e.preventDefault()
  console.log(data)
  var Url = window.URL.createObjectURL(data)
 
  picWall.innerHTML += `      
  <div class="pic">
    <img class="upPic" src=${Url} alt="">
    <div class="shadowBox">
        <div class="previewBtn"><span class="iconfont icon-fangdajing1-xianxing"></span></div>
        <div class="deleteBtn"><span class="iconfont icon-lajixiang"></span></div>
    </div>
  </div> 
`
updateFun()
}


function imgMove(img) {
    // 图片坐标信息
    let imgTop = 0;
    let imgLeft = 0;
    // 鼠标坐标信息
    let mx = 0;
    let my = 0;
    // 图片拖动开始前
    img.ondragstart = e => {
        // 初始化鼠标坐标信息
        mx = e.clientX;
        my = e.clientY;
    }

    // 图片拖动中
    img.ondrag = function(e){
         cancelHandler(e)      
        if (e.clientX <= 277 || e.clientX >= 746 || e.clientY <= 36 || e.clientY >= 483) {
            return
        }
        console.log(e.clientY)
        imgTop = imgTop + e.clientY - my;
        imgLeft = imgLeft + e.clientX - mx;
        mx = e.clientX;
        my = e.clientY;
        img.style.transform = `translate(${imgLeft}px,${imgTop}px)`

    }
}


function updateFun(){
    var deleteBtn = $(".deleteBtn")
    var pic = $(".pic")
    var previewBtn = $(".previewBtn")
    var upPic = $(".upPic")
    var picSize = 200
    var index = 0
    // 绑定关闭预览图片界面
    closeBtn.onclick  = function(){
        previewBox.style.display = 'none'
        scroll.style.overflow= "visible"
    }

    for (let t = 0; t < deleteBtn.length; t++) {
        // 绑定删除图片事件
       deleteBtn[t].onclick = function(){
       picWall.removeChild(pic[t])
       }
        // 绑定预览图片事件
        previewBtn[t].onclick = function(){
            previewBox.style.display = 'block'  
            previewPic.style.height = '200px'
            previewPic.style.width =  '200px'
            previewPic.src = upPic[t].src
            index = t
            scroll.style.overflow= "hidden"
            previewPic.style.transform = `translate(0,0)`
        }
    }
    // 绑定滚轮缩放照片事件
    previewPic.onwheel = function(e){
        // console.log(e.deltaY/125)
        picSize += -(e.deltaY/125)*50
        // if(picSize >= 450) picSize = 450
        if(picSize <= 150) picSize = 150
        previewPic.style.height = picSize + 'px'
        previewPic.style.width = picSize + 'px'
        if(parseFloat(previewPic.style.height)>450){
            imgMove(previewPic)
        }else{
            previewPic.style.transform = `translate(0,0)`
        }
    }
    
    // 返回上一张图片
    preBtn.onclick = function(){
       if(index === 0){
        index = upPic.length - 1
       }else{
         index --
       }
       previewPic.style.height = '200px'
       previewPic.style.width =  '200px'
       if(parseFloat(previewPic.style.height)>450){
        imgMove(previewPic)
       }
       previewPic.style.transform = `translate(0,0)`
       previewPic.src = upPic[index].src
    }

    // 下一张图片
    nextBtn.onclick = function(){
        if(index === upPic.length - 1 ){
            index = 0
           }else{
             index ++  
           }
           previewPic.style.height = '200px'
           previewPic.style.width =  '200px'
           if(parseFloat(previewPic.style.height)>450){
            imgMove(previewPic)
           }
           previewPic.style.transform = `translate(0,0)`
           previewPic.src = upPic[index].src
    }
}


 //封装了一个取消默认事件的函数,用来兼容老IE
 function cancelHandler(event){
      if (event.preventDefault) {
          event.preventDefault();
      } else {
          event.returnValue = false;
      }
  }


}

1664686328165.jpg