如何在paperjs中拖动/调整矩形大小和旋转矩形



我想在paperjs中拖动并调整矩形的大小,我还想旋转矩形并调整其大小,同时保持其相对尺寸。

理想情况下,我希望通过拖动鼠标的一个角(锚点)来完成此操作。在paperjs中,什么数学或功能有助于做到这一点?

我已经尝试过使用缩放和修改拐角,但它并没有像我希望的那样工作。有人能给我一个解决方案吗?

提前谢谢。

这里有一个简单的解决方案,应该可以让您开始。它不处理旋转,因为我不确定用户界面是如何工作的,但通过修改边界框来调整矩形的大小,你应该能够毫无问题地旋转它。

paperjs草图

我决定制作我自己的用户界面,并在没有更多信息的情况下,使示例更加复杂,以尽可能多地解决你们的问题。这是新的草图:

新草图

UI是

  1. 在矩形中单击以通过拖动移动它
  2. 单击一个角并拖动以调整其大小
  3. 控件单击一个角来旋转它

点击角落有点棘手,但这是留给读者的练习。它们是彩色圆圈,只是为了强调Path的每个分段点的位置。

代码要点:

  • 使用矩形的边界进行缩放。就纸张而言,CCD_ 2不是矩形。它是连接四个线段点的四条曲线(恰好是直的)。当你需要使用一个矩形来获得它的中心、左上角等时,你需要一个Rectangle。使用矩形的边界(Path.Rectangle.bounds)缩放可见矩形。代码用一个额外的浅绿色矩形来说明边界,这样它就可以看到(旋转时最容易看到)。

  • onMouseDown()设置onMouseDrag()的状态,并设置每个状态所需的数据,例如,保存缩放基准以调整大小。

  • onMouseDrag()实现移动、调整大小和旋转。

    tool.onMouseDrag = function(e) {
    if (rect.data.state === 'moving') {
    rect.position = rect.position + e.point - e.lastPoint;
    adjustRect(rect);
    } else if (rect.data.state === 'resizing') {
    // scale by distance from down point
    var bounds = rect.data.bounds;
    var scale = e.point.subtract(bounds.center).length /
    rect.data.scaleBase.length;
    var tlVec = bounds.topLeft.subtract(bounds.center).multiply(scale);
    var brVec = bounds.bottomRight.subtract(bounds.center).multiply(scale);
    var newBounds = new Rectangle(tlVec + bounds.center, brVec + bounds.center);        
    rect.bounds = newBounds;        
    adjustRect(rect);
    } else if (rect.data.state === 'rotating') {
    // rotate by difference of angles, relative to center, of
    // the last two points.
    var center = rect.bounds.center;
    var baseVec = center - e.lastPoint;
    var nowVec = center - e.point;
    var angle = nowVec.angle - baseVec.angle;
    rect.rotate(angle);
    adjustRect(rect);
    }
    }
    
  • 移动非常容易——只需计算事件的当前点和最后一点之间的差,并将矩形的位置更改那么多。

  • 调整大小并不那么明显。策略是根据鼠标放下点和矩形中心之间的原始距离(scaleBase.length)调整x和y边界。请注意,虽然paper-full.js允许使用带点的运算符("+"、"-"、"*"、"/"),但我使用了几次原始的subtract()multiply()方法,我发现以这种方式链式计算是很自然的。

  • 旋转使用了一个非常好的论文概念,即点也定义了一个向量,向量有一个角度。它只是注意到事件lastPointpoint相对于矩形中心的角度差异,并将矩形旋转该差异。

  • CCD_ 13和CCD_。

考虑以下内容。我只是通过大量的例子来弄清楚这一点。

我的目标:

  • 选择项目时使用我自己的边界框
  • 移动、调整大小和旋转(捕捉到旋转[45度])选定项目
  • 显示项目的标题/名称

示例草图

Paper.js代码

var hitOptions = {
segments: true,
stroke: true,
fill: true,
tolerance: 5
};
function drawHex(w, c, n){
var h = new Path.RegularPolygon(new Point(100, 100), 6, w / 2);
h.selectedColor = 'transparent';

c = c != undefined ? c : "#e9e9ff";
n = n != undefined ? n : "Hexayurt";
h.name = n;
h.fillColor = c;
h.data.highlight = new Group({
children: [makeBounds(h), makeCorners(h), makeTitle(h)],
strokeColor: '#a2a2ff',
visible: false
});

return h;
}
function makeCorners(o, s){
s = s != undefined ? s : 5;
var g = new Group();
var corners = [
o.bounds.topLeft,
o.bounds.topRight,
o.bounds.bottomLeft,
o.bounds.bottomRight
];
corners.forEach(function(corner, i) {
var h = new Path.Rectangle({
center: corner,
size: s
});
g.addChild(h);
});
return g;
}
function makeBounds(o){
return new Path.Rectangle({
rectangle: o.bounds
});
}
function makeTitle(o, n, c){
c = c != undefined ? c : 'black';
var t = new PointText({
fillColor: c,
content: n != undefined ? n : o.name,
strokeWidth: 0
});
t.bounds.center = o.bounds.center;
return t;
}
function selectItem(o){
console.log("Select Item", o.name);
o.selected = true;
o.data.highlight.visible = true;
o.data.highlight.bringToFront();
}
function clearSelected(){
project.selectedItems.forEach(function(o, i){
console.log("Unselect Item", o.name);
o.data.highlight.visible = false;
});
project.activeLayer.selected = false;
}
function moveBoxes(o){
var boxes = o.data.highlight.children[1].children;
boxes[0].position = o.bounds.topLeft;
boxes[1].position = o.bounds.topRight;
boxes[2].position = o.bounds.bottomLeft;
boxes[3].position = o.bounds.bottomRight;
}
function moveTitle(o){
var t = o.data.highlight.children[2];
t.bounds.center = o.bounds.center;
}
function adjustBounds(o){
if(o.data.state == "moving"){
o.data.highlight.position = o.position;
} else {
o.data.highlight.children[0].bounds = o.bounds;
moveBoxes(o);
}
}
var hex1 = drawHex(200);
console.log(hex1.data, hex1.data.highlight);
var segment, path;
var movePath = false;
var tool = new Tool();
tool.minDistance = 10;
tool.onMouseDown = function(event) {
segment = path = null;
var hitResult = project.hitTest(event.point, hitOptions);
if (!hitResult){
clearSelected();
return;
}
if(hitResult && hitResult.type == "fill"){
path = hitResult.item;
}
if (hitResult && hitResult.type == "segment") {
path = project.selectedItems[0];
segment = hitResult.segment;
if(event.modifiers.control){
path.data.state = "rotating";
} else {
path.data.state = "resizing";
path.data.bounds = path.bounds.clone();
path.data.scaleBase = event.point - path.bounds.center;
}
console.log(path.data);
}
movePath = hitResult.type == 'fill';
if (movePath){
project.activeLayer.addChild(hitResult.item);
path.data.state = "moving";
selectItem(path);
console.log("Init Event", path.data.state);
}
};
tool.onMouseDrag = function(event) {
console.log(path, segment, path.data.state);
if (segment && path.data.state == "resizing") {
var bounds = path.data.bounds;
var scale = event.point.subtract(bounds.center).length / path.data.scaleBase.length;
var tlVec = bounds.topLeft.subtract(bounds.center).multiply(scale);
var brVec = bounds.bottomRight.subtract(bounds.center).multiply(scale);
var newBounds = new Rectangle(tlVec + bounds.center, brVec + bounds.center);        
path.bounds = newBounds;
adjustBounds(path);
} else if(segment && path.data.state == "rotating") {
var center = path.bounds.center;
var baseVec = center - event.lastPoint;
var nowVec = center - event.point;
var angle = nowVec.angle - baseVec.angle;
if(angle < 0){
path.rotate(-45);
} else {
path.rotate(45);
}
adjustBounds(path);
} else if (path && path.data.state == "moving") {
path.position += event.delta;
adjustBounds(path);
}
};

这将使用.data将边界框、句柄和标题的引用存储为一个组。这样,它们总是在那里,它们可以只是visible的真或假。这样可以根据需要轻松地显示和隐藏它们。

drawHex( width , color, name )

  • 宽度-必需,宽像素数
  • 颜色-可选,用于定义填充颜色的字符串。默认值:#e9e9ff
  • 名称-可选,用作名称和标题的字符串。默认值:";Hexayurt">

交互

  • 单击-选择项目(显示边界框和控制柄)
  • 单击+拖动-移动项目
  • 单击并拖动控制柄-调整项目大小
  • Ctrl+单击+拖动手柄-旋转项目

这是我的第一次尝试,我可能会清理很多代码。例如,我可以专门将事件绑定到句柄,而不是查看更多全局事件。

相关内容

  • 没有找到相关文章

最新更新