Drag/resize/rotate

Touch-enabled dragging, resizing, rotating

by 20yco

HTML

<script src="https://rawgit.com/nichollascarter/js-drag-resize-rotate-tool/master/dist/js/subjx.js"></script>
<link rel="stylesheet" href="https://rawgit.com/nichollascarter/js-drag-resize-rotate-tool/master/dist/style/subjx.css">
<div style="width:100%; height:100%;">
  <div style="position: absolute; display: inline; box-sizing: border-box; color: black">
    Double click on element to activate/deactivate

    <div id="move">
      Move:
      <span></span>
    </div>
    <div id="resize">
      Resize:
      <span></span>
    </div>
    <div id="rotate">
      Rotate:
      <span></span>
    </div>
  </div>

  <svg id="svg-container" width="100%" height="50%" transform="scale(1, 1)">

    <rect class="drag-svg" x="552" y="209" width="30" height="30" stroke="black" fill="transparent" stroke-width="5" transform="rotate(0 567 224)"></rect>
    <rect class="drag-svg" x="469" y="211" rx="10" ry="10" width="30" height="30" stroke="black" fill="transparent" stroke-width="5" transform="rotate(0 484 226)"></rect>

    <circle cx="792" cy="152" r="20" stroke="red" fill="transparent" stroke-width="5" transform="rotate(0 792 152)"></circle>
    <ellipse class="drag-svg" cx="358" cy="222" rx="22.000000000000004" ry="17" stroke="red" fill="transparent" stroke-width="5" transform="rotate(0 358 222)"></ellipse>

    <line class="drag-svg" x1="626" x2="666" y1="200" y2="240" stroke="orange" fill="transparent" stroke-width="5" transform="rotate(0 646 220)"></line>
    <polyline class="drag-svg" points="599 73 604 83 609 78 614 93 619 88 624 103 629 98 634 113 639 108" stroke="orange" fill="transparent" stroke-width="5" transform="rotate(0 619 93)"></polyline>

    <polygon class="drag-svg" points="356 71 361 91 376 91 366 101 371 116 356 106 341 116 346 101 336 91 351 91" stroke="green" fill="transparent" stroke-width="5" transform="rotate(0 356 93.5)"></polygon>

    <path class="drag-svg" d="M451,91 Q471,66,481,91 T521,91 " fill="none" stroke="blue" stroke-width="5"...

CSS

html,
body {
  margin: 0;
  padding: 0;
  height: 100%;
}

.draggable {
  position: absolute;
  width: 150px;
  height: 50px;
  background-color: yellow;
}

.clonable {
  position: absolute;
  width: 50px;
  height: 50px;
  left: 0;
}

JavaScript

// define methods
const methods = {
  onInit(el) {
    console.log('init');
  },
  onMove(dx, dy) {
    subjx('#move > span')[0].innerHTML = `x: ${dx}px; y: ${dy}px`;
  },
  onResize(dx, dy) {
    subjx('#resize > span')[0].innerHTML = `x: ${dx}px; y: ${dy}px`;
  },
  onRotate(rad) {
    subjx('#rotate > span')[0].innerHTML = `${Math.floor(rad * 180 / Math.PI)}deg`;
  },
  onDrop(e, el) {
    console.log('is dropped');
  },
  onDestroy(el) {
    console.log('is destroyed');
  }
};
// additional options
const svgOptions = {
  container: '#svg-container',
  restrict: '#svg-container',
  rotationPoint: true,
  snap: {
    x: 30,
    y: 30,
    angle: 25
  },
  ...methods
};

const svgs =
  subjx('.drag-svg').drag(svgOptions);

svgs.forEach(item => {
  subjx(item.controls).on('dblclick', () => {
    item.disable();
  });
});

// double click activating/deactivating the drag method
subjx('.drag-svg').on('dblclick', e => {
  if (e.currentTarget.classList.contains('sjx-drag')) return;
  const xDraggable = subjx(e.currentTarget).drag(svgOptions)[0];
  // adding event to controls
  const controls = xDraggable.controls;
  subjx(controls).on('dblclick', () => {
    xDraggable.disable();
  });
});

const options = {
  container: '#stack',
  restrict: '#stack',
  //rotationPoint: true,
  proportions: true,
  each: {
    move: true,
    resize: true
  },
  snap: {
    x: 40,
    y: 40,
    angle: 0
  },
  cursorMove: 'move',
  cursorRotate: 'crosshair',
  cursorResize: 'pointer',
  ...methods
};

const Draggables = subjx('.draggable').drag(options);

Draggables.forEach(item => {
  const controls = item.controls;
  subjx(controls).on('dblclick', () => {
    item.disable();
    Draggables.splice(Draggables.indexOf(item), 1);
  });
});

subjx('.draggable').on('dblclick', e => {
  if (e.currentTarget.classList.contains('sjx-drag')) return;
  const xDraggable = subjx(e.currentTarget).drag(options)[0];
  Draggables.push(xDraggable);
  // adding event to controls
  const controls =...