专栏首页前端达人手写原生代码专题 | 图片拖拽效果(一)

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

一、系列介绍

前端的小伙伴们,我想大多数都是颜值控吧,看到一个漂亮或新奇的效果,都想搞明白是怎么实现的吧。但是前端发展的实在太快,各种框架和组件五花八门,由于项目业务时间的问题,我们都习惯了使用各种框架和组件去实现,以至于离开这些东西,我们有可能连个最基础的动效都不清楚怎么实现,这就是我想写这个系列文章的原因,除了这个原因,也是方便小编自己总结和梳理,日后用到时方便查阅。总之练习这些基础的项目并不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;
    height: 100vh;
    overflow: hidden;
    margin: 0;
}

.empty{
    height: 150px;
    width: 150px;
    margin: 10px;
    border: solid 3px black;
    background-color: white;
}

.fill{
    background-image: url("https://source.unsplash.com/random/150x150");
    height: 145px;
    width: 145px;
    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” 获取本项目源码。

本文分享自微信公众号 - 前端达人(frontend84),作者:前端达人

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2021-05-30

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Flutter 可以缩放拖拽的图片

    在pub上面找了下,没有发现一个效果跟微信一样的支持缩放拖拽效果的image,所以就自己撸了一个,之前写过Flutter 什么功能都有的Image,于是就在这个...

    Android技术干货分享
  • Android使用ViewDragHelper实现QQ聊天气泡拖动效果

    本文的目的是实现类似于QQ消息提醒的气泡的拖拽效果。网上已有大神的实现效果是通过监听控件的OnTouchEvent事件的ACTION_DOWN,ACTION_M...

    砸漏
  • 微信公众号Markdown Here排版的缺失环节

    早上看了一下微信公众号后台。我上一篇微信公众号什么时间发的?看完我自己都吓了一跳——4月15日!

    王树义
  • 使用Typora+PicGo配置Gitee图床

    https://pan.baidu.com/s/1J8U22Q87U3kDPtDy8EOa4A 提取码:glj5 复制这段内容后打开百度网盘手机 App,操作更...

    清菡
  • HTML5原生拖放事件的学习与实践

    之前学习了 HTML5 的拖放事件,开发中也用到了拖拽组件。为了厘清整体的逻辑,专门做了一个小例子。

    心谭博客
  • 基于React+Koa实现一个h5页面可视化编辑器-Dooring

    前段时间笔者一直忙于数据可视化方面的工作,比如如何实现拖拽式生成可视化大屏,如何定制可视化图表交互和数据导入方案等,这块需求在B端企业中应用非常大,所以非常有探...

    徐小夕
  • 史上最详细仿QQ消息拖拽粘性效果

    https://github.com/lygttpod/AndroidCustomView/blob/master/app/src/main/java/com/...

    陈宇明
  • Android自定义View之仿QQ未读消息拖拽效果

    绘制以上两条贝塞尔曲线和直线需要五个点:P1,P2,P3,P4,M,其中P1,P2,P3,P4是圆的切点,现在只知道两个圆的中心圆点O1和O2,那么怎么根据这两...

    Rouse
  • 这里有一份史上最详细仿QQ未读消息拖拽粘性效果的实现,快来收藏!

    原文链接:https://www.jianshu.com/p/ed2721286778

    Android技术干货分享

扫码关注云+社区

领取腾讯云代金券