[Preview Live] How to Create Draggable, Resizable, Scalable, Rotatable, Warpable Element

moveable-Preview-Live

Moveable is an npm package that makes your components withdrawable. Movable is a JavaScript library that makes an element draggable, resizable, scalable, scrollable, rotatable, roundtable, clippable, and wrappable.

ngx resizable moveable, svelte resizable div, drag resize js, vue draggable resizable, js draggable scale

How to make use of it:

Install and import the moveable.

# NPM
$ npm install moveable --save
import Moveable from "moveable";

Or load the umd version from the dist folder.

<script src="/dist/moveable.min.js"></script>
<-- or from a cdn -->
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/moveable.min.js"></script>

Initialize the Moveable library and specify the target component.

const moveable = new Moveable(document.body, {
      target: document.querySelector(".target"),
      container: null,
      rootContainer: null,
      rotatable: false,
      rotationPosition: "top",
      roundable: true,
      roundRelative: false,
      draggable: false,
      dragTarget: target,
      scalable: false,
      resizable: false,
      warpable: false,
      pinchable: true, // ["resizable", "scalable", "rotatable"]
      pinchThreshold: 0,
      pinchOutside: true,
      clippable: true,
      defaultClipPath: "inset",
      customClipPath: "",
      clipRelative: false,
      clipArea: false,
      dragWithClip: true,
      triggerAblesSimultaneously: false,
      snappable: true,
      snapElement: true,
      snapThreshold: 5,
      snapVertical: true,
      snapHorizontal: true,
      snapCenter: false,
      snapDigit: 0,
      snapGap: true,
      snapDistFormat: self,
      isDisplaySnapDigit: true,
      originDraggable: true,
      scrollable: true,
      scrollContainer: document.body,
      scrollThreshold: 0,
      getScrollPosition: ({ scrollContainer }) => ([scrollContainer.scrollLeft, scrollContainer.scrollTop]),
      bounds: { left: 0, top: 0, bottom: 1000, right: 1000 },
      innerBounds: null,
      innerBound: null,
      verticalGuidelines: [100, 200, 300],
      horizontalGuidelines: [0, 100, 200],
      elementGuidelines: [document.querySelector(".element")],
      keepRatio: true,
      origin: true,
      padding: null,
      zoom: 1,
      dragArea: false,
      edge: false, // resize, scale events at edges
      clipVerticalGuidelines: [0, 100, 200],
      clipHorizontalGuidelines: [0, 100, 200],
      clipSnapThreshold: 5,
      clipTargetBounds: true,
      throttleDrag: 0,
      throttleResize: 0,
      throttleScale: 0,
      throttleRotate: 0,
      throttleDragRotate: 0,
      renderDirections: ["n", "nw", "ne", "s", "se", "sw", "e", "w"],
      className: "",
      defaultGroupRotate: 0 // Sets the initial rotation of the group
});

Callback features.

const moveable = new Moveable(document.body, {
    OnDrag: function () {},
    OnDragEnd: function () {},
    OnDragGroup: function () {},
    OnDragGroupEnd: function () {},
    OnDragGroupStart: function () {},
    OnDragStart: function () {},
    OnPinch: function () {},
    OnPinchEnd: function () {},
    OnPinchGroup: function () {},
    OnPinchGroupEnd: function () {},
    OnPinchGroupStart: function () {},
    OnPinchStart: function () {},
    OnResize: function () {},
    OnResizeEnd: function () {},
    OnResizeGroup: function () {},
    OnResizeGroupEnd: function () {},
    OnResizeGroupStart: function () {},
    OnResizeStart: function () {},
    OnRotate: function () {},
    OnRotateEnd: function () {},
    OnRotateGroup: function () {},
    OnRotateGroupEnd: function () {},
    OnRotateGroupStart: function () {},: function () {},
    OnRotateStart: function () {},
    OnScale: function () {},
    OnScaleEnd: function () {},
    OnScaleGroup: function () {},
    OnScaleGroupEnd: function () {},
    OnScaleGroupStart: function () {},
    OnScaleStart: function () {},
    OnWarp: function () {},
    OnWarpEnd: function () {},
    OnWarpStart: function () {},
    OnRenderStart: function () {},
    OnRender: function () {},
    OnRenderEnd: function () {},
    OnRenderGroupStart: function () {},
    OnRenderGroup: function () {},
    OnRenderGroupEnd: function () {},
});

Event handlers.

moveable.on("click", ({ hasTarget, containsTarget, targetIndex }) => {
  // If you click on an element other than the target and not included in the target, index is -1.
  console.log("onClickGroup", target, hasTarget, containsTarget, targetIndex);
});

moveable.on("clickGroup", ({ inputTarget, isTarget, containsTarget, targetIndex }) => {
  // If you click on an element other than the target and not included in the target, index is -1.
  console.log("onClickGroup", inputTarget, isTarget, containsTarget, targetIndex);
});

moveable.on("drag", ({ target, transform }) => {
  target.style.transform = transform;
});

moveable.on("dragEnd", ({ target, isDrag }) => {
  console.log(target, isDrag);
});

moveable.on("dragGroup", ({ targets, events }) => {
  console.log("onDragGroup", targets);
  events.forEach(ev => {
       // drag event
       console.log("onDrag left, top", ev.left, ev.top);
       // ev.target!.style.left = `${ev.left}px`;
       // ev.target!.style.top = `${ev.top}px`;
       console.log("onDrag translate", ev.dist);
       ev.target!.style.transform = ev.transform;)
  });
});

moveable.on("dragGroupEnd", ({ targets, isDrag }) => {
  console.log("onDragGroupEnd", targets, isDrag);
});

moveable.on("dragGroupStart", ({ targets }) => {
  console.log("onDragGroupStart", targets);
});

moveable.on("dragStart", ({ target }) => {
  console.log(target);
});

moveable.on("pinch", ({ target }) => {
  console.log(target);
});

moveable.on("pinchEnd", ({ target }) => {
  console.log(target);
});

moveable.on("pinchGroup", ({ targets, events }) => {
  console.log("onPinchGroup", targets);
});

moveable.on("pinchGroupEnd", ({ targets, isDrag }) => {
  console.log("onPinchGroupEnd", targets, isDrag);
});

moveable.on("pinchGroupStart", ({ targets }) => {
  console.log("onPinchGroupStart", targets);
});

moveable.on("pinchStart", ({ target }) => {
  console.log(target);
});

moveable.on("rotate", ({ target }) => {
  console.log(target);
});

moveable.on("scroll", ({ scrollContainer, direction }) => {
  scrollContainer.scrollLeft += direction[0] * 10;
  scrollContainer.scrollTop += direction[1] * 10;
})

moveable.on("scrollGroup", ({ scrollContainer, direction }) => {
  scrollContainer.scrollLeft += direction[0] * 10;
  scrollContainer.scrollTop += direction[1] * 10;
});

moveable.on("scale", ({ target }) => {
  console.log(target);
});

moveable.on("pinchEnd", ({ target }) => {
  console.log(target);
});

moveable.on("rotateEnd", ({ target }) => {
  console.log(target);
});

moveable.on("scaleEnd", ({ target }) => {
  console.log(target);
});

moveable.on("pinchGroup", ({ targets, events }) => {
  console.log("onPinchGroup", targets);
});

moveable.on("pinchGroupEnd", ({ targets, isDrag }) => {
  console.log("onPinchGroupEnd", targets, isDrag);
});

moveable.on("pinchGroupStart", ({ targets }) => {
  console.log("onPinchGroupStart", targets);
});

moveable.on("pinchStart", ({ target }) => {
  console.log(target);
});

moveable.on("render", ({ target }) => {
  console.log("onRender", target);
});

moveable.on("renderEnd", ({ target }) => {
  console.log("onRenderEnd", target);
});

moveable.on("renderGroup", ({ targets }) => {
  console.log("onRenderGroup", targets);
});

moveable.on("renderGroupEnd", ({ targets }) => {
  console.log("onRenderGroupEnd", targets);
});

moveable.on("renderGroupStart", ({ targets }) => {
  console.log("onRenderGroupStart", targets);
});

moveable.on("renderStart", ({ target }) => {
  console.log("onRenderStart", target);
});

moveable.on("resize", ({ target, width, height }) => {
  target.style.width = `${e.width}px`;
  target.style.height = `${e.height}px`;
});

moveable.on("resizeEnd", ({ target, isDrag }) => {
  console.log(target, isDrag);
});

moveable.on("resizeGroup", ({ targets, events }) => {
  console.log("onResizeGroup", targets);
  events.forEach(ev => {
      const offset = [
          direction[0] < 0 ? -ev.delta[0] : 0,
          direction[1] < 0 ? -ev.delta[1] : 0, ]; // ev.drag is a drag event that occurs when the group resize. const left = offset[0] + ev.drag.beforeDist[0]; const top = offset[1] + ev.drag.beforeDist[1]; const width = ev.width; const top = ev.top; }); }); moveable.on("resizeGroupEnd", ({ targets, isDrag }) => {
  console.log("onResizeGroupEnd", targets, isDrag);
});

moveable.on("resizeGroupEnd", ({ targets, isDrag }) => {
  console.log("onResizeGroupEnd", targets, isDrag);
});

moveable.on("resizeGroupStart", ({ targets }) => {
  console.log("onResizeGroupStart", targets);
});

moveable.on("resizeStart", ({ target }) => {
  console.log(target);
});

moveable.on("rotate", ({ target, transform, dist }) => {
  target.style.transform = transform;
});

moveable.on("rotateEnd", ({ target, isDrag }) => {
  console.log(target, isDrag);
});

moveable.on("rotateGroup", ({ targets, events }) => {
  console.log("onRotateGroup", targets);
  events.forEach(ev => {
      const target = ev.target;
      // ev.drag is a drag event that occurs when the group rotate.
      const left = ev.drag.beforeDist[0];
      const top = ev.drag.beforeDist[1];
      const deg = ev.beforeDist;
  });
});

moveable.on("rotateGroupEnd", ({ targets, isDrag }) => {
  console.log("onRotateGroupEnd", targets, isDrag);
});

moveable.on("rotateGroupStart", ({ targets }) => {
  console.log("onRotateGroupStart", targets);
});

moveable.on("rotateStart", ({ target }) => {
  console.log(target);
});

moveable.on("rotateStart", ({ target }) => {
  console.log(target);
});

moveable.on("scale", ({ target, transform, dist }) => {
  target.style.transform = transform;
});

moveable.on("scaleEnd", ({ target, isDrag }) => {
  console.log(target, isDrag);
});

moveable.on("scaleGroup", ({ targets, events }) => {
  console.log("onScaleGroup", targets);
  events.forEach(ev => {
      const target = ev.target;
      // ev.drag is a drag event that occurs when the group scale.
      const left = ev.drag.beforeDist[0];
      const top = ev.drag.beforeDist[0];
      const scaleX = ev.scale[0];
      const scaleX = ev.scale[1];
  });
});

moveable.on("scaleGroupEnd", ({ targets, isDrag }) => {
  console.log("onScaleGroupEnd", targets, isDrag);
});

moveable.on("scaleGroupStart", ({ targets }) => {
  console.log("onScaleGroupStart", targets);
});

moveable.on("scaleStart", ({ target }) => {
  console.log(target);
});

moveable.on("scroll", ({ scrollContainer, direction }) => {
  scrollContainer.scrollLeft += direction[0] * 10;
  scrollContainer.scrollTop += direction[1] * 10;
});

moveable.on("snap", e => {
  console.log("onSnap", e);
});

moveable.on("warp", ({ target, transform, delta, multiply }) => {
 // target.style.transform = transform;
 matrix = multiply(matrix, delta);
 target.style.transform = `matrix3d(${matrix.join(",")})`;
});

moveable.on("warpEnd", ({ target, isDrag }) => {
  console.log(target, isDrag);
});

moveable.on("warpStart", ({ target }) => {
  console.log(target);
});

API strategies.

// destroy
moveable.destroy();

// check if is dragging
moveable.isDragging();

// check if is moveable element
moveable.isMoveableElement(e.target);

// check whether an event has been attached to a component.
moveable.hasOn(eventName);

// indicate whether the event is attached. 
moveable.hitTest(el);

// indicate whether the event is attached. 
moveable.hitTest(el);

// update the shape of the moveable
moveable.updateRect();

// change options or properties
moveable.setState(state, callbackopt);

// triggers a custom event
moveable.trigger(eventName, customEventopt, ...restParam);

// Instantly Request (requestStart - request - requestEnd)
moveable.request("draggable", { deltaX: 10, deltaY: 10, isInstant: true });

// Start move
const requester = moveable.request("draggable");
requester.request({ deltaX: 10, deltaY: 10 });
requester.request({ deltaX: 10, deltaY: 10 });
requester.request({ deltaX: 10, deltaY: 10 });
requester.requestEnd();

// update
moveable.updateTarget();

// trigger an event
moveable.on(event);

// executs event just one time
moveable.once(event);

// unbind an event
moveable.off(event);

moveablejs, moveable Plugin/Github


See Demo And Download

Official Website(daybrush): Click Here

This superior jQuery/javascript plugin is developed by daybrush. For extra Advanced usage, please go to the official website.