HTML5+JS:拖动元素
本帖最后由 马黑黑 于 2022-2-9 22:07 编辑HTML的元素一般都是静止状态,但交互离不开元素的可拖动性,因此,HTML5引入了 draggable 属性。draggable源于动词 drag,拖动,able 作为形容词后缀,表示可以、能够等意思,draggable就是可拖动的之意(注意g要双写)。
当web元素拥有 draggable="true" 的属性设定,理论上它是可以拖动的,不论它是一个图片,还是一个 div,甚至只是一个链接。这里,以图片为例,将 draggable 属性写入 img 标签:
<img id="img1" alt="" src="图片地址" draggable="true" />
这样,理论上,图片就是可以拖动的。但是,wed可视对象能否真正被拖动,HTML自身无法独立完成,img标签仅赋予了图片可拖动的属性,真正实现起来,需要通过设计一系列的 JS 函数来帮忙完成。
第一,我们要明确拖动什么,可用 dataTransfer.setData() 方法来设置被拖放内容的相关数据。
data是数据,transfer,转移之意,dataTransfer就是数据转移、移动、拖动;set,设置,setData,设置数据。此方法需要两个参数:格式和数据。第一个参数,即数据格式,我们可以自设为“pic”或其他的,是将来要引用数据的关键词依据,保持声明引用前后一致就行,第二个参数,即数据,就是图片呀什么的要被拖动的对象,它通过目标对象的 id 标识符来表示。
比如,假设有一个元素叫 obj,则如果要拖动这个元素,可以这么办:
dataTransfer.setData("pic",obj.target.id);
如前已解释,pic是我们定义的数据格式或类型标识,将在后续被使用,要放在引号里;第二个参数 obj.target.id 语句里,obj是我们定义的对象名,target.id 是目标id,必须这样表达,强记。
现在,我们来设计一个JS函数,完成定义要拖动什么的工作:
function drag(obj) {
obj.dataTransfer.setData("pic", obj.target.id);
}
drag(obj)是我们自定义的函数,函数名 drag,函数参数是obj,指被拖动对象。函数内容放在大括号里,表示对象obj通过 dataTransfer.setData() 方法,定义数据类型为 pic 的 obj 为即将被移动的对象(内容)。
drag(obj)这个函数发生在HTML对象开始移动之时,即 JS 对应的 ondragstart 事件,所以,img标签的HTML代码要加入它,通过 ondragstart 事件 调用 drag(obj) 函数,drag(obj)函数的参数不能随便命名,只能用“event”这个单词,亦即,告诉函数 drag(obj),我们要在图片的 ondragstart 事件中调用你,你的 obj 参数传入的是 event 元素:
<img id="img1" alt="" src="图片地址" draggable="true" ondragstart="drag(event)" />
再次强调:上句,新加入的蓝红字串里,自定义的drag()函数的obj参数只能用 event(元素)这个单词传入,后面定义的自定义函数也是这样使用。
第二,移动到何处。移民要有接收地,假如你是移民,你从A国出发,即 ondragstart 事件已经发生,下一步就是路经(over)某国,JS对应的 ondragover 事件发生,经过B国时,HTML世界里,默认是不接纳移民被放下(drop)的,我们需要取消该拒绝移民的“政策”:
preventDefault()
这是“阻止默认属性”之意,亦即取消默认设置,令其开放准许接接收“移民”。我们需要设计一个函数来发出我们的强迫B国接收移民的函数指令:
function allowDrop(obj) {
obj.preventDefault();
}
这个函数我们也设计了一个参数 obj,对象之意,obj是一个函数变量,这里它不是指图片,而是指接收图片“移民”的一个“国家”,B国,在HTML里,可以是一个 div 盒子:
(这个地方代码编辑起来很怪异,请参阅后面的相应代码)
好了,B国允许移民了,那就把移民放下,这个需要 JS 对应的 ondrop 方法,我们同样要为这个方法设计一个函数:
function drop(obj) {
obj.preventDefault();
var data = obj.dataTransfer.getData("pic");
obj.target.appendChild(document.getElementById(data));
}
drop(obj) 是我们自定义的函数,在这里,obj 参数指被放下的图片对象(即“移民”),首先申明去除图片被放下时接收地打开方式的默认设定(默认是链接处理),再通过getData方法获取被放下的目标数据类型依据,即pic(参考第一步的解释),赋值给data句柄变量,接着在目的地即“B国”用 appendChild(追加孩子)的方法将图片追加到其中。
drop(obj)函数在B国 div 中通过 ondrop 事件调用:
(这个地方代码编辑起来很怪异,请参阅后面的相应代码)
完整的HTML和JS代码如下(设定了图片尺寸与div边框以方便观察效果):
<img id="img1" alt="" src="./pic/2.jpg" draggable="true" ondragstart="drag(event)" width="200" />
<div id="B国" ondragover="allowDrop(event)" ondrop="drop(event)" style="border:1px solid; width:400px;height:400px;"></div>
<script language="javascript">
function drag(obj) {
obj.dataTransfer.setData("pic", obj.target.id);
}
function allowDrop(obj) {
obj.preventDefault();
}
function drop(obj) {
obj.preventDefault();
var data = obj.dataTransfer.getData("pic");
obj.target.appendChild(document.getElementById(data));
}
</script>
怪不得黑黑说这个比较难懂,的确有点绕。黑黑辛苦了{:4_187:} 红影 发表于 2022-2-9 22:40
怪不得黑黑说这个比较难懂,的确有点绕。黑黑辛苦了
绕就算了,编辑还不顺畅,我可是在线编写的,然后再把编写的代码放在本地测试 img那句里的id="img1" 和div里的id="B国",这两个没看懂,为什么要设置两个id=
另外,obj的定义函数一直被使用到,但是pic的数据类型没看懂,这个也和 event一样是必须这样用的么?还有别的数据类型的吧? 哦,知道了,pic是数据的代称,为了让obj借它拿到数据。 马黑黑 发表于 2022-2-9 22:43
绕就算了,编辑还不顺畅,我可是在线编写的,然后再把编写的代码放在本地测试
黑黑辛苦了,这么绕的东西,能说得这么清晰,相当不容易呢{:4_199:} drag,这个单词有意思,中文发音是拽K,和它的本意很像,拽呀拽就是drag了{:4_170:} 马黑黑 发表于 2022-2-9 22:43
绕就算了,编辑还不顺畅,我可是在线编写的,然后再把编写的代码放在本地测试
这个命令的绕,就在于开始赋予的各种含义都用的event的名,而后面真正运作的是另外设定的代称。
有种隔层皮的感觉,不那么直接{:4_173:} 红影 发表于 2022-2-9 23:09
这个命令的绕,就在于开始赋予的各种含义都用的event的名,而后面真正运作的是另外设定的代称。
有种隔 ...
event是元素的意思,它是固定的。编写函数是用的obj是代称,用别的也可以 红影 发表于 2022-2-9 23:02
drag,这个单词有意思,中文发音是拽K,和它的本意很像,拽呀拽就是drag了
drag就是拉、拖拽的意思,其实应该读成 拽哥{:5_117:} 红影 发表于 2022-2-9 23:01
黑黑辛苦了,这么绕的东西,能说得这么清晰,相当不容易呢
这个确实不太好解释,比解释闭包还困难 今天先看一下,这个得反复学习领会了才会操作
黑黑肚子里面的宝藏太多了{:4_173:}
明天上班了。今天得早睡,有时间再上来仔细看看。 小辣椒 发表于 2022-2-9 23:39
今天先看一下,这个得反复学习领会了才会操作
黑黑肚子里面的宝藏太多了
没有JS基础,这个理解起来难度较大 红影 发表于 2022-2-9 22:55
img那句里的id="img1" 和div里的id="B国",这两个没看懂,为什么要设置两个id=
另外,obj的定义函数一直 ...
首先,document里的元素,id是唯一的,图片的id、div的id不能同名。
其次,JS里的函数,都用到 target.id 关键字,这些自定义函数是通过目标元素的id进行相关操作,所以,作为被拖动对象的img图片和作为接收图片的容器的div都必须要id标识。
第三:这些id标识我们的函数不去读取确切的名称,有就行,所以命名时可以随意,但必须有,还不能与document内的其他元素同名。 红影 发表于 2022-2-9 22:55
img那句里的id="img1" 和div里的id="B国",这两个没看懂,为什么要设置两个id=
另外,obj的定义函数一直 ...
关于 obj 和 ”pic“标识:、
obj 是函数的参数,我用 object 这个单词的缩写,对象的意思,自定义的名称,并不是唯一可用的,也可以用其他的,而且,每个函数(我们总共编写了三个函数)的参数名称可以不同。这个参数 obj 是待传输数据的标识,所以他怎么命名都没关系,本例中这些函数传入的都是 event 关键字(event是内置关键字,不能改),也就是说,event 接管 obj 这个参数 ,并且我们的每一个函数都能识别 event 这个元素的是哪个元素(得益于target.id)。当函数有参数,一般写成 hanshu(参数名),“参数名”会在函数运行时被传入的数据代替,我们在函数中暂且把“参数名”当成数据处理。
“pic”是本例定义的图片数据标识,后面的函数读取放下的元素是哪一个时,通过这个标识识别被放下的对象,相当于一个口令,有了口令,pass。 马黑黑 发表于 2022-2-9 23:13
event是元素的意思,它是固定的。编写函数是用的obj是代称,用别的也可以
嗯,这个拖曳的命令需要慢慢看到熟悉,就不觉得怪了{:4_173:} 马黑黑 发表于 2022-2-9 23:14
drag就是拉、拖拽的意思,其实应该读成 拽哥
对对,哈哈,因为读音,倒是一下记住了这个单词,和中文的意思好接近的{:4_173:} 红影 发表于 2022-2-10 16:51
嗯,这个拖曳的命令需要慢慢看到熟悉,就不觉得怪了
代码并不长,函数也不多,就是方法、属性以及一些特定的命名可能陌生 红影 发表于 2022-2-10 16:52
对对,哈哈,因为读音,倒是一下记住了这个单词,和中文的意思好接近的
是的哦 马黑黑 发表于 2022-2-10 09:44
首先,document里的元素,id是唯一的,图片的id、div的id不能同名。
其次,JS里的函数,都用到 target.i ...
“这些id标识我们的函数不去读取确切的名称,有就行。”
所以这个也是让人感觉绕的原因之一。