2017-02-28 5 views
0

私は起点とマウスポインタの間に線を引くSVGを持っていますが、シフトが押されたときに何をしたいのですか(event.shiftKey === true) 「スナップ」は、最も近い45度の座標になります。これは、Photoshopで基本的に得られるのと同じ動作です。45度のスナップの座標を計算する

私は2つのポイントの間の角度で角度を計算することができました(必要に応じて、おそらくIF/ELSEツリーを使用して、どの角度をスナップするかを決めることができます)。しかし、新しい度合いに基づいて「終わり」の座標を計算します。私はここに簡単な例設定した

:私はcouldnとしてカメラを使用していたとして、私はまた、私は再作成しようとしているPhotoshopの行動の写真を撮影したhttps://jsbin.com/sohafekije/2/edit?html,js,output

は(品質が悪いです「トンスクリーンショット - 申し訳ありません)ただ、100%明確にする:http://i.imgur.com/Yo04uxY.jpg

enter image description here

基本的に私はあなたがシフトキーを押したときに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>

+0

長さ=最初の点とマウスの間の距離で線に角度を適用しようとしましたか? (距離= sqrt((x2 - x1)²+(y2 - y1)²)) – Kornflexx

+0

@Kornflexxまあ私はこれを試した:https://jsbin.com/kebikekaxo/1/edit?html,js,output。しかし、描画された行の長さは、Photoshopの動作と比較すると長すぎます(私はUXの目的で "標準"として使用しています)。私は彼らが線の長さを計算するときにはもっと複雑な何かをしなければならないと思う。 – TRG

+0

私は、線の長さの "オーバーシュート"が距離とともに大きくなることに気付きました(線が小さいときはオーバーシュートが小さい)。多分、線の長さにある種の指数修正を適用するでしょうか? (しかし、私は実際には数学では悪いので、ここではストローで握っています) – TRG

答えて

1

私はそれをやりました!

どのように新しい角度を計算し、yの値のx値と洞のためのコサインを使用して、それを適用

それを使用しています。ここでは、PI/4のステップで角度が-PIにPIに到達しました。ステップを変更したい場合は、 'var newAngle = ...'行の4を他の番号で置き換えます。それはですどのように

は、私はあなたが8角位置、PIのラジアンで4を(cirlceが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は角度のx値を返し(グラフィックの説明はwikipediaを参照)、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)]; 
} 
+0

あなたは伝説です!私はあなたがそれをどのように働かせたか分かりません(私は数学に役立つと思います)が、それは完全に機能します。ありがとうございますD – TRG

+0

アハハ、あなたは歓迎です:)。私はあなたの説明を更新するつもりです、理解する必要があります、それほど難しいことではありません。 – Kornflexx

+0

@TRG、Kornflexx、私はちょっとした変更や改善をお勧めしますか?新しい終わりを計算する前に 'dist * = Math.cos(shiftedAngle-newAngle);'を追加してください。これは、その角度/ベクトル上でカーソルが最も近い可能な点になるように、距離をわずかに変更します。 – Thomas

関連する問題