用 js 的 selection range 操作选择区域内容和图片


Posted in Javascript onApril 18, 2017

先放上最后的效果,这是点击图片以前:

用 js 的 selection range 操作选择区域内容和图片

这是点击图片以后:

用 js 的 selection range 操作选择区域内容和图片

非常清晰,一目了然,就算是小白用户也明白发生了什么。挺好的。

最近在做编辑器相关的东西,遇到一个需求,用户在编辑器中插入或者粘贴的图片要支持点击以后,可以按 Backspace 键或者 Delete 键删除掉。

刚开始拿到这个需求的想法是调用编辑器自带的删除图片方法删掉图片,但后来查看源码发现这个方法是编辑器内部方法,并没有暴露出来,于是第一个思路走不通了。

第二个思路是在编辑器的顶层容器里监听 keyup 事件,然后判断是否是两个删除键,如果是就拦截,然后找到当前点击的图片,手动删掉。

实际上这也是行不通的,原因有二。首先,这个删除是没法阻止的,因为事件的监听是在顶层父元素里,这时候阻止其实是阻止掉事件在顶层容器上的效果,而不是在发生元素上的效果。所有涉及到事件冒泡的地方,在父容器上阻止效果都是不能达到目的的,只能在事件最开始发生的元素上阻止。 

然后,当按下删除键的时候,之前点击的图片已经不是点击状态了,已经拿不到了。因为取消选择在前,删除在后。

后来忽然意识到,想要的效果其实就是点击图片的时候选中图片,就像用户自己选中网页中一段内容那样选中那张图片就好了。页面上点击一个图片默认是没有效果的,我要做的仅仅是点击时候选中这个图片就可以了。这样做的好处是,当用户点击图片选中以后,如果点删除键,无论是 Backspace 还是 Delete 键都可以删除;而且如果用户不像删除,直接点击别的地方,或者按下上下左右箭头就可以取消选择,这和用户平时的操作体验是一样的,根本没有什么副作用。

selection 是 HTML5 的新接口,是 window 的一个方法,用法是 window.getSelection().

取得 selection 以后,要把当前图片加入到选取中,selection 有一个 Selection.selectAllChildren() 方法,但这个方法只能选中元素的全部子元素,而我们要选中的是 img 元素自身,img 元素也没有子元素。于是继续在 selection 的方法中看看有没有别的长的像的方法,果然,找到了 Selection.addRange() 看这长相一看就很像我们要找的人。addRange 方法需要传入一个 range 对象,range是啥呢?

平时在页面上选择东西都是鼠标咔一下框一大片,但如果在编辑器里,其实是可以选择好几个片段的,一般按住 Ctrl / Control 键就可以多处选择。我猜这个 selection 就类似于选中的所有区域,range 就类似于每一个单独的选中的片段,先这么理解。

继续往下看,发现 range 有一个 Range.selectNode() 方法,这不正是我要找的人吗?先创建一个 range 对象,let range = document.createRange()  createRange 是 document 的方法,然后讲当前图片插入 range,再把 range 插入 selection 中即可。代码如下:

let checkClickImg = function(e) {
 let target = e.target;
 if (target.nodeName.toLowerCase() === 'img') {
  // 删除之前所有的选区
  window.getSelection().removeAllRanges();
  let selection = window.getSelection();
  let range = document.createRange();
  range.selectNode(target);
  selection.addRange(range);
 }
}

这个实现方法的最大优点在于利用浏览器原生自带的功能,这样就和用户的操作习惯保持一致,不会有任何的突兀。选中的效果很明显,而且选中以后无论是删除,还是取消,都跟之前习惯一致,都很容易,更要的是这些操作不用再写代码了啊,因为是浏览器原生自带的功能。

嗯,算是比较完美了。

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持三水点靠木!

Javascript 相关文章推荐
jquery模拟按下回车实现代码
Sep 20 Javascript
JavaScript获取网页中第一个链接ID的方法
Apr 03 Javascript
浅析函数声明和函数表达式——函数声明的声明提前
May 03 Javascript
关于网页中的无缝滚动的js代码
Jun 09 Javascript
Vue.js如何优雅的进行form validation
Apr 07 Javascript
jquery单击文字或图片内容放大并居中显示
Jun 23 jQuery
vue实现图书管理demo详解
Oct 17 Javascript
关于Vue的路由权限管理的示例代码
Mar 06 Javascript
vue移动端实现下拉刷新
Apr 22 Javascript
VUE搭建手机商城心得和遇到的坑
Feb 21 Javascript
Jquery的autocomplete插件用法及参数讲解
Mar 12 jQuery
turn.js异步加载实现翻书效果
Jul 25 Javascript
jacascript DOM节点——元素节点、属性节点、文本节点
Apr 18 #Javascript
Angularjs根据json文件动态生成路由状态的实现方法
Apr 17 #Javascript
微信小程序实战之轮播图(3)
Apr 17 #Javascript
微信小程序实战之顶部导航栏(选项卡)(1)
Jun 19 #Javascript
微信小程序实战之上拉(分页加载)效果(2)
Apr 17 #Javascript
微信小程序教程系列之新建页面(4)
Apr 17 #Javascript
微信小程序商城项目之淘宝分类入口(2)
Apr 17 #Javascript
You might like
支持中文的PHP按字符串长度分割成数组代码
2015/05/17 PHP
thinkphp3.2中实现phpexcel导出带生成图片示例
2017/02/14 PHP
详解cookie验证的php应用的一种SSO解决办法
2017/10/20 PHP
Yii框架核心组件类实例详解
2019/08/06 PHP
ThinkPHP3.1.2 使用cli命令行模式运行的方法
2020/04/14 PHP
JavaScript中的对象化编程
2008/01/16 Javascript
jquery 简单图片导航插件jquery.imgNav.js
2010/03/17 Javascript
动态加载外部javascript文件的函数代码分享
2011/07/28 Javascript
js replace正则表达式应用案例讲解
2013/01/17 Javascript
JavaScript动态改变HTML页面元素例如添加或删除
2014/08/10 Javascript
js实现上传图片及时预览
2016/05/07 Javascript
原生js实现ajax方法(超简单)
2016/09/20 Javascript
Bootstrap modal 多弹窗之叠加显示不出弹窗问题的解决方案
2017/02/23 Javascript
移动端触摸滑动插件swiper使用方法详解
2017/08/11 Javascript
es6+angular1.X+webpack 实现按路由功能打包项目的示例
2017/08/16 Javascript
基于es6三点运算符的使用方法(实例讲解)
2017/10/12 Javascript
如何通过JS实现转码与解码
2020/02/21 Javascript
原生js实现下拉框选择组件
2021/01/20 Javascript
[00:59]PWL开团时刻DAY7——我在赶
2020/11/06 DOTA
Python实现读取txt文件中的数据并绘制出图形操作示例
2019/02/26 Python
python实现图片转字符小工具
2019/04/30 Python
Python中return函数返回值实例用法
2020/11/19 Python
html5 迷宫游戏(碰撞检测)实例一
2013/07/25 HTML / CSS
2014年圣诞节倒计时网页的制作过程
2014/12/05 HTML / CSS
普天C++笔试题
2016/03/20 面试题
什么是静态路由,其特点是什么?什么是动态路由,其特点是什么?
2013/07/26 面试题
亲戚结婚的请假条
2014/02/11 职场文书
道德模范先进事迹
2014/02/14 职场文书
拒绝黄毒毒宣传标语
2014/06/26 职场文书
生物学专业求职信
2014/07/23 职场文书
我的职业生涯规划:打造自己的运动帝国
2014/09/18 职场文书
商铺门面租房协议书
2014/10/21 职场文书
介绍信的写法
2015/01/31 职场文书
结婚司仪主持词
2015/06/29 职场文书
宝宝满月祝酒词
2015/08/10 职场文书
pytorch加载预训练模型与自己模型不匹配的解决方案
2021/05/13 Python