interact js with guide line
Asked Answered
W

2

5

enter image description here

Interact.js has a snap option to snapping element. But I don't know how to show those guide lines. I was thinking about there might be some events trggered when snapping happened, and I might use them to show those lines, but I didn't find them in the documentation.

Widow answered 1/7, 2015 at 7:29 Comment(0)
P
5

interact doesn't support those guidelines out of the box, but you can build them relatively easy for yourself.

I built this fiddle to show the process.

The important part is this:

interact(element)
    .draggable({
        snap: {
            targets: [
                function (x, y) {
                    var newX = Math.round(x / 50) * 50;
                    var newY = Math.round(y / 50) * 50;
                    someFunction(newX, newY);
                    return {
                        x: newX,
                        y: newY
                    };
            }],

As you can see, you can build the function that determines the snapping position (newX and newY) in regard to your current mouse position. In this function you can also call another function. In this case I called a function to show one line if the object is at this position. Here you can get creative. You could set the position of one line Element to the current position, you could set some predefined lines and calculate which is the closest to only show that one, this depends on you business problem.

For more information about interact - snapping, look in here in the docs

Palm answered 7/7, 2015 at 16:47 Comment(0)
L
2

might be a bit late but it still can be useful for those who struggle with alignment. Here is my complete approach:

Codepen: https://codepen.io/lakers19/pen/ZEoPpKL

const targets = []

const cleanXLine = () => {
  const guideLineX = document.querySelector('.guide-line-x')
  guideLineX.style.left = 0
  guideLineX.style.top = 0
  guideLineX.style.width = 0
  guideLineX.style.height = 0
}

const cleanYLine = () => {
  const guideLineY = document.querySelector('.guide-line-y')
  guideLineY.style.left = 0
  guideLineY.style.top = 0
  guideLineY.style.width = 0
  guideLineY.style.height = 0
}

const resetGuideLine = () => {
  cleanXLine()
  cleanYLine()
}

const handleStart = (event) => {
  // get all interactive elements
  targets.length = 0

  const elements = document.querySelectorAll('.draggable')

  elements.forEach((element) => {
    const rect = element.getBoundingClientRect()
    const { x, y, width, height } = rect

    if (element === event.target) return

    const actualX = x + window.scrollX
    const actualY = y + window.scrollY

    const range = 4

    targets.push({
      x: actualX,
      range,
      rect,
      element,
    })

    targets.push({
      x: actualX + width,
      range,
      rect,
      element,
    })

    targets.push({
      x: actualX + width / 2,
      range,
      rect,
      element,
    })

    targets.push({
      y: actualY,
      range,
      rect,
      element,
    })

    targets.push({
      y: actualY + height,
      range,
      rect,
      element,
    })

    targets.push({
      y: actualY + height / 2,
      range,
      rect,
      element,
    })
  })
}

const drawGuideLine = (event) => {
  const inRange = event.modifiers.length ? event.modifiers[0]?.inRange : false

  if (inRange) {
    const guideLineX = document.querySelector('.guide-line-x')
    const guideLineY = document.querySelector('.guide-line-y')
    const {
      x: xModifier,
      y: yModifier,
      rect,
    } = event.modifiers[0].target.source

    const { x, y } = event.target.getBoundingClientRect()

    if (xModifier) {
      guideLineX.style.left = `${xModifier}px`
      guideLineX.style.top = `${Math.min(rect.y, y)}px`
      guideLineX.style.width = '1px'
      guideLineX.style.height = `${Math.abs(rect.y - y)}px`
      cleanYLine()
    }
    if (yModifier) {
      console.log(rect.x - x)
      guideLineY.style.left = `${Math.min(rect.x, x)}px`
      guideLineY.style.top = `${yModifier - window.scrollY}px`
      guideLineY.style.width = `${Math.abs(rect.x - x)}px`
      guideLineY.style.height = '1px'
      cleanXLine()
    }
  } else {
    resetGuideLine()
  }
}


interact('.draggable')
  .draggable({
    // enable inertial throwing
    inertia: false,
    // keep the element within the area of it's parent
    modifiers: [interact.modifiers.snap({
          targets: targets,
          relativePoints: [
            { x: 0, y: 0 }, // snap relative to the element's top-left,
            { x: 0.5, y: 0.5 }, // to the center
            { x: 1, y: 1 }, // and to the bottom-right
          ],
        }),
      interact.modifiers.restrictRect({
        restriction: 'parent',
        endOnly: true
      })
    ],
    // enable autoScroll
    autoScroll: true,

    listeners: {
      // call this function on every dragmove event
      move: dragMoveListener,
      start: handleStart,

      // call this function on every dragend event
      end (event) {
        resetGuideLine()
      }
    }
  })

function dragMoveListener (event) {
  drawGuideLine(event)
  var target = event.target
  // keep the dragged position in the data-x/data-y attributes
  var x = (parseFloat(target.getAttribute('data-x')) || 0) + event.dx
  var y = (parseFloat(target.getAttribute('data-y')) || 0) + event.dy

  // translate the element
  target.style.transform = 'translate(' + x + 'px, ' + y + 'px)'

  // update the posiion attributes
  target.setAttribute('data-x', x)
  target.setAttribute('data-y', y)
}

// this function is used later in the resizing and gesture demos
window.dragMoveListener = dragMoveListener
#canvas{
  width: 100vw;
  height: 100vh;
  background:  rgb(22, 197, 180);
}

.draggable {
  background: rgb(71, 44, 113);
  width: 60px;
  height: 60px;
}

.draggable:nth-child(1){
  translate: 20px 10px; 
}

.draggable:nth-child(2){
   translate: 50px 60px; 
}

body {
  display: grid;
  place-items: center;
  place-content: center;
  height: 100%;
}

html{
  height: 100%;
}

.guide-line {
  pointer-events:none;
  background:red;
  position:fixed;
  display: flex;
  justify-items:space-between;
  width: 0;
  height:0;
  left:0;
  right:0;
  }

  .guide-line > span {
    font-size: 9px;
    line-height: 0;
    color: red;
    position: absolute;
  }

  .guide-line-x > span {
    transform: translateX(-50%);
    left: 50%;
  }

.guide-line-y{
  flex-direction:row;
}

.guide-line-x {
  flex-direction:column;
}

  .guide-line-y > span{
    transform: translateY(-50%);
    top: 50%;
  }
<script src="https://cdnjs.cloudflare.com/ajax/libs/interact.js/1.10.17/interact.min.js"></script>
  <div id="canvas">
    <div class="draggable" ></div>
    <div class="draggable"> </div>
    <div  class="guide-line-y guide-line">
            <span style="opacity:0" >x</span>
            <span>x</span>
          </div>
          <div class="guide-line-x guide-line">
            <span style="opacity:0">x</span>
            <span>x</span>
          </div>
  </div>
Ladybird answered 14/10, 2022 at 18:53 Comment(1)
Looks like this is the same as the one in this question.Tuberosity

© 2022 - 2024 — McMap. All rights reserved.