手写原生代码专题 | 图片拖拽效果(一)

前端达人

共 5441字,需浏览 11分钟

 ·

2021-06-03 15:38

一、系列介绍

前端的小伙伴们,我想大多数都是颜值控吧,看到一个漂亮或新奇的效果,都想搞明白是怎么实现的吧。但是前端发展的实在太快,各种框架和组件五花八门,由于项目业务时间的问题,我们都习惯了使用各种框架和组件去实现,以至于离开这些东西,我们有可能连个最基础的动效都不清楚怎么实现,这就是我想写这个系列文章的原因,除了这个原因,也是方便小编自己总结和梳理,日后用到时方便查阅。总之练习这些基础的项目并不low,放低姿态,从最基础的原生代码开始复习实践,帮助我们梳理基础知识,日积月累,一定会有不少收获。

本系列文章小编将和大家一起从最基础的原生代码实践,做一些小的项目,从最基础的实践中复习和掌握前端的一些基础知识,只有熟练了才能理解前端的本质,学习前端新的知识和框架时就能更快的上手。本专题文章会用到 ES6、css3的特性来实践目前比主流的交互特效。

二、 图片拖拽效果介绍

本篇文章,如下视频所示,界面有5个方格拖放区域,我们可以在这些区域里拖拽图片,当鼠标拖动图片时,图片周围有灰色的粗边框效果提示用户当前元素可拖动,在可放置图片的目标方格会出现白色的虚线边框并且背景色更改为黑色,提示用户可以在此位置放置被拖动的图片,结束拖动时(松开鼠标时),图片将会放置在目标方格内。

三、拖拽相关知识复习

在练习前,我们先复习下和拖拽相关的几个API事件,在某个元素被拖动时,会按照顺序触发以下事件:

  1. dragstart(按住鼠标不放,刚开始拖动元素时,就会触发 dragstart 事件)
  2. drag(dragstart 事件触发后,只要元素还在被拖动时,就会持续触发 drag 事件,类似 mouseover,随着鼠标移动而不断触发)
  3. dragend(当拖动元素的动作停止时即松开鼠标时,放到目标位置或非目标位置,都会触发此事件)

以上三个事件,都是针对被拖动元素的,并不会改变被拖动元素的外观,如果你想改变外观需要自己定义。

除了这些事件,当你把元素拖动到一个有效的放置目标上时,会依次触发以下事件:

  1. dragenter(只要被拖动元素进入目标位置上,就会立即触发)
  2. dragover(dragenter事件触发后,会立即触发此事件,如果被拖动元素,还在目标元素内持续拖动,会持续触发此事件)
  3. dragleave 或 drop(当被拖动的元素,放置在目标之外,dragover事件就会立即停止,触发dragleave事件;如果被拖动元素被放到了目标上,则会触发drop事件)

四、开始编写代码

复习完基础知识后,我们来开始动手实践吧,我们依次创建3个文件 index.html,style.css,script.js,然后在 index.html 文件里引入样式和脚本文件,接下来我们开始编写代码吧!

1、编写HTML代码

html代码文件比较简单,我们依次创建5个div方格,并将被拖动的图片元素容器初始化放置在第一个方格内,并在元素上添加可拖动属性 draggable 值为 true,表示此元素可被拖动(可调用拖拽API),示例代码如下:

<divclass="empty">
    <divclass="fill"draggable="true"></div>
</div>

<divclass="empty"></div>
<divclass="empty"></div>
<divclass="empty"></div>
<divclass="empty"></div>

2、编写CSS样式

接下来,我们来编写相关的CSS样式,代码很简单,这里只是简单说明下:

  1. 首先我们先定义全局样式,让五个方格水平垂直居中,这里我们使用flex弹性盒子布局;
  2. 接下来我们定义五个方格样式:宽高150px,背景元素为白色,边框为黑色;
  3. 被拖动的图片样式:宽高145px,图片路径我们调用了unsplash.com 提供的图片服务,可以按照图片大小随机图片,在我们需要图片测试数据时,这个服务非常有用;
  4. 为了让用户比较直观的感受哪个元素正在被拖动,我们定义元素被拖动的外观样式,给图片定义5px宽的灰色边框。
  5. 在拖动至目标位置元素时,为了让用户更直观的感受到哪些位置是可以放置的目标元素,我们需要给其定义 hovered 样式,进入目标位置元素时,样式发生改变,背景为黑灰色,并有白色的边框虚线。
  6. 为了适应小屏幕,将五个方格由水平排列更改为垂直居中排列。

以上就是我们编写样式代码的思路,相关的CSS代码如下:

*{
    box-sizing: border-box;
}

body{
    background-color: steelblue;
    display: flex;
    align-items: center;
    justify-content: center;
    height100vh;
    overflow: hidden;
    margin0;
}

.empty{
    height150px;
    width150px;
    margin10px;
    border: solid 3px black;
    background-color: white;
}

.fill{
    background-imageurl("https://source.unsplash.com/random/150x150");
    height145px;
    width145px;
    cursor: pointer;
}

.hold{
    border: solid 5px #ccc;
}

.hovered{
    background-color#333;
    border-color: white;
    border-style: dashed;
}

@media(max-width: 800px) {
    body{
        flex-direction: column;
    }
}

3、编写JS脚本

最后我们来编写脚本代码,在编写前,我们需要提前规划思考下,具体思路如下:

  1. 首先定义两个DOM对象变量fill和empties,一个代表被拖动的图片对象,一个是可放置元素的目标对象(数组对象)。
  2. 在被拖动的图片元素上,绑定 dragstart 和 dragend事件。
  3. 在可被放置图片的目标元素进行循环迭代,依次绑定 dragenter、dragover、dragleave、drop 事件。
  4. 接下来我们分别来定义相关事件函数, dragstart :当图片目标刚被拖动时,我们为元素添加灰色的粗边框属性 .hold,并将当前此元素的容器背景div隐藏,这里使用样式 invisible。
  5. 鼠标放下时,拖拽动作结束,触发dragend事件,我们定义 dragEnd() 函数,将图片元素的容器样式更改为fill。
  6. 接下来,我们来定义拖动至目标位置元素触发的相关事件函数,进入目标元素时,触发 dragEnter:阻止默认的浏览器行为,为其添加进入目标位置的元素样式 .hovered;在目标位置元素移动拖动元素时的 dragOver 函数:阻止浏览器的默认行为;当元素离开目标位置时 dragLeave,我们需要将当前元素的样式更改为原始的样式 empty;最后定义 dragDrop 函数,用户在目标位置放置拖动的图片元素,松开鼠标时触发,我们先将当前位置的样式更改为empty,并在其中添加拖动的图片元素容器。

思路就聊到这里,下面给出脚本相关的代码,示例代码如下:

constfill=document.querySelector(".fill");
constempties=document.querySelectorAll(".empty");

fill.addEventListener('dragstart',dragStart);
fill.addEventListener('dragend',dragEnd);

for(constemptyofempties){
    empty.addEventListener('dragenter',dragEnter);
    empty.addEventListener('dragover',dragOver);
    empty.addEventListener('dragleave',dragLeave);
    empty.addEventListener('drop',dragDrop);
}

functiondragStart(){
this.className += " hold";
setTimeout(()=>this.className='invisible',0)
}

functiondragEnd(){
this.className='fill'
}

functiondragOver(e){
    e.preventDefault();
}

functiondragEnter(e){
    e.preventDefault();
this.className += " hovered"
}

functiondragLeave(){
this.className='empty'
}

functiondragDrop(){
this.className="empty"
this.append(fill)
}

结束语

好了,今天的项目就到这里结束了,想必大家都熟悉了拖拽相关的事件和如何应用,有了这些基础后,我们就有了写出更复杂拖拽应用的基础。最后大家可以点击阅读原文体验交互效果(在PC端体验),如果想获取本案例源码,请关注「前端达人」公众号,回复 “a01” 获取本项目源码。

浏览 19
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报