Javascript 计算45度捕捉的坐标

Javascript 计算45度捕捉的坐标,javascript,math,svg,svg.js,Javascript,Math,Svg,Svg.js,我有一个SVG,它在原点和鼠标指针之间画一条线,我想做的是当按下shift(event.shiftKey===true)时,使线“捕捉”到最近的45度坐标,基本上与photoshop中的行为相同 我已经设法计算出两点之间的角度(以度为单位)(这样我也可以决定捕捉哪个角度,如果需要的话可能使用IF/ELSE树),但是我不知道如何根据新的角度重新计算“end”坐标 我在这里设置了一个简化的示例: 我还拍摄了一张我试图重现的photoshop行为的照片(质量很差,因为我不得不使用相机,因为我无法截图-

我有一个SVG,它在原点和鼠标指针之间画一条线,我想做的是当按下shift(event.shiftKey===true)时,使线“捕捉”到最近的45度坐标,基本上与photoshop中的行为相同

我已经设法计算出两点之间的角度(以度为单位)(这样我也可以决定捕捉哪个角度,如果需要的话可能使用IF/ELSE树),但是我不知道如何根据新的角度重新计算“end”坐标

我在这里设置了一个简化的示例:

我还拍摄了一张我试图重现的photoshop行为的照片(质量很差,因为我不得不使用相机,因为我无法截图-对不起),只是为了100%清楚:

本质上,我是在试图重现你在photoshop中按住shift键时的行为,但我猜你需要很好的数学才能解决问题,而我不是

非常感谢您的帮助:)

var-app=document.getElementById('app'),
svg=svg(应用程序),
line=svg.polyline([]).fill('none').stroke({width:1}),
开始=[250250],
end=null,
angleTxt=document.getElementById('angle'),
lineLengthTxt=document.getElementById('linelength');
行标记('开始'、10、10、功能(添加){
添加.圆圈(10).填充(“#f06”)
})
//鼠标移动时,重新绘制线条
svg.on('mousemove',函数(e){
结束=[e.layerX,e.layerY];
线图([开始,结束]);
calcAngle();
});
函数calcAngle(){
var deltaX=结束[0]-开始[0],
deltaY=结束[1]-开始[1],
rad=数学atan2(deltaY,deltaX),
度=弧度*(180/数学π),
linelen=Math.sqrt(deltaX*deltaX+deltaY*deltaY);
angleTxt.textContent=deg;
lineLengthTxt.textContent=linelen;
}
#应用程序{边框:1px纯蓝色;宽度:100%;高度:600px}

JS-Bin
角度:-
线路长度:-
我做到了

如何使用它

计算新角度,并使用余弦表示x值,使用正弦表示y值。这里的角度为-PI到PI,步长为PI/4;如果要更改步骤,请将“var newAngle=…”行中的4替换为其他数字

工作原理

首先我想的是,你需要8个角度的位置,4个π弧度(一个圆环是2π弧度)。所以你需要简化你的角度

newAngle / Math.PI // value is between -1 and 1 (it's a double)
newAngle / Math.PI * 4 // value is between -4 and 4 (it's a double)
Math.round(newAngle / Math.PI * 4) // value is between -4 and 4 (but it's a integer now)
Math.round(newAngle / Math.PI * 4) / 4 // value is between -1 and 1 (with step of 0.25)
Math.round(newAngle / Math.PI * 4) / 4 * Math.PI // value is between -PI and PI with step of 0.25 * PI (PI/4)
现在你的新角度是正确的。Cosinus返回角度的x值(查看维基百科的图形解释)和角度的y值。 将余弦/窦乘以长度,即可找到下一个点。

我做到了

如何使用它

计算新角度,并使用余弦表示x值,使用正弦表示y值。这里的角度为-PI到PI,步长为PI/4;如果要更改步骤,请将“var newAngle=…”行中的4替换为其他数字

工作原理

首先我想的是,你需要8个角度的位置,4个π弧度(一个圆环是2π弧度)。所以你需要简化你的角度

newAngle / Math.PI // value is between -1 and 1 (it's a double)
newAngle / Math.PI * 4 // value is between -4 and 4 (it's a double)
Math.round(newAngle / Math.PI * 4) // value is between -4 and 4 (but it's a integer now)
Math.round(newAngle / Math.PI * 4) / 4 // value is between -1 and 1 (with step of 0.25)
Math.round(newAngle / Math.PI * 4) / 4 * Math.PI // value is between -PI and PI with step of 0.25 * PI (PI/4)
现在你的新角度是正确的。Cosinus返回角度的x值(查看维基百科的图形解释)和角度的y值。 将余弦/窦乘以长度,即可找到下一个点。


您是否尝试在长度=第一个点和鼠标之间的距离的直线上应用角度?(距离=sqrt((x2-x1)²+(y2-y1)²))@kornflex我试过这个:。但是当你把它与photoshop行为(我用它作为用户体验的“标准”)相比时,绘制的线条长度太长了。我猜他们在计算线长度时必须做一些更复杂的事情。我注意到线长度上的“超调”随着距离的增加而变大(当线很小时,超调很小)。也许他们对线的长度做了指数修正?(但我的数学真的很差,所以我只是在抓救命稻草)你有没有试着用长度=第一个点和鼠标之间的距离来应用线的角度?(距离=sqrt((x2-x1)²+(y2-y1)²))@kornflex我试过这个:。但是当你把它与photoshop行为(我用它作为用户体验的“标准”)相比时,绘制的线条长度太长了。我猜他们在计算线长度时必须做一些更复杂的事情。我注意到线长度上的“超调”随着距离的增加而变大(当线很小时,超调很小)。也许他们对线的长度做了指数修正?(但我的数学真的不好,所以我只是在抓救命稻草)先生,你真是个传奇人物!我不知道你是怎么计算出来的(我想数学好会有帮助),但它工作得很好。非常感谢:大哈哈,不客气:)。我会更新我的解释,你需要理解,这没那么难。@TRG,kornflex,我可以建议一些改变/改进吗?添加
dist*=Math.cos(移位角度newAngle)。这会稍微改变距离,使端点在该角度/向量上是距离光标最近的点。先生,您是一个传奇!我不知道你是怎么计算出来的(我想数学好会有帮助),但它工作得很好。非常感谢:大哈哈,不客气:)。我会更新我的解释,你需要理解,这没那么难。@TRG,kornflex,我可以建议一些改变/改进吗?添加
dist*=Math.cos(移位角度newAngle)。这会略微更改距离,使端点在该角度/向量上成为距离光标最近的点。