Apply interactive drag and resize functionality

by jude_pinto

HTML

<!-- Example HTML structure -->
<div class="circle" data-x="0" data-y="0" style="transform: translate(0px, 0px);"></div>
<div class="circle" data-x="100" data-y="100" style="transform: translate(100px, 100px);"></div>
<button id="reset">Reset</button>

CSS

.circle {
  width: 100px;
  height: 100px;
  background-color: #cc69a5;
  border-radius: 50%;
  position: absolute;
  touch-action: none; /* required for interact.js to work on touch devices */
  user-select: none;
  cursor: move;
}

JavaScript

// Sexual Ecologies Diagram Sample Code (Refactored)
// By: Jude Pinto

// This code is a refactored version of an interactive survey for Aki Gormezano's study on Sexual Ecologies,
// using the interact.js library by Taye (https://interactjs.io/)

// Instructions: Drag and resize any circle using mouse or touch. Press "Reset" to return to original positions.

(function () {
  const circles = document.querySelectorAll('.circle');

  // Apply transform to element and update data attributes
  function applyTransform(el, x, y) {
    el.style.transform = `translate(${x}px, ${y}px)`;
    el.dataset.x = x;
    el.dataset.y = y;
  }

  // Store initial positions in data attributes
  circles.forEach(circle => {
    const rect = circle.getBoundingClientRect();
    const initialX = parseFloat(circle.dataset.x) || 0;
    const initialY = parseFloat(circle.dataset.y) || 0;

    circle.dataset.initialX = initialX;
    circle.dataset.initialY = initialY;
    applyTransform(circle, initialX, initialY);
  });

  // Dragging behavior
  interact('.circle').draggable({
    listeners: {
      move(event) {
        const target = event.target;
        const dx = event.dx;
        const dy = event.dy;

        const x = (parseFloat(target.dataset.x) || 0) + dx;
        const y = (parseFloat(target.dataset.y) || 0) + dy;

        applyTransform(target, x, y);
      }
    }
  });

  // Optional: Resizing behavior (if needed)
  interact('.circle').resizable({
    edges: { left: true, right: true, bottom: true, top: true },
    listeners: {
      move(event) {
        const target = event.target;

        let { width, height } = event.rect;
        target.style.width = `${width}px`;
        target.style.height = `${height}px`;

        const x = (parseFloat(target.dataset.x) || 0) + event.deltaRect.left;
        const y = (parseFloat(target.dataset.y) || 0) + event.deltaRect.top;

        applyTransform(target, x, y);
      }
   ...