59

SVG ドキュメント内のマウス カーソルの位置に関して問題が発生しています。HTML ページでJavaScriptを使用して、ドラッグ時にカーソルを追従するポテンショメータを設計したいと考えています。

試しevt.clientX/Yてみevt.screenX/Yましたが、SVG がautoscaleであるため、SVG 内の座標が異なります。私は何日も答えを探していましたが、解決策を見つけることができませんでした (SVG の再スケーリング係数をリアルタイムで知っているか、SVG 座標系でのマウス位置の関数を持っています)。

ローテーションは単純なルールに従います。

if (evt.screenX < xc)
  ang = Math.atan((evt.screenY - yc) / (evt.screenX - xc)) * 360/(2*Math.PI) - 90;  

if (evt.screenX > xc)
  ang = Math.atan((evt.screenY - yc) / (evt.screenX - xc)) * 360/(2*Math.PI) + 90;  

回転の中心として、すべてを SVG 内のマウスの座標に(xc;yc)置き換えます。evt.screenX/Y

4

3 に答える 3

141

画面空間からグローバル SVG 空間に変換する方法だけでなく、ポイントを SVG 空間から要素の変換された空間に変換する方法も示すこのコードを参照してください:
http://phrogz.net/svg/drag_under_transformation.xhtml

要するに:

// Find your root SVG element
var svg = document.querySelector('svg');

// Create an SVGPoint for future math
var pt = svg.createSVGPoint();

// Get point in global SVG space
function cursorPoint(evt){
  pt.x = evt.clientX; pt.y = evt.clientY;
  return pt.matrixTransform(svg.getScreenCTM().inverse());
}

svg.addEventListener('mousemove',function(evt){
  var loc = cursorPoint(evt);
  // Use loc.x and loc.y here
},false);

編集:あなたのニーズに合わせたサンプルを作成しました(グローバルSVGスペースのみですが):
http://phrogz.net/svg/rotate-to-point-at-cursor.svg

上記に次のメソッドを追加します。

function rotateElement(el,originX,originY,towardsX,towardsY){
  var angle = Math.atan2(towardsY-originY,towardsX-originX);
  var degrees = angle*180/Math.PI + 90;
  el.setAttribute(
    'transform',
    'translate('+originX+','+originY+') ' +
      'rotate('+degrees+') ' +
      'translate('+(-originX)+','+(-originY)+')'
  );
}
于 2012-04-24T13:27:36.337 に答える
2

@Phrogz: あなたの素晴らしい例をありがとう、私はそれから学びました. 少し簡単にするために、以下のように一部を変更しました。コアJavaでマウスイベントを処理するのと同じように、ここでも同じように処理できると思うので、あなたの例で私の方法を試しました。

「rotateElement」機能は少し難しいと思うので削除し、代わりになるものを見つけました。

以下のコードを参照してください。

var svg=document.getElementById("svg1");
var pt=svg.createSVGPoint();
var end_small=document.getElementById("end_small");
var line=document.getElementById("line1");

end_small.addEventListener('mousemove', function(evt) {

    var loc=getCursor(evt);
    end_small.setAttribute("cx",loc.x);
    end_small.setAttribute("cy",loc.y);

    loc = getCursor(evt); // will get each x,y for mouse move

    line.setAttribute('x2',loc.x); // apply it  as end points of line
    line.setAttribute('y2',loc.y); // apply it as end points of line

}, false);

function getCursor(evt) {
    pt.x=evt.clientX;
    pt.y=evt.clientY;
    return pt.matrixTransform(svg.getScreenCTM().inverse());
}

だから私がしたことは、SVG全体ではなく小さな円にのみリスナーを追加したことです。マウスがあなたによって動かされるたびに、上記のように関数x, yから取得され、翻訳されず、翻訳されない行の時点でこれを与えます回転します。マウスを円に移動してからゆっくりと移動する必要があります。マウスが円から離れた場合、右側の小さな円にのみリスナーを追加したため、線は移動しません。getCursor()x, yx2, y2

于 2014-01-25T04:45:47.353 に答える