使用javascript(interact.js)调整旋转项目的大小

che*_*xis 14 javascript resize interact.js

我花了很多天时间尝试使用interact.js旋转一个可调整大小的项目.

这是我此时的代码,我将尝试解释这个概念.

我们有一个选择器项有两个原因,因为容器可以使用css转换(比如缩放),我们需要将选择器放在外面,因为我们有一个多选,如果我选择了两个矩形,选择器会增长,但在这种情况下,这不是主要问题,我们已经计算了比例,没有问题和其他事情.

当选择器调整大小时,它采用矩形,并使宽度,高度,左,顶部和旋转相同.

使用Javascript:

// TAP - CLICK EVENT (just for positioning the selector)
interact('#rectangle').on('tap', event => {
  console.log('Tap Box!');
  event.stopPropagation();
  const $rectangleCloned = $('#rectangle').clone();
  const previousTransform = $rectangleCloned.css('transform');
  $rectangleCloned.css('transform', 'none');
  $rectangleCloned.css('opacity', '0');
  $rectangleCloned.css('display', 'block');


  $('#container').append($rectangleCloned);
  const values = $rectangleCloned[0].getBoundingClientRect();
  // This is just a trick for fast implementation:
  $('#selector').css('top', values.y);
  $('#selector').css('left', values.x);
  $('#selector').css('width', values.width);
  $('#selector').css('height', values.height);
  $('#selector').css('transform', previousTransform);

  $rectangleCloned.remove();
  return values;
});


interact('.pointer9').draggable({
  max: 1,
  onmove: event => {
    const angleDeg =
      Math.atan2(
        centerRotate.posY - event.pageY,
        centerRotate.posX - event.pageX
      ) *
      180 /
      Math.PI;

    console.log(this.rotate);
    const prevAngle = this.rotate - angleInitial;
    const angle = parseInt(angleDeg) + prevAngle;
    this.$rectangle.css({
      transform: 'rotate(' + angle + 'deg)'
    });
    this.$selector.css({
      transform: 'rotate(' + angle + 'deg)'
    });
  },
  onstart: event => {
    const data = event.interactable.getRect(event.target.parentNode);
    this.centerRotate = {
      posX: data.left + data.width / 2,
      posY: data.top + data.height / 2
    };
    this.angleInitial =
      Math.atan2(
        centerRotate.posY - event.pageY,
        centerRotate.posX - event.pageX
      ) *
      180 /
      Math.PI;
    this.$rectangle = $('#rectangle');
    this.$selector = $('#selector');
    this.rotate = $rectangle.attr('angle') || 0;
  },
  onend: event => {
    const $box = $('#selector');
    const matrix = $box.css('transform');
    const values = matrix
      .split('(')[1]
      .split(')')[0]
      .split(',');

    var a = values[0];
    var b = values[1];
    var angle = Math.round(Math.atan2(b, a) * (180 / Math.PI));
    $rectangle.attr('angle', angle);

  }
});


interact('#selector')
  .resizable({
    // resize from all edges and corners
    edges: {
      left: true,
      right: true,
      bottom: true,
      top: true
    },

    // keep the edges inside the parent
    restrictEdges: {
      outer: 'parent',
      endOnly: true,
    },

    // minimum size
    restrictSize: {
      min: {
        width: 100,
        height: 50
      },
    },

    inertia: true,
  })
  .on('resizemove', function(event) {
    var target = event.target,
      x = parseFloat($(target).offset().left) || 0,
      y = parseFloat($(target).offset().top) || 0;

    // update the element's style
    target.style.width = event.rect.width + 'px';
    target.style.height = event.rect.height + 'px';

    // translate when resizing from top or left edges
    x += event.deltaRect.left;
    y += event.deltaRect.top;

    target.style.left = x + 'px';
    target.style.top = y + 'px';

    $('#rectangle')[0].style.left = target.style.left;
    $('#rectangle')[0].style.top = target.style.top;

    $('#rectangle')[0].style.width = target.style.width;
    $('#rectangle')[0].style.height = target.style.height;

    target.setAttribute('data-x', x);
    target.setAttribute('data-y', y);

  });
Run Code Online (Sandbox Code Playgroud)

CSS:

#container {
  width: 500px;
  height: 400px;
  top: 0;
  left: 0;
  position: absolute;
  background-color: #CCC;
}

#rectangle {
  top: 50px;
  left: 50px;
  width: 120px;
  height: 60px;
  background-color: red;
  position: absolute;
}

#selector {
  display: inline-block;
  position: absolute;
  pointer-events: none;
  z-index: 9999;
  top: -1000px;
  /*Not showing at start*/
}

#selector .pointers {
  display: inline-block;
  position: absolute;
  z-index: 2;
  width: 10px;
  height: 10px;
  pointer-events: all;
}

#selector .pointers .point {
  width: 10px;
  height: 10px;
  background-color: #fff;
  border: 2px solid rgba(0, 0, 0, 0.9);
  border-radius: 50%;
  box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
}

#selector .pointers.pointer1 {
  top: -5px;
  left: -5px;
}

#selector .pointers.pointer2 {
  bottom: -5px;
  left: -5px;
}

#selector .pointers.pointer3 {
  top: -5px;
  right: -5px;
}

#selector .pointers.pointer4 {
  bottom: -5px;
  right: -5px;
}

#selector .pointers.pointer-north {
  top: -5px;
  left: calc(50% - 5px);
}

#selector .pointers.pointer-south {
  bottom: -5px;
  left: calc(50% - 5px);
}

#selector .pointers.pointer-east {
  right: -5px;
  top: calc(50% - 5px);
}

#selector .pointers.pointer-west {
  left: -5px;
  top: calc(50% - 5px);
}

#selector .pointer-rotate {
  border: 2px solid rgba(0, 0, 0, 0.9);
  box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
  border-radius: 50%;
  cursor: rotate;
}

#selector .pointer9 {
  bottom: -70px;
  left: calc(50% - 11px);
  display: inline-block;
  width: 20px;
  height: 20px;
  background-color: #fff;
  pointer-events: all;
  position: absolute;
}

#selector .rotate-line {
  border-left: 1px dashed #5f5f5f;
  height: 40px;
  position: absolute;
  top: -40px;
  left: calc(50% - 1px);
  width: 1px;
}
Run Code Online (Sandbox Code Playgroud)

HTML:

<div id="container">
  <div id="rectangle">
  </div>
  <div id="selector">
    <div class="pointers pointer1">
      <div class="point"></div>
    </div>
    <div class="pointers pointer2">
      <div class="point">
      </div>
    </div>
    <div class="pointers pointer3">
      <div class="point">
      </div>
    </div>
    <div class="pointers pointer4">
      <div class="point">
      </div>
    </div>
    <div class="pointers pointer-north">
      <div class="point">
      </div>
    </div>
    <div class="pointers pointer-east">
      <div class="point">

      </div>
    </div>
    <div class="pointers pointer-south">
      <div class="point">
      </div>
    </div>
    <div class="pointers pointer-west">
      <div class="point">
      </div>
    </div>
    <span class="topline lines-resize" />
    <span class="rightline lines-resize" />
    <span class="botline lines-resize" />
    <span class="leftline lines-resize" />
    <div class="pointer-rotate pointer9" />
    <div class="rotate-line" />
  </div>
</div>
Run Code Online (Sandbox Code Playgroud)

小提琴测试:

https://jsfiddle.net/ub70028c/46/

我已经读到其他人试图做同样的事情而没有结果......

谢谢!

Ali*_*ani 5

我检查了你的代码和类似的库resizable,并rotatable找出了你的问题。

首先,检查类似库:

请参阅我由jquery.freetrans.js创建的这个小提琴

如果你检查<div class="shape">,你可以看到

transform: matrix(1, 0, 0, 1, 0, 0);
Run Code Online (Sandbox Code Playgroud)

如果你旋转它,transform变化如下:

transform: matrix(0.997373, -0.0724379, 0.0724379, 0.997373, 0, 0);
Run Code Online (Sandbox Code Playgroud)

在类似的情况下,您的代码transform首先使用它,但它不使用transform,并且在旋转之后,它如下所示:

transform: rotate(-2.49576deg);
Run Code Online (Sandbox Code Playgroud)

如果您可以使用matrix而不是rotatein transform,您的代码将正常工作。如果您无法更改它,您可以使用类似的库,例如可以jquery.freetrans.js与旋转和调整大小一起正常工作的库。


Tar*_*ani 1

https://github.com/taye/interact.js/issues/569

https://github.com/taye/interact.js/issues/499

https://github.com/taye/interact.js/issues/394

恐怕您选择了一个作者已明确表达其意图的库

没有内置的方法。正如我在中提到的,#137我对处理缩放或旋转元素并不真正感兴趣

所以你应该问自己的问题是

我是否想找到一种解决方法来使这个库正常工作,或者选择另一个库?

更新 1:2018 年 4 月 28 日

如果您想在画布而不是普通元素中进行操作,那么我发现Fabric.js是一个不错的选择

FabricJS