计算 45 度捕捉的坐标
Calculate coordinates for 45 degree snap
我有一个 SVG 在原点和鼠标指针之间画一条线,我想做的是当按下 shift 时(event.shiftKey === true)使线 "snap" 到最近的 45 度坐标,基本上与您在 photoshop 中获得的行为相同。
我已经设法计算出两点之间的角度(因此我也可以决定捕捉哪个角度,如果需要的话可能会使用 IF/ELSE 树)但是我不知道我如何根据新度数重新计算 "end" 坐标。
我在这里建立了一个简化的例子:https://jsbin.com/sohafekije/2/edit?html,js,output
我还拍了一张我正在尝试重现的 Photoshop 行为的照片(质量很差,因为我不得不使用相机,因为我无法截屏 - 抱歉)只是为了 100% 清晰:http://i.imgur.com/Yo04uxY.jpg
本质上,我正在尝试重现您在按住 Shift 键时在 photoshop 中获得的行为,但我猜想您需要非常擅长数学才能找到解决方案,而我不是!
非常感谢任何帮助:)
var app = document.getElementById('app'),
svg = SVG(app),
line = svg.polyline([]).fill('none').stroke({ width: 1 }),
start = [250,250],
end = null,
angleTxt = document.getElementById('angle'),
lineLengthTxt = document.getElementById('linelength');
line.marker('start', 10, 10, function(add) {
add.circle(10).fill('#f06')
})
// On mouse move, redraw the line
svg.on('mousemove', function(e){
end = [e.layerX, e.layerY];
line.plot([start, end]);
calcAngle();
});
function calcAngle() {
var deltaX = end[0] - start[0],
deltaY = end[1] - start[1],
rad = Math.atan2(deltaY, deltaX),
deg = rad * (180/Math.PI),
linelen = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
angleTxt.textContent = deg;
lineLengthTxt.textContent = linelen;
}
#app { border: 1px solid blue; width:100%; height:600px}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
<script type="text/javascript" src="https://rawgit.com/svgdotjs/svg.js/master/dist/svg.js"></script>
</head>
<body>
<div id="app"></div>
Angle: <span id="angle">-</span><br>
Line Length: <span id="linelength">-</span>
</body>
</html>
我做到了!
How use it
您计算新角度并使用余弦作为 x 值并使用正弦作为 y 值来应用它。这里的角度从 -PI 到 PI,步长为 PI/4;如果要更改步骤,请将 'var newAngle = ...' 行中的 4 替换为其他数字。
How it's works
首先我在考虑你需要 8 个角度位置,4 个 PI 弧度(一个圆是 2PI 弧度)。所以你需要简化你的角度。
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 return 角度的 x 值(查看维基百科的图形解释)和 Sinus 角度的 y 值。
将 COSINUS/SINUS 乘以长度即可找到下一个点。
function applyNewAngle() {
var deltaX = end[0] - start[0],
deltaY = end[1] - start[1],
dist = Math.sqrt(Math.pow(deltaX,2) + Math.pow(deltaY,2));
var newAngle = Math.atan2(deltaY, deltaX);
var shiftedAngle = Math.round(newAngle / Math.PI * 4) / 4 * Math.PI;
end = [start[0]+dist*Math.cos(shiftedAngle), start[1]+dist*Math.sin(shiftedAngle)];
}
我有一个 SVG 在原点和鼠标指针之间画一条线,我想做的是当按下 shift 时(event.shiftKey === true)使线 "snap" 到最近的 45 度坐标,基本上与您在 photoshop 中获得的行为相同。
我已经设法计算出两点之间的角度(因此我也可以决定捕捉哪个角度,如果需要的话可能会使用 IF/ELSE 树)但是我不知道我如何根据新度数重新计算 "end" 坐标。
我在这里建立了一个简化的例子:https://jsbin.com/sohafekije/2/edit?html,js,output
我还拍了一张我正在尝试重现的 Photoshop 行为的照片(质量很差,因为我不得不使用相机,因为我无法截屏 - 抱歉)只是为了 100% 清晰:http://i.imgur.com/Yo04uxY.jpg
本质上,我正在尝试重现您在按住 Shift 键时在 photoshop 中获得的行为,但我猜想您需要非常擅长数学才能找到解决方案,而我不是!
非常感谢任何帮助:)
var app = document.getElementById('app'),
svg = SVG(app),
line = svg.polyline([]).fill('none').stroke({ width: 1 }),
start = [250,250],
end = null,
angleTxt = document.getElementById('angle'),
lineLengthTxt = document.getElementById('linelength');
line.marker('start', 10, 10, function(add) {
add.circle(10).fill('#f06')
})
// On mouse move, redraw the line
svg.on('mousemove', function(e){
end = [e.layerX, e.layerY];
line.plot([start, end]);
calcAngle();
});
function calcAngle() {
var deltaX = end[0] - start[0],
deltaY = end[1] - start[1],
rad = Math.atan2(deltaY, deltaX),
deg = rad * (180/Math.PI),
linelen = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
angleTxt.textContent = deg;
lineLengthTxt.textContent = linelen;
}
#app { border: 1px solid blue; width:100%; height:600px}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
<script type="text/javascript" src="https://rawgit.com/svgdotjs/svg.js/master/dist/svg.js"></script>
</head>
<body>
<div id="app"></div>
Angle: <span id="angle">-</span><br>
Line Length: <span id="linelength">-</span>
</body>
</html>
我做到了!
How use it
您计算新角度并使用余弦作为 x 值并使用正弦作为 y 值来应用它。这里的角度从 -PI 到 PI,步长为 PI/4;如果要更改步骤,请将 'var newAngle = ...' 行中的 4 替换为其他数字。
How it's works
首先我在考虑你需要 8 个角度位置,4 个 PI 弧度(一个圆是 2PI 弧度)。所以你需要简化你的角度。
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 return 角度的 x 值(查看维基百科的图形解释)和 Sinus 角度的 y 值。 将 COSINUS/SINUS 乘以长度即可找到下一个点。
function applyNewAngle() {
var deltaX = end[0] - start[0],
deltaY = end[1] - start[1],
dist = Math.sqrt(Math.pow(deltaX,2) + Math.pow(deltaY,2));
var newAngle = Math.atan2(deltaY, deltaX);
var shiftedAngle = Math.round(newAngle / Math.PI * 4) / 4 * Math.PI;
end = [start[0]+dist*Math.cos(shiftedAngle), start[1]+dist*Math.sin(shiftedAngle)];
}