admin管理员组

文章数量:1022712

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.

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.

Share Improve this question asked Jul 1, 2015 at 7:29 ChefChef 6837 silver badges17 bronze badges
Add a ment  | 

2 Answers 2

Reset to default 5 +50

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

might be a bit late but it still can be useful for those who struggle with alignment. Here is my plete 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./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>

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.

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.

Share Improve this question asked Jul 1, 2015 at 7:29 ChefChef 6837 silver badges17 bronze badges
Add a ment  | 

2 Answers 2

Reset to default 5 +50

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

might be a bit late but it still can be useful for those who struggle with alignment. Here is my plete 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./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>

本文标签: javascriptinteract js with guide lineStack Overflow