paperjs 使用鼠标事件绘制 0 到 360º 弧

paperjs draw 0 to 360º arc using mouse events

我正在尝试通过 paper.js

使用鼠标事件绘制弧线

用户必须能够绘制从 0 度到 360 度的圆弧。 我面临的问题是我可以绘制 270 度弧,但超过 270 度,弧会翻转到另一个象限。

起点必须位于任何地方

草图可以在这里找到:

http://sketch.paperjs.org/#V/0.12.7/S/nVTBjpswEP2VEZeQXYcG2l6IOFTpZQ+RVruHHkpVeR1nQSE2MoZNFPHvtbHdeCGtorWEsOf5zTyex5wDhg80SIPnPZWkCFBA+FavOywAC/KbNHSVs5zptcDbsm2yZLlcmQChTFKRMfoGj7xkMvyyXCL1zC3eSCzkCP5qYJeTxJDBsAPLIlqXglQ0POcM1DDpU/tGJmhEpJDY9a6sqjWvuNo3e6kw2c9y1s9XoAvYD/AquNR6NFLwPXVcQbczNAZ/lFtZpBBPgDWuNYe3TLEADKzLAgyV4TJyJjmvIs42vG3ohndaz65lRJachbRTHzeHsyNpT2rPsgGPaj2PjshfnbSNjtLF2WD2wnjlI0lWT6OYvVY0C7skGmYP7EnZilmz6OJRxFXxuIJ0uMq0ueun7+GEgSZZ0bBE9hzNCb7Pa08qEvSgDAodaMNeh3wTJDQC9J5e2+a8BKcIV3WBYzS8kqu1TRfYhqKyFQy8xtgJfkj9gB5H14fREe5tF95ttCTCG1tyjt5zTn85pxGnKZnjXCi9R5eFaq7X4iYZcAcjIQoys2Rhq3xKbhHnMl3kXc30D8n8Q6bdj/J/xMRJjusKb7/xn/974+11t03Um7+Z+ne+CIr3w+1sgvTnr/4P

这是实现的代码:

var arc_cse;

var radius=200;
var center=new Point(400,400);
var start=new Point(400,500);


var c1 = new Path.Circle({
    center: center,
    radius: 2,
    fillColor: 'black'
}); 

arc_cse = new Path({
        strokeColor: 'red',
        strokeWidth: 1,
        strokeCap: 'round',  
    });    

           
tool.onMouseMove = function(event) {

    var p=new Point(event.point.x,event.point.y);
    var v1=start-center;
    var v2=p-center;
    var angle=(v2.angleInRadians-v1.angleInRadians);
    
    var arcval=arc_CRD(v1.angleInRadians,v2.angleInRadians,angle,center,radius);
    
    arc_cse.remove();
    arc_cse= new Path.Arc(arcval);
}

function arc_CRD(alpha1,alpha2,angle,center,radius){
   
    return {
        from: {
            x: center.x + radius*Math.cos(alpha1),
            y: center.y + radius*Math.sin(alpha1)
        },
        through: {
            x: center.x + radius * Math.cos(alpha1 + (alpha2-alpha1)/2),
            y: center.y + radius * Math.sin(alpha1 + (alpha2-alpha1)/2)
        },
        to: {
            x: center.x + radius*Math.cos(alpha1+(alpha2-alpha1)),
            y: center.y + radius*Math.sin(alpha1+(alpha2-alpha1))
        },
        strokeColor: 'red',
        strokeWidth: 3,
        strokeCap: 'round'
    }
   
}

提前致谢

当然有很多方法可以做到这一点,但我会这样做:sketch
这应该可以帮助您找到适合您自己用例的解决方案。

function dot(point, color) {
    const item = new Path.Circle({ center: point, radius: 5, fillColor: color });
    item.removeOnMove();
}

function drawArc(from, center, mousePoint) {
    const radius = (from - center).length;
    const circle = new Path.Circle(center, radius);
    const to = circle.getNearestPoint(mousePoint);
    const middle = (from + to) / 2;

    const throughVector = (middle - center).normalize(radius);
    const angle = (from - center).getDirectedAngle(to - center);
    const through = angle <= 0
        ? center + throughVector
        : center - throughVector;

    const arc = new Path.Arc({
        from,
        through,
        to,
        strokeColor: 'red',
        strokeWidth: 2
    });

    circle.removeOnMove();
    arc.removeOnMove();

    // Visual helpers
    dot(from, 'orange');
    dot(center, 'black');
    dot(mousePoint, 'red');
    dot(to, 'blue');
    dot(middle, 'lime');
    dot(through, 'purple');
    circle.strokeColor = 'black';

    return arc;
}

function onMouseMove(event) {
    drawArc(view.center + 100, view.center, event.point);
}

编辑

为了回答您的评论,这里有一个更数学的方法:sketch
这是基于您的代码并具有完全相同的行为,因此您使用它应该没有困难。
这两种实现的关键是 Point.getDirectedAngle() 方法,它允许您根据通过点侧调整行为。

const center = new Point(400, 400);
const start = new Point(400, 500);

const c1 = new Path.Circle({
    center: center,
    radius: 2,
    fillColor: 'black'
});

let arc;

function getArcPoint(from, center, angle) {
    return center + (from - center).rotate(angle);
}

function drawArc(from, center, mousePoint) {
    const directedAngle = (from - center).getDirectedAngle(mousePoint - center);
    const counterClockwiseAngle = directedAngle < 0
        ? directedAngle
        : directedAngle - 360;

    const through = getArcPoint(from, center, counterClockwiseAngle / 2);
    const to = getArcPoint(from, center, counterClockwiseAngle);

    return new Path.Arc({
        from,
        through,
        to,
        strokeColor: 'red',
        strokeWidth: 1,
        strokeCap: 'round'
    });
}

function onMouseMove(event) {
    if (arc) {
        arc.remove();
    }
    arc = drawArc(start, center, event.point);
}