创建 Draggable
创建 Draggable( target:Object, vars:Object ) : Array
[静态] 一种比构造函数更灵活的创建 Draggable 实例的方式(相比new Draggable(...)
)。
参数
目标对象: 对象
可拖动的目标元素;这可以是一个普通的 DOM 元素或者是一组元素的数组。例如:
document.getElementById("yourID")
或者$("#yourID")
或者"#yourID"
或者[element1, element2, element3]
.vars: 对象
一个包含可选配置数据的对象,比如
{type: "x,y", inertia: true, edgeResistance: 0.8, onDrag: yourFunction}
.
返回值 : 数组
一组 Draggable 实例(每个元素对应一个实例)。
细节
比构造函数(new Draggable(...)
)创建 Draggable 实例提供了更灵活的方式,Draggable.create()
因为".yourClass"
. Draggable.create()
方法可以接收元素、元素数组,甚至像Draggable.create()
会为每个元素创建一个实例并返回一个数组。
下列用法都是有效的:
//a regular DOM element
Draggable.create(document.getElementById("yourID"), {type: "x,y"});
//or selector text
Draggable.create("#yourID", {type: "x,y"});
//or an array of elements
Draggable.create([element1, element2, element3], {type: "x,y"});
第二个参数是vars
包含任何可选配置数据的
配置对象
- 字符串- 指针按下到释放期间应该使用的光标 CSS 值。它可以与普通的
cursor
值,例如:cursor: "grab", activeCursor: "grabbing"
. - Boolean- 如果
true
,Draggable 将允许上下文菜单(比如用户右键点击或长按)。通常情况下这是被抑制的,因为它可能会妨碍拖动(尤其是在触摸设备上)。默认值:false
. - Boolean- 如果
true
,preventDefault()
不会在原始的鼠标/指针/触摸事件上调用。如果你希望允许默认行为(如触摸滚动),这可能很有用。然而通常来说,最好让 Draggable 调用preventDefault()
以获得最佳的拖拽用户体验。默认值:false
. - Boolean- 默认情况下,当 Draggables 限制为单一轴时,允许在相反方向进行原生触摸滚动。例如,一个
type: "x"
或者"left"
的 Draggable 允许垂直方向的原生触摸滚动,type: "y"
或者"top"
则允许水平方向的原生触摸滚动。默认值:true
. - 数字- 要启用当 Draggable 被拖动到可滚动容器边缘40像素以内时自动滚动,请将 autoScroll 设置为非零值,其中1表示正常速度,2表示双倍速度,依此类推(可以使用任意数字)。为了更直观或自然的效果,当鼠标/触摸越靠近边缘时会滚动得越快。默认值为0(不自动滚动)。请参阅这个 CodePen查看演示。
- [元素 | 字符串 | 对象]- 要使可拖动元素保持在另一个 DOM 元素(如容器)的边界内,你可以传入该元素,例如
bounds: document.getElementById("container")
或者甚至传入选择器文本如"#container"
。如果愿意,你也可以将边界定义为矩形,例如bounds: {top: 100, left: 0, width: 1000, height: 800}
它基于父级的坐标系统(top 和 left 是相对于父级左上角的位置)。或者你可以定义特定的最大和最小值,如bounds: {minX: 10, maxX: 300, minY: 50, maxY: 500}
或者bounds: {minRotation: 0, maxRotation: 270}
. - 对象- 所有回调函数(
onDrag
,onDragEnd
,onDragStart
等等)所使用的执行作用域。这个作用域决定了在任何回调函数中this
指向的对象。较旧的针对每个回调的作用域属性已被弃用但仍有效。 - 函数- 你的 Draggable 可能包含一些“可点击”的子元素,例如链接
<a>
标签,<button/>
或者<input>
元素等等。默认情况下,它对这些元素上的点击和轻触会有不同的处理方式,不允许用户拖动它们。你可以设置dragClickables: true
来覆盖此行为,但有时你可能还是想精确控制 Draggable 认为哪些元素是“可点击”的。因此你可以使用自定义函数,该函数接收被点击的元素作为唯一的参数,并返回 true 或 false。每当用户按下鼠标或手指在 Draggable 上时,Draggable 都会调用这个函数,并将事件的目标传递给你的 clickableTest 函数。 - 字符串- 默认情况下(除了
type: "rotation"
外),元素的 cursor CSS 属性会被设置为move
这样当鼠标悬停其上时会有视觉提示表明它可以移动。但你也可以根据需要定义不同的光标(如文档描述于https://devdocs.io/css/cursor)例如cursor: "pointer"
. - Boolean- 默认情况下,Draggable 可以应用于几乎所有元素,但有时你可能希望点击
<a>
,<input>
,<select>
,<button>
,以及<textarea>
元素(以及任何具有data-clickable="true"
属性的元素)不会触发拖动操作,这样浏览器的默认行为才会生效(例如点击输入框会获得焦点并放置光标以便开始输入)。如果你想让 Draggable 忽略这些点击并允许默认行为,则设置dragClickables: false
. - 数字- 一个介于0和1之间的数值,用于控制在拖动过程中持续施加到元素上的阻力大小。1 表示完全不允许拖动,0.75 表示较大阻力(使对象以四分之一速度移动),0.5 表示半速等等。这个设置甚至可以应用于旋转。
- 数字- 一个介于0和1之间的数值,用于控制当元素超出边界(如果有设置边界的话)时所受到的阻力大小。1 表示完全不允许拖出边界,0.75 表示较大阻力(拖动时对象在边界外以四分之一速度移动),0.5 表示半速等等。这个设置甚至可以应用于旋转。
- Boolean- 默认情况下,当浏览器支持时,会使用3D变换来强制将元素置于GPU自己的图层上,从而加快合成速度。通常这种做法性能最佳,但你可以通过设置
force3D: false
来禁用它。如果你正在拖动的元素包含正在动画的子元素,那么这样做可能是明智的选择。 - [Boolean | 对象]- InertiaPlugin 是在用户释放鼠标(或触摸)后实现基于动量运动的关键。要让 Draggable 在鼠标释放(或触摸结束)时自动对该元素应用一个 InertiaPlugin 动画,你可以设置
inertia: true
(inertia
也适用)。或者,对于高级效果,你可以定义实际的惯性对象,它会被传递到 tween 中,例如inertia: {top: {min: 0, max: 1000, end: [0,200,400,600]}}
。不过,如果你想要对 InertiaPlugin 动画进行完全控制,你可以简单地使用onDragEnd
调用你自己的函数来创建动画。如果定义了inertia: true
,你还可以使用以下适用于鼠标/触摸释放后运动的配置属性...查看更多详细信息
- snap: [函数 | 对象 | 数组] - 允许你定义规则,指定元素在释放后应该落脚在哪里。例如,你可能希望旋转总是停在90度的增量位置上,或者你希望
x
和y
希望值正好落在网格上(自然落点最近的格子),或者你可能希望它落在一个非常特定的值上。你可以通过以下任何一种方式定义这个对齐规则:- 作为一个函数- 这个函数会接收到一个数值参数,即自然结束的值。该函数必须返回新的结束值(你可以在函数内部运行任意逻辑并返回对应的值)。例如,要使值对齐到最接近的50的倍数,你可以这样做:
snap: function(endValue) { return Math.round(endValue / 50) * 50; }
. - 作为一个数组- 如果使用一组数值,InertiaPlugin 首先会计算自然落点,然后遍历数组并找出最接近的数字(只要它不在你定义的边界之外)。例如,从中选择最接近的10、50、200和450中的数值时,你可以这样做:
snap: [10,50,200,450]
. - 作为一个对象- 如果你希望对每个属性使用不同的逻辑,比如如果
type
设置为"x,y"
并且你希望x
部分对齐到一组特定的值,y
部分对齐到另一组值,你可以使用具有对应属性的对象,例如:snap:{x: [5,20,80,400], y: [10,60,80,500]}
或者如果type
设置为"top,left"
并且你想分别为其使用不同的函数,你可以这样写:snap: {top: function(endValue) { return Math.round(endValue / 50) * 50; }, left: function(endValue) { return Math.round(endValue / 100) * 100; }}
。你可以在该对象中定义一个 points 属性,将两者结合在一起:x
和y
,例如liveSnap: {points: [{x: 0, y: 0},{x: 100, y: 0}], radius: 20}
当该点在数组中距离在20像素(distance)以内时会自动贴靠到数组中的任意一点。或者你甚至可以使用基于函数的值来运行你自己的贴靠逻辑,例如:liveSnap: {points: function(point) { //run custom logic and return a new point }}
。有关示例,请参见本页的贴靠(snapping)部分。
- 作为一个函数- 这个函数会接收到一个数值参数,即自然结束的值。该函数必须返回新的结束值(你可以在函数内部运行任意逻辑并返回对应的值)。例如,要使值对齐到最接近的50的倍数,你可以这样做:
- onThrowUpdate : 函数- 每次 InertiaPlugin 的补间动画更新/渲染时调用的函数(基本上相当于每次引擎“tick”时激活补间动画)。这仅适用于用户释放鼠标/触摸后生成的补间动画 —— 在用户拖动元素时不会调用该函数(那是由
onDrag
控制的)。默认情况下,onThrowUpdate
的作用域是 Draggable 实例本身,但如果你更愿意,也可以定义一个callbackScope
,就像其他补间动画一样。 - onThrowComplete : 函数- 当 InertiaPlugin 补间动画完成时调用的一个函数。这仅适用于用户释放鼠标/触摸后生成的补间动画 —— 用户释放鼠标/触摸时并不会立即调用该函数 —— 那是由
onDragEnd
控制的。默认情况下,onThrowComplete
的作用域是 Draggable 实例本身,但如果你更愿意,也可以定义一个callbackScope
,就像其他补间动画一样。 - throwResistance : 数字- 一个数值(
1000
默认值)用于控制当鼠标/触摸释放并且启用了基于动量的运动(通过设置inertia: true
参数)时的阻力或摩擦力。数值越大,阻力越强,运动减速得越快。(需要 InertiaPlugin 和设置inertia: true
,否则throwResistance
会被忽略。) - maxDuration : 数字- 基于动能的惯性补间动画的最大持续时间(以秒为单位)。InertiaPlugin 会自动分析速度和边界,并确定合适的持续时间(通常更快的动作会导致更长的缓动时间),但你可以通过定义一个
maxDuration
来设置上限。默认值为10秒。这与用户拖动物体的最长时间无关 —— 它只针对释放鼠标/触摸后出现的惯性补间动画。(需要 InertiaPlugin 和设置inertia: true
,否则maxDuration
会被忽略。) - minDuration : 数字- 基于动能的惯性补间动画应保持的最小持续时间(以秒为单位)。InertiaPlugin 会自动分析速度和边界,并确定合适的持续时间(通常更快的动作会导致更长的缓动时间),但你可以强制让补间至少持续一段时间,通过定义一个
minDuration
默认值为0.2秒。这与用户拖动物体的最短时间无关 —— 它只针对释放鼠标/触摸后出现的惯性补间动画。(需要 InertiaPlugin 和设置inertia: true
,否则 minDuration 会被忽略。) - overshootTolerance : 数字- 影响在补间结束时平稳返回静止位置之前允许超出多少范围。当快速滑动产生的初始速度超过边界/min/max时可能会发生这种情况。数值越大,
overshootTolerance
允许补间在必要时超越最大/最小值的余地就越大。默认值为1
如果你不希望有任何超出,可以将其设为0
.
- snap: [函数 | 对象 | 数组] - 允许你定义规则,指定元素在释放后应该落脚在哪里。例如,你可能希望旋转总是停在90度的增量位置上,或者你希望
- [函数 | Boolean | 数组 | 对象]- 允许你定义一些规则,在拖动过程中 the element is being dragged (whereas regular snap affects only the end value(s), where the element lands after the drag is released). For example, maybe you want the rotation to snap to 10-degree increments while dragging or you want the x and y values to snap to a grid (whichever cell is closest). You can define the
liveSnap
in any of the following ways:查看更多详细信息
- 作为一个函数- 这个函数会接收到一个数值参数,即原始的(未修改的)值。该函数必须返回新的值(你可以在函数内部运行任意逻辑并返回对应的值)。例如,要使值对齐到最接近的50的倍数,你可以这样做:
liveSnap: function(value) { return Math.round(value / 50) * 50; }
. - 作为一个数组- 如果你使用一组数值,Draggable 会遍历数组并找到最接近的数字(只要它不在你定义的边界之外)。例如,从中选择最接近的10、50、200和450中的数值时,你可以这样做:
liveSnap: [10,50,200,450]
. - 作为一个对象- 如果你希望对每个属性使用不同的逻辑,比如如果
type
设置为"x,y"
并且你希望“x”部分贴靠到一组值,而“y”部分贴靠到另一组值,你可以使用一个具有对应属性的对象,例如:liveSnap: {x: [5,20,80,400], y: [10,60,80,500]}
。或者如果type
设置为"top,left"
并且你想为每个属性使用不同的函数,你可以这样做:liveSnap: {top: function(value) { return Math.round(value / 50) * 50; }, left: function(value) { return Math.round(value / 100) * 100; }}
。你可以在此对象内定义一个points
属性,将x和y组合在一起,比如liveSnap: {points:[{x: 0, y: 0}, {x: 100, y: 0}], radius: 20}
当该点在数组中距离在20像素(distance)以内时会自动贴靠到数组中的任意一点。或者你甚至可以使用基于函数的值来运行你自己的贴靠逻辑,例如:liveSnap: {points: function(point) { //run custom logic and return a new point }}
。有关示例,请参见本页的贴靠(snapping)部分。 - 作为布尔值(
true
)- 实时贴靠(live snapping)将使用为snap
定义的所有内容(这样不仅适用于最终值,也适用于拖拽过程中的实时应用)。
- 作为一个函数- 这个函数会接收到一个数值参数,即原始的(未修改的)值。该函数必须返回新的值(你可以在函数内部运行任意逻辑并返回对应的值)。例如,要使值对齐到最接近的50的倍数,你可以这样做:
- Boolean- 如果
true
,当在任一方向(水平或垂直)上拖动超过2像素时,将锁定移动到该轴向,因此在此次拖拽过程中元素只能沿该方向(水平或垂直,以初始移动最大的方向为准)拖动。不允许对角线移动。显然,这仅适用于类型为type
id 为"x,y"
,或者"top,left"
的可拖拽元素。如果你只允许垂直移动,应设置type
设置为"y"
或者"top"
。如果你只允许水平移动,应设置type
设置为"x"
或者"left"
. - 数字- 默认情况下,Draggable要求可拖拽元素必须移动超过2像素才会被解释为拖拽操作,但你可以使用
minimumMovement
。所以minimumMovement: 6
则要求可拖拽元素移动超过6像素才被视为拖拽操作。 - 函数- 当鼠标/触摸按下并释放时,在没有移动3个像素或更多的情况下调用的函数。这使得更容易判断用户的意图(点击或拖动)。在此函数中,
this
指向 Draggable 实例(除非你明确指定了使用callbackScope
设置的作用域),this.target
) 或者边界坐标 (this.maxX
,this.minX
,this.maxY
,以及this.minY
). 默认情况下,pointerEvent
(与 Draggable 相关的最后的鼠标或触摸事件)将作为唯一的参数传递给回调函数,这样你可以例如访问它的pageX
,pageY
,target
,currentTarget
,等等。 - 数组- 提供给
onClick
回调函数的可选参数数组。例如,onClickParams: ["clicked", 5]
可以与此代码一起使用:onClick: function(message, num) { console.log("message: " + message + ", num: " + num); }
. - 函数- 在每次拖拽期间鼠标(或触摸)移动时调用的函数。在这个函数中,
this
指向 Draggable 实例(除非你明确指定了使用callbackScope
设置的作用域),this.target
) 或者边界坐标 (this.maxX
,this.minX
,this.maxY
,以及this.minY
). 默认情况下,pointerEvent
(与 Draggable 相关的最后的鼠标或触摸事件)将作为唯一的参数传递给回调函数,这样你可以例如访问它的pageX
,pageY
,target
,currentTarget
等等。这个回调每requestAnimationFrame只调用一次。 - 数组- 提供给
onDrag
回调函数的可选参数数组。例如,onDragParams: ["dragged", 5]
可以与此代码一起使用:onDrag: function(message, num) { console.log("message: " + message + ", num: " + num); }
. - 函数- 一旦鼠标(或触摸)在拖拽后松开时立即调用的函数。即使没有任何移动,
onDragEnd
总是会被触发,而onClick
回调只有在鼠标/触摸移动小于3像素时才会触发。在这个函数中,this
指向 Draggable 实例(除非你明确指定了使用callbackScope
设置的作用域),this.target
) 或者边界坐标 (this.maxX
,this.minX
,this.maxY
,以及this.minY
). 默认情况下,pointerEvent
(最后一个与 Draggable 相关的鼠标或触摸事件)将作为唯一参数传递给回调,这样您可以例如访问pageX
,pageY
,target
,currentTarget
,等等。 - 数组- 提供给
onDragEnd
回调函数的可选参数数组。例如,onDragEndParams: ["drag ended", 5]
可以与此代码一起使用:onDragEnd: function(message, num) { console.log("message: " + message + ", num: " + num); }
. - 函数- 一旦鼠标(或触摸)移动超过2像素就调用的函数,意味着拖拽已经开始。在这个函数中,
this
指向 Draggable 实例(除非你明确指定了使用callbackScope
设置的作用域),this.target
) 或者边界坐标 (this.maxX
,this.minX
,this.maxY
,以及this.minY
). 默认情况下,pointerEvent
(最后一个与 Draggable 相关的鼠标或触摸事件)将作为唯一参数传递给回调,这样您可以例如访问pageX
,pageY
,target
,currentTarget
,等等。 - 数组- 提供给
onDragStart
回调函数的可选参数数组。例如,onDragStartParams: ["drag started", 5]
可以与此代码一起使用:onDragStart: function(message, num) { console.log("message: " + message + ", num: " + num); }
. - 函数- 一旦移动被锁定到水平或垂直轴时调用的函数。这种情况发生在
lockAxis
设置为true
并且用户拖动足够远的距离让Draggable判定锁定了哪个轴时。在启用了触摸的设备上,当你有一个仅允许沿一个轴拖动(如type: "x"
,type: "y"
,type: "left"
,或者type: "top"
)的Draggable,并且用户通过触摸进行拖动时,Draggable也会判断方向,从而决定是否允许原生触摸滚动还是由Draggable驱动的拖动。在函数内部,this
指向Draggable实例,便于访问锁定的轴向(this.lockedAxis
其值为"x"
或者"y"
),或目标元素(this.target
),等等。默认情况下,最新的与Draggable相关的鼠标或触摸事件(pointerEvent
(最后一个与 Draggable 相关的鼠标或触摸事件)将作为唯一参数传递给回调,这样您可以例如访问pageX
,pageY
,target
,currentTarget
,等等。 - 函数- 在每次拖拽期间鼠标(或触摸)移动时调用的函数。在这个函数中,
this
指向 Draggable 实例(除非你明确指定了使用callbackScope
设置的作用域),this.target
) 或者边界坐标 (this.maxX
,this.minX
,this.maxY
,以及this.minY
). 默认情况下,pointerEvent
(与 Draggable 相关的最后的鼠标或触摸事件)将作为唯一的参数传递给回调函数,这样你可以例如访问它的pageX
,pageY
,target
,currentTarget
等属性。这不同于onDrag
的是它可以在每个 requestAnimationFrame 中触发多次。一般来说,最好使用onDrag
,但如果由于某些原因你需要在拖动事件上执行操作,也可以使用这个选项。.stopPropogation
或者.stopImmediatePropogation
在拖动事件上的操作。 - 函数- 当鼠标(或触摸)按下元素时应调用的一个函数。在这个函数中,
this
指向 Draggable 实例(除非你明确指定了使用callbackScope
设置的作用域),this.target
) 或者边界坐标 (this.maxX
,this.minX
,this.maxY
,以及this.minY
). 默认情况下,pointerEvent
(最后一个与 Draggable 相关的鼠标或触摸事件)将作为唯一参数传递给回调,这样您可以例如访问pageX
,pageY
,target
,currentTarget
,等等。 - 数组- 提供给
onPress
回调函数的可选参数数组。例如,onPressParams: ["drag started", 5]
可以与此代码一起使用:onPress: function(message, num) { console.log("message: " + message + ", num: " + num); }
. - 函数- 不论是否实际拖动了内容,在目标元素上按下的鼠标(或触摸)释放后立即调用该函数。在此函数内,
this
指向 Draggable 实例(除非你明确指定了使用callbackScope
设置的作用域),this.target
) 或者边界坐标 (this.maxX
,this.minX
,this.maxY
,以及this.minY
). 默认情况下,pointerEvent
(最后一个与 Draggable 相关的鼠标或触摸事件)将作为唯一参数传递给回调,这样您可以例如访问pageX
,pageY
,target
,currentTarget
,等等。 - 数组- 提供给
onRelease
回调函数的可选参数数组。例如,onReleaseParams: ["drag ended", 5]
可以与此代码一起使用:onRelease: function(message, num) { console.log("message: " + message + ", num: " + num); }
. - [元素 | 字符串 | 对象]- 如果你只想让某个特定区域(如窗口的顶部栏)触发拖动,而不是整个元素,你可以定义一个子元素作为触发器,比如
trigger: yourElement
,trigger: "#topBar"
,或者trigger: $("#yourID")
。你可以将触发器定义为一个元素或者选择器字符串。 - 字符串- 表示拖动类型(拖动应该影响的属性)。以下任意一个都可以使用:[
"x,y"
(基本上是 transform 的translateX
和translateY
属性) |"left,top"
|"rotation"
|"x"
|"y"
|"top"
|"left"
]。默认值是"x,y"
. - Boolean- 默认情况下,对于垂直或水平拖动,当一个元素被按下/触摸时,它的
zIndex
被设置为一个较高的值(默认值为1000
),并且每当新的元素被按下/触摸时,这个数值会递增并应用到新元素上,以确保堆叠顺序看起来正确(新按下的对象上升到最上层),如果你希望跳过此行为,则设置zIndexBoost: false
.
属性
描述
请注意,如果你要将 Draggable 应用于动态创建的元素,应在调用 Draggable.create() 之前先将该元素添加到 DOM 中。