调整已经绘制的矩形paperjs的大小

时间:2019-08-29 00:02:37

标签: vue.js paperjs

我正在使用纸张JS在画布上创建一个矩形。以下是在vue.js中绘制矩形的代码。

created () {
    const toolDrag = event => {
      let trackingRect = new paper.Path.Rectangle(event.downPoint, event.point)
      trackingRect.strokeColor = new paper.Color('#2661D8')
      trackingRect.strokeColor.alpha = 0.7
      trackingRect.strokeWidth = this.strokeWidth

      trackingRect.removeOn({
        drag: true,
        up: true
      })
    }

    // Finalise rectangle properties and draw.
      let $this = this;
    const toolUp = event => {
      let newRect = new paper.Path.Rectangle(event.downPoint, event.point)
      newRect.strokeColor = new paper.Color(this.getColor().stroke)
      newRect.fillColor = new paper.Color(this.getColor().fill)
      newRect.strokeWidth = this.strokeWidth
        newRect.selected = true;

      // Custom data attribute:
      newRect.data.type = 'rectangle'
      newRect.data.class = ''
      // Flag the annotation has been edited and the changes are not saved
      this.flagAnnotationEdits()
    }

    this.toolRect = new paper.Tool();
    this.toolRect.onMouseDrag = toolDrag;
    this.toolRect.onMouseUp = toolUp;

  },

现在,我想允许用户通过拖动矩形的任何角来调整绘制的矩形的大小,但是我有点卡住了,无法理解该怎么做。

我已经看到了通过更改边界来调整矩形大小的解决方案,但是找不到我的用例的解决方案。任何帮助表示赞赏。

1 个答案:

答案 0 :(得分:1)

有很多方法可以实现您想要的。
我发现的最简单的方法之一是,每次拖动矩形的一个角时都重新创建矩形。
这样,您只需要知道拖动的角位置和对角位置,就可以轻松创建合适的矩形。
这是sketch,演示了可能的实现。
我认为您应该可以轻松地将其转换为您的特定案例。

// This settings controls the handles size.
const HANDLES_RADIUS = 5;

// This flag allow us to know when we are dragging an handle.
let dragging = false;
// This will store the offset from the handle position to the
// mouse down point. This allow a better drag UX.
let offset;
// This will store the point representing the opposite rectangle corner from
// the one being dragged.
let oppositePoint;

// We start by creating a rectangle in the middle of the canvas.
// This rectangle will be replaced each time a corner is dragged.
let rectangle = createRectangle(view.center - 50, view.center + 50);

// Then, we create an handle for each of the corners.
// These will be used to modify the rectangle shape.
const handles = rectangle.segments.map((segment, index) => new Path.Rectangle({
    from: segment.point - HANDLES_RADIUS,
    to: segment.point + HANDLES_RADIUS,
    fillColor: 'orange',
    // We store the segment index bound to this specific handle in the custom
    // data object. This will allow us to know, when an handle is clicked,
    // which segment is concerned by the event.
    data: { segmentIndex: index },
    // On mouse down on an handle...
    onMouseDown: function(event) {
        // ...get and store the opposite segment point.
        // We will use it later to redraw the rectangle.
        const oppositeSegmentIndex = (this.data.segmentIndex + 2) % 4;
        oppositePoint = rectangle.segments[oppositeSegmentIndex].point;
        // Store the offset.
        offset = event.point - rectangle.segments[this.data.segmentIndex].point;
        // Activate dragging state.
        dragging = true;
    }
}));

// On mouse move...
function onMouseMove(event) {
    // ...don't do nothing if we are not dragging an handle.
    if (!dragging) {
        return;
    }
    // Get the new corner position by applying the offset to the event point.
    const activePoint = event.point + offset;
    // Recreate the rectangle with the new corner.
    rectangle.remove();
    rectangle = createRectangle(oppositePoint, activePoint);
    // For each corner...
    rectangle.segments.forEach((segment, index) => {
        // ...place an handle...
        handles[index].position = segment.point;
        // ...store the potentially new segment <=> corner bound.
        handles[index].data.segmentIndex = index;
    });
}

// On mouse up...
function onMouseUp() {
    // Disable dragging state
    dragging = false;
}


//
// HELPERS
//

// This method is used to avoid duplicating the rectangle instantiation code.
function createRectangle(from, to) {
    return new Path.Rectangle({
        from,
        to,
        strokeColor: 'orange'
    });
}