Simple dragging logic library for Laminar. Library is based on handling and wrapping pointer events fired while dragging. It doesn't depend on HTML draggable attribute.
See demo and examples source.
For Laminar v16.0.0:
libraryDependencies += "dev.bluepitaya" %%% "laminar-dragging" % "1.1"
def component() = {
val draggingModule: Dragging.DraggingModule[String] = Dragging
.createModule[String]()
val eventKindLabel = Var[String]("Drag the square!")
div(
// bindings for document events, put them in "parent" of dragging elements
draggingModule.documentBindings,
div(
// binding function for dragging elements
draggingModule.componentBindings("someObj"),
// event stream of dragging events
draggingModule.componentEvents("someObj") -->
Observer[Dragging.Event] { event =>
event match {
// e is dom.PointerEvent
case Dragging.Event(e, DragEventKind.Start) => eventKindLabel
.set("START")
case Dragging.Event(e, DragEventKind.Move) => eventKindLabel
.set("MOVE")
case Dragging.Event(e, DragEventKind.End) => eventKindLabel
.set("END")
}
},
// just some styles
Seq(width("100px"), height("100px"), backgroundColor("green"))
),
p(child.text <-- eventKindLabel),
// current dragging id
p(child.text <-- draggingModule.currentDraggingIdSignal.map(_.toString()))
)
}
Function Dragging.createModule[A]()
creates Laminar event handlers under the hood and return module defined below. Type parameter A is type of unique id for each dragging component.
/** Dragging toolbox.
*
* @param documentBindings
* Pointer event bindings for document.
* @param componentBindings
* Function for creating pointer event bindings in dragging element.
* @param componentEvents
* Function for creating event stream of draggin events.
* @param currentDraggingIdSignal
* Signal of current dragging id.
*/
case class DraggingModule[A](
documentBindings: Seq[Binder.Base],
componentBindings: A => Seq[Binder.Base],
componentEvents: A => EventStream[Event],
currentDraggingIdSignal: Signal[Option[A]]
)
def getRelativePosition(e: Event, container: dom.Element): Vec2f
- Get dragging position relative to other element. See RelativeExample.scala
for use case.
def withDeltaPosition(componentEvents: EventStream[Event]): EventStream[(Event, Vec2f)]
- Append dragging position relative to start dragging position. See DeltaExample.scala
and DeltaExample2.scala
for use cases.
To run example page you need to:
- Run
sbt
->project example
->~fastLinkJS
- Execute
yarn
(only once to install JS deps) ->yarn dev
inexample/ui
dir.