如何在Paper.js中的路径中选择单个曲线?

时间:2018-10-18 21:11:17

标签: paperjs

我需要明确选择单击路径的单个曲线,我该怎么做?

例如,在this sketch中,我们可以在单击时选择整个路径:

enter image description here

当前,我可以检测到曲线(无论如何,不​​确定是否合适):<​​/ p>

..onMouseDown = (event) ~>
    hit = scope.project.hitTest event.point
    if hit?item
        # select only that specific segment
        curves = hit.item.getCurves!
        nearest = null
        dist = null
        for i, curve of curves
            _dist = curve.getNearestPoint(event.point).getDistance(event.point)
            if _dist < dist or not nearest?
                nearest = i
                dist = _dist

        selected-curve = curves[nearest]
            ..selected = yes

但是仍然选择了整个路径:

enter image description here

我想要实现的是这样的:

enter image description here

2 个答案:

答案 0 :(得分:4)

有一种更轻松的方法来实现您想要的。
通过检查其location属性,您可以知道命中是否在曲线上。
如果已设置,则可以轻松获取曲线点并手动绘制选择。
这是sketch的演示。

enter image description here

var myline = new Path(new Point(100, 100));
myline.strokeColor = 'red';
myline.strokeWidth = 6;
myline.add(new Point(200, 100));
myline.add(new Point(260, 170));
myline.add(new Point(360, 170));
myline.add(new Point(420, 250));

function onMouseDown(event) {
    hit = paper.project.hitTest(event.point);

    // check if hit is on curve
    if (hit && hit.location) {
        // get curve
        var curve = hit.location.curve;
        // draw selection
        var selection = new Group(
            new Path.Line({
                from: curve.point1,
                to: curve.point2,
                strokeColor: 'blue',
                strokeWidth: 3
            }),
            new Path.Rectangle({
                from: curve.point1 - 5,
                to: curve.point1 + 5,
                fillColor: 'blue'
            }),
            new Path.Rectangle({
                from: curve.point2 - 5,
                to: curve.point2 + 5,
                fillColor: 'blue'
            })
        );
        // make it automatically be removed on next down event
        selection.removeOnDown();
    }
}

更新

作为替代方案,为避免弄乱导出的图形,您可以简单地选择线条而不是将其应用为笔触样式。
参见此sketch

enter image description here

var selection = new Path.Line({
    from: curve.point1,
    to: curve.point2,
    selected: true
});

答案 1 :(得分:2)

没有内置的方法可以完成您想要的AFAIK。

基本上,您需要遍历各个片段,构造一条直线,然后查看匹配是否在该特定直线上。这条线不能是透明的,也不能被视为命中点,这就是为什么我给它指定颜色和宽度以匹配可见线的原因。这也是测试后将其删除的原因。

以下是草图solution,它进一步实现了这一点:

function onMouseDown(event){
    if (!myline.hitTest(event.point)) {
        return
    }
    c1.remove()
    c2.remove()
    // there's a hit so this should find it
    let p = event.point
    let segs = myline.segments
    for (let i = 1; i < segs.length; i++) {

        let line = new Path.Line(segs[i - 1].point, segs[i].point)
        line.strokeWidth = 6
        line.strokeColor = 'black'
        if (line.hitTest(p)) {
            c1 = new Path.Circle(segs[i-1].point, 6)
            c2 = new Path.Circle(segs[i].point, 6)
            c1.fillColor = 'black'
            c2.fillColor = 'black'
            line.remove()
            return
        }
        line.remove()
    }
    throw new Error("could not find hit")
}

这是我画的:

enter image description here