UNPKG

joicomponents

Version:

Design patterns to build native web components

120 lines (96 loc) 4.98 kB
# Mixin: `DraggingFling` `DraggingFling` adds support for one-finger gesture for dragging on the screen, commonly used to move and/or scroll elements on the screen. A `fling` callback/event is triggered if the finger is removed from the screen while in motion, the dragging ends abruptly. See also `spin` in [PinchSpin](Mixin3_PinchSpinGesture.md). `DraggingFling` records a sequence of one-finger events (cf. [EventRecording](../../chapter2_HowToMakeMixins/Pattern4_EventRecording.md)): * `touchstart`/`mousedown`, * `touchmove`/`mousemove`, * `touchend`/`mouseup`, and * `touchcancel`. And turns them into a series of *optional* callbacks (cf. [OptionalCallbacksEvents](../../chapter2_HowToMakeMixins/Pattern6_OptionalCallbacksEvents.md)): * `draggingstartCallback()`, * `draggingCallback()`, * `draggingendCallback()`, * `draggingcancelCallback()`, * and `flingCallback()`. The `draggingstart`, `dragging`, `draggingend` timeline correspond to `touchstart`, `touchmove`, and `touchend/touchcancel`. ## Implementation details The `DraggingFling` is built using the [EventRecording](../../chapter2_HowToMakeMixins/Pattern4_EventRecording.md) and [FunctionalMixin](../../chapter2_HowToMakeMixins/Pattern2_FunctionalMixin.md) patterns. The `DraggingFling` mixin only reacts when *one* finger/mousebutton is used. If only an additional finger or mousebutton is pressed, the event recording is cancelled. `fling` is triggered when the finger or mouse have moved more than a minimum `flingDistance`(px) for more than minimum `flingDuration`(ms). Both `flingDistance` and `flingDuration` are implemented as [StaticSettings](../../chapter2_HowToMakeMixins/Pattern3_StaticSettings.md). The default value of `flingDistance` is `50`(px), and the default value of `flingDuration` is `200`(ms). `flingDistance` is calculated as the distance from the start and end position of the finger/mouse, where the start position was the position of the finger/mouse at pinchend - `spinDuration`. `DraggingFling` has the following *OptionalCallbacks* methods: - `draggingstartCallback({event, x, y})` - `draggingCallback({event, x, y, distX, distY, distDiag, durationMs})` - `draggingendCallback({event, x, y})` - `draggingcancelCallback({event})` - `flingCallback({event, x, y, distX, distY, distDiag, durationMs})` `DraggingFling` has the following StaticSetting for an *OptionalEvent*: - draggingEvent: true => mixin will also dispatch the following events - draggingstart: {event, x, y} - dragging: {event, x, y, distX, distY, distDiag, durationMs} - draggingend: {event, x, y} - fling: {event, x, y, distX, distY, distDiag, durationMs} The *OptionalCallback* methods' names and argument correspond exactly to the *OptionalEvent* name and detail. `DraggingFling` implement an extensive [InvadeAndRetreat!](../gestures/Pattern4_InvadeAndRetreat.md) strategy to block default actions in the browsers such as "drag-to-scroll". `DraggingFling` does not use pointerevents. It could have. But it doesn't in order to avoid to polyfill pointerevents in Safari. ## Example: DraggingBlock ```html <style> dragging-block { display: block; position: fixed; top: 100px; left: 100px; width: 50px; height: 50px; background: orange; } </style> <dragging-block></dragging-block> <script type="module"> import {DraggingFling} from "https://rawgit.com/orstavik/JoiComponents/master/src/gestures/DraggingFling.js"; class DraggingBlock extends DraggingFling(HTMLElement) { //[1] static get draggingEvent(){ return true; } draggingCallback(detail){ this.innerText = "x: " + detail.distX + ", y: " + detail.distY; //[3] } } customElements.define("dragging-block", DraggingBlock); const block = document.querySelector("dragging-block"); block.addEventListener("dragging", (e) => { block.style.left = (parseFloat(block.style.left) + e.detail.distX) + "px"; //[3] block.style.top = (parseFloat(block.style.top) + e.detail.distY) + "px"; //[3] }); </script> ``` todo add and writeup the numbers in the example. 1. Adding the functional mixin `DraggingFling(HTMLElement)`. DraggingBlock elements will now dispatch dragging events when dragged. 2. Adds the listener for `dragging` event when the element connects to the DOM. Removes the listener for `dragging` event when the element disconnects. 3. Moves the element using `e.detail.distX` and `e.detail.distY` from the `dragging` event. Test it out on [codepen](https://codepen.io/orstavik/pen/XEwPaE). ## References * [Lauke: getting touchy presentation](https://www.youtube.com/watch?v=jSL-RluQhMs) * [Lauke: getting touchy on github](https://github.com/patrickhlauke/getting-touchy-presentation) * https://developer.mozilla.org/en-US/docs/Web/API/Pointer_events * https://github.com/jquery/PEP