拖拽上传图片——jquery版

实现文件的拖拽功能主要用到HTML5提供的两个API Drag和Drop。我们先来了解一下API的作用:

拖放事件

关于拖放事件有些是在被拖动元素上触发的,而有些则是在放置目标上触发的

当我们拖动某个元素时,会依次触发:

  • ondragstart
  • ondrag
  • ondragend

这三个事件都是在被拖动元素上触发的。当拖动开始时会先触发dragstart事件,然后在拖动的过程中会持续触发drag事件,当拖动停止时(无论被拖动元素是否放到了有效的放置目标)都会触发dragend事件,这三个事件类似鼠标的移动事件mousestart,mousemove,mouseend

当某个元素被拖动到放置目标上,会依次触发:

  • dragenter
  • dragover
  • dragleave 或 drop

这三个事件都是在放置目标上触发的。当元素进入放置目标时会触发dragenter事件,当元素在放置目标上移动时会持续触发dragover事件,当元素移出放置目标时会触发dragleave事件,当元素被放到了放置目标中会触发drop事件而不是dragleave事件,这几个事件(除drop)也类似鼠标的移动事件mouseenter,mouseover,mouseleave

阻止默认行为。虽然所有的元素都支持drop事件,但是这些元素默认是不允许放置的,这个时候当我们在放置目标上松开鼠标是不会触发drop事件的,我们可以通过event.preventDefault()来阻止默认的行为,如下:

droptarget.ondragenter = event => {
    event.preventDefault()
}
droptarget.ondragover = event => {
    event.preventDefault()
}
复制代码

另外在一些浏览器中,当我们移动图片到放置目标上,松开的时候会打开这张图片,如果移动的是超链接,则会打开这个页面。我们有时候需要阻止这种默认的行为,可以这样做

droptarget.ondrop = event => {
    event.preventDefault()
}

dataTransfer对象

dataTransfer对象用来在拖动的过程中从被拖动元素向放置目标传递数据,这个对象有两个方法setData和getData

setData有两个参数,第一个是MIME类型,第二个则是我们要保存的值

event.dataTransfer.setData('text/plain', 'msg')
event.dataTransfer.setData('text/uri-list', 'http://baidu.com')
复制代码

getData只有一个参数,就是setData中我们传的第一个参数

event.dataTransfer.getData('text/plain')
event.dataTransfer.setData('text/uri-list')
复制代码

setData我们一般在dragstart中去使用,而getData只能在drop事件中去使用,这个务必记住

你拖动一个图片到目标区域,那目标区域怎么获取这个图片的信息呢?就靠它!它是事件对象的一个属性,用于从被拖动元素向放置目标传递字符串格式的数据。
拖拽上传图片——jquery版_第1张图片

SparkDM5

上传图片用图片文件的对象hash哈希值判断图片是否一样,避免重复提交相同的图片到服务器中,这里我们采用SparkMD5来生成文件hash值。

拖拽上传图片——jquery版_第2张图片

示例

页面:




  
  
  Document
  
  
  
  


  
图片展示区:
将图片拖拽至此处上传

js

const img_arr = [];
// 文件上传
function uploadFile() {
  $("#file").click();
}

function upload(files) {
  const MAX_COUNT = 3;
  const IMG_COUNT = MAX_COUNT - img_arr.length;
  const additional_arr = [];
  const IMG_TYPES = ['image/jpeg', 'image/jpg', 'image/png', 'image/gif'];
  if (Array.prototype.some.call(files, function(file) {return !IMG_TYPES.includes(file.type)})) {
    layer.msg("图片格式不正确!!!")
    $("#file").val('');
    return;
  }

  if (files.length > IMG_COUNT) {
    layer.msg(`最多只能上传${MAX_COUNT}张图片!`)
    $("#file").val('');
    return;
  }

  Array.prototype.forEach.call(files, function(file, i, arr) {
    const fileReader = new FileReader();
    const sparkMD5 = new SparkMD5();
    fileReader.readAsDataURL(file);
    fileReader.onload = (event) => {
      const binary =  event.target.result;
      // 生成图片hash
      const hash = sparkMD5.appendBinary(binary).end();
      // 判断是否存在相同的图片
      if (!isExists(hash)) {
        additional_arr.push({
          hash,
          src: binary,
          file
        });
      } else {
        // 中断文件流
        fileReader.abort();
        layer.msg("请不要上传相同的图片!!!");
      }
    };
    fileReader.onloadend = (event) => {
      // 读取完成
      if (additional_arr.length === arr.length) {
        img_arr.push(...additional_arr);
        show(additional_arr); // 展示在展览区
        $("#file").val('');
      }
    }
  })
} 

// 判断是否有相同的图片
function isExists(hash) {
  return img_arr.some(function(item) {
    return item.hash === hash;
  })
}

// 文件change
function fileChange(that, event) {
  const files = event.target.files;
  upload(files);
}


/** 控制删除icon */
function imgMouseEnter(that) {
  $(that).find("span.del-icon").css('display', 'block');
};

function imgMouseLeave(that) {
  $(that).find("span.del-icon").css('display', 'none');
}


/** 展示图片 */
function show(additional_arr) {
  if (!additional_arr.length) {
    return;
  }

  const img_html = additional_arr.reduce(function(init, item) {
    init += `
      
      
    `
    return init;
  }, '');

  $(".show-area").append(img_html);
}

// 删除
function deleteImg(that) {
  const hash = $(that).attr("hash");
  const $imgBox = $(that).parents(".img-box");
  $imgBox.remove();
  img_arr.splice(img_arr.findIndex(function(item) {
    return item.hash === hash;
  }), 1);
}

// 获取元素位置
function getElementLeft(element){
 var actualLeft = element.offsetLeft;
 var current = element.offsetParent;

 while (current !== null){
   actualLeft += current.offsetLeft;
   current = current.offsetParent;
 }
 return actualLeft;
}

function getElementTop(element){
 var actualTop = element.offsetTop;
 var current = element.offsetParent;

 while (current !== null){
  actualTop += current.offsetTop;
  current = current.offsetParent;
 }
 return actualTop; 
}

/** =================== drag ================= */
function imgDrag(that, event) {
  var e = event || window.event;
  e.preventDefault()
  e.stopPropagation()
}

function dragUpload(that, event) {
  var e = event || window.event;
  e.preventDefault()
  e.stopPropagation()
  const files = e.dataTransfer.files;
  upload(files);
}

// 拖拽删除
function imgDragEnd(that, event) {
  const hash = $(that).attr("hash");
  const $showArea = $(".show-area");
  const $imgBox = $(that).parents(".img-box");
  const width = $showArea[0].clientWidth;
  const height = $showArea[0].clientHeight;
  const origin = {
    x: getElementLeft($showArea[0]),
    y: getElementTop($showArea[0])
  };

  const target = {
    x: event.clientX,
    y: event.clientY
  }

  if (target.x - origin.x > width || target.x < origin.x || target.y - origin.y > height || target.y < origin.y) {
    $imgBox.remove();
    img_arr.splice(img_arr.findIndex(function(item) {
      return item.hash === hash;
    }), 1);
  }
  $showArea.css("border", "1px dashed #c3c3c3");
}

function imgDragOver(that, event) {
  const $showArea = $(that).parents(".show-area");
  $showArea.css("border", "1px solid #0065ff");
}

css

html, body {
  position: relative;
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
}

#drag-show {
  padding-top: 40px;
  line-height: 60px;
  text-align: center;
}

.show-area {
  display: inline-block;
  height: 60px;
  line-height: 60px;
  width: 180px;
  border: 1px dashed #c3c3c3;
  border-radius: 5px;
  vertical-align: middle;
}

.title {
  display: inline-block;
  line-height: 60px;
  color: #555;
  font-size: 20px;
  vertical-align: middle;
}

.img-box {
  position: relative;
  display: inline-block;
  width: 50px;
  height: 50px;
  line-height: 50px;
  margin-right: 8px;
  vertical-align: middle;
  cursor: pointer;
}

.img-span {
  display: inline-block;
  width: 100%;
  height: 100%;
  vertical-align: middle;
  overflow: hidden;
}

.img-item {
  display: inline-block;
  width: 100%;
  vertical-align: middle;
}

.del-icon {
  position: absolute;
  top: -7px;
  right: -7px;
  width: 14px;
  height: 14px;
  background-image: url('./del.png');
  background-size: 100% 100%;
  cursor: pointer;
}

#drag-area {
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  left: 50%;
  width: 300px;
  height: 200px;  
  margin-left: -150px;
  margin-top: 20px;
  color: #555;
  font-size: 20px;
  border-radius: 12px;
  border: 1px dashed #c3c3c3;
}

.upload-box {
  display: inline-block;
  width: auto;
  height: auto;
}


#upload {
  display: inline-block;
  width: 50px;
  height: 50px;
  padding: 8px;
  margin-top: 10px;
  box-sizing: border-box;
  border-radius: 5px;
  border: 1px dashed #c3c3c3;
  background-size: 100% 100%;
  background-image: url('./plus.png');
  cursor: pointer;
}

#upload:hover {
  background-color: #fafafa;
}

效果:

你可能感兴趣的:(拖拽,上传,上传图片,jquery)