外側の div 内に内側の div があります。内側の div はドラッグ可能で、外側は 40 度回転します。これはテストケースです。実際の場合、それは任意の角度である可能性があります。図に示すように配置されているポイントと呼ばれる別の div があります。(私はフラッシュバックグラウンドから来ました。フラッシュでは、内側のdivをドラッグすると、外側の回転されたdivの中に含まれていてもマウスに従います。)しかし、HTMLでは、見えるように内側のdivはマウスに従いません。フィドルから。divの「ポイント」がマウスに正確に追従するようにします。これは可能ですか?三角法を使って動かそうとしましたが、うまくいきませんでした。
6 に答える
これがこの問題に対する私のアプローチです。
回転したdivの外側にポイントを置きます。そうすれば、ドラッグ イベントが通常の動作を生成することが保証されます (変な方向にジャンプすることはありません)。ドラッグ可能なハンドラーを使用して、ポイントをマウス カーソルにアタッチします。
ドラッグ イベントでは、ドラッグ オフセットを変換して新しい値を反映させます。これは、回転角度の反対方向に、外側の div 中心を中心にオフセットを回転させることによって行われます。
テストしたところ、IE9、Firefox、および Chrome で動作しているようです。
角度にさまざまな値を試すことができ、うまく機能するはずです。
ページ内の複数の div に同じロジックを適用できるように、HTML も変更しました。
編集:
コメントで提案されているように、封じ込め動作とカスケード回転を考慮してスクリプトを更新しました。
また、outer
divを別のdiv内にドラッグできるようにすることで期限切れになります。現在、ほとんど機能しています。ドラッグされた div の中心を更新して、ドラッグ動作を修正できるようにする必要があります。
赤いdivをドラッグしてみてください。
私は今仕事をしているので、あなたのために仕事をすることはできませんが、あなたの問題を解決するための最も近い方法の背後にある数学を説明することができます(おそらく最も簡単な解決策ではありませんが、他のハックのいくつかとは異なり、はるかに柔軟です実装したら)。
まず最初に、使用している回転プラグインが要素に変換を適用していることを理解する必要があります(transform: rotate(30deg)
)。これは、ブラウザーによってマトリックスに変更されます(matrix(0.8660254037844387, 0.49999999999999994, -0.49999999999999994, 0.8660254037844387, 0, 0)
)。次に、要素を回転させることにより、子要素の軸が完全に回転することを理解する必要があります(長い間探した後、これを回避する実際のトリックはありません。これは理にかなっています)。他の回答のいくつかが示唆しているように、子を親から外すこともできますが、これはアプリケーションのオプションではないと思います。
ここで、このように行う必要があるのは、親の元の行列をキャンセルすることです。これは2段階のプロセスです。まず、次の行に沿ったコードを使用して行列を見つける必要があります。
var styles = window.getComputedStyle(el, null);
var matrix = styles.getPropertyValue("-webkit-transform") ||
styles.getPropertyValue("-moz-transform") ||
styles.getPropertyValue("-ms-transform") ||
styles.getPropertyValue("-o-transform") ||
styles.getPropertyValue("transform");
次に、マトリックスは上記のような文字列になります。これを使用して作業できる配列に解析する必要があります(これを行うためのjqueryプラグインがあります)。それが済んだらrotate(-30deg)
、たとえばこのライブラリ(または数学の本:P)を使用して実行できる行列の逆行列(例では要約)を取得する必要があります。
最後に、逆行列時間を実行する必要があります(前述の行列ライブラリを使用)変換行列(このツールを使用して、それらがどのように見えるかを理解します(変換はx軸とy軸に沿った動きであり、左と上に少し似ています)比較的配置された要素ですが、ハードウェアで高速化され、行列変換cssプロパティの一部です))これにより、子要素に適用できる新しい行列が得られ、親要素と同じ軸上で平行移動が得られます。
left
さて、これを、特に回転のみのtop
手動三角法1(逆行列または行列の必要性全体を完全にバイパスする)で行うことでこれを大幅に簡略化できますが、これには通常の回転でのみ機能するという明確な欠点があります。で使用される特定の状況に応じて変更する必要があります。
ああ、フラッシュの方がはるかに簡単だと思っているなら、信じてください。HTML/ CSSで軸を回転させる方法は非常に理にかなっています。フラッシュのような動作が必要な場合は、このライブラリを使用してください。
1これは、たとえば、モハメド・アリが彼の答えで行っていることです(彼のjsFiddletransformOffset
の関数)。
免責事項、私がこのようなことをしてからしばらく経ち、マトリックスの理解が非常に良くなることはありませんでした。間違いを見つけた場合は、指摘/修正してください。
Webkit の場合のみ、webkitConvertPointFromPageToNode
関数は不足している動作を処理します。
var point = webkitConvertPointFromPageToNode(
document.getElementById("outer"),
new WebKitPoint(event.pageX, event.pageY)
);
jsFiddle: http://jsfiddle.net/kB4ra/108/
他のブラウザーもカバーするには、この StackOverflow の回答で説明されている方法を使用できます: https://stackoverflow.com/a/6994825/638544
function coords(event, element) {
function a(width) {
var l = 0, r = 200;
while (r - l > 0.0001) {
var mid = (r + l) / 2;
var a = document.createElement('div');
a.style.cssText = 'position: absolute;left:0;top:0;background: red;z-index: 1000;';
a.style[width ? 'width' : 'height'] = mid.toFixed(3) + '%';
a.style[width ? 'height' : 'width'] = '100%';
element.appendChild(a);
var x = document.elementFromPoint(event.clientX, event.clientY);
element.removeChild(a);
if (x === a) {
r = mid;
} else {
if (r === 200) {
return null;
}
l = mid;
}
}
return mid;
}
var l = a(true),
r = a(false);
return (l && r) ? {
x: l,
y: r
} : null;
}
これには、マウスがターゲット要素の外にある場合は機能しないという欠点がありますが、カバーする領域を任意の量だけ拡張できるはずです (ただし、ウィンドウ全体をカバーすることを保証するのはかなり難しいでしょう)。大きい)。
jsFiddle: http://jsfiddle.net/kB4ra/122/
これは、mousemove イベントを追加することで #point に適用するように拡張できます。
$('#outer').mousemove(function(event){
var point = convertCoordinates(event, $("#outer"));
$("#point").css({left: point.x+1, top: point.y+1});
});
#point の x 座標と y 座標を 1px ずつ調整して、マウスの真下にならないように注意してください。そうしないと、#inner のドラッグがブロックされます。別の修正方法として、マウス イベントを検出するハンドラーを #point に追加し、#point のすぐ下にある要素にハンドラーを渡します (大きなページ要素で 2 回実行されないように、Propagation を停止します)。
jsFiddle: http://jsfiddle.net/kB4ra/123/
divを回転させないと、divはマウスに正確に従うように思えます。これはプラグインに問題がある可能性があります.ドラッグ可能な機能を正しくシミュレートできますか?
バグがありますが、これは基本的に必要なことを行います。ドラッグ イベント ハンドラーをバインドし、ui オブジェクトをインターセプトして、親要素のオフセット X と Y を使用するように変更します。X、Y、上、左などはすべてこれらのオブジェクトにあります。今日はもう少し時間があれば、もっと良い例をお見せしようと思います。幸運を!
これはjqueryライブラリの問題である可能性があります。または、内側のdivと外側のdivのzオーダー値を割り当てることでこれを確認できます。内側のdivにより大きな数値を与えるようにしてください。