简体   繁体   English

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

[英]paperjs draw 0 to 360º arc using mouse events

I´m trying to draw an arc using mouse events with paper.js我正在尝试使用带有 paper.js 的鼠标事件绘制弧线

The user must be able to draw an arc from 0 degree to 360 degree.用户必须能够绘制从 0 度到 360 度的圆弧。 The issue that I´m facing is that I can draw 270 degree arc but more than 270, the arc flips to another quadrant.我面临的问题是我可以绘制 270 度弧,但超过 270 度,弧会翻转到另一个象限。

Start point must be located anywhere起点必须位于任何位置

A sketch can be found here:可以在这里找到草图:

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 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

and this is the implemented code:这是实现的代码:

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'
    }
   
}

Thanks in advance提前致谢

There are certainly tons of ways to do this but here's how I would do it: sketch .当然有很多方法可以做到这一点,但我会这样做: 草图
This should help you finding the proper solution to your own use case.这应该可以帮助您找到适合您自己用例的解决方案。

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);
}

Edit编辑

In answer to your comment, here is a more mathematical approach: sketch .在回答您的评论时,这是一种更数学的方法: 草图
This is based on your code and has exactly the same behavior so you should have no difficulty using it.这是基于您的代码并且具有完全相同的行为,因此您应该没有困难使用它。
The key of both implementation is the Point.getDirectedAngle() method which allow you to adapt the behavior depending on the through point side.这两种实现的关键是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);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM