46

たとえば、 -vendor-transform: rotate(40deg)長方形<div>にcss属性を設定すると、突然のドラッグとサイズ変更はすべて非常に奇妙で欠陥があります。

単純なjQueryUIの例を次に示します。http://jsfiddle.net/Ja4dY/1/

変換時にその長方形をドラッグまたはサイズ変更すると、長方形が上下にジャンプし、カーソルが正しい位置に留まらないことに気付くでしょう。実際のコードでは、サイズ変更とドラッグにカスタムコードを使用していますが、同じ問題が発生しました。

もちろん、「問題」は、要素の方向が変わることです。したがって、左が右、上が下、その中間になり、Javascriptコードは変換されないため、各方向を処理します。

だから、質問:変換/回転された要素をどのように補正できますか?

良いリソース/本/ブログも大歓迎です。

4

7 に答える 7

16

getComputedStyle()を使用して、要素に適用されている現在の変換行列を取得できます。これを使用して、現在のマウス位置を変換された空間内の位置に変換し、クリック/ドラッグイベントが要素の境界やコーナー内にあるかどうかを確認できます。このための良いリソース:

http://www.useragentman.com/blog/2011/01/07/css3-matrix-transform-for-the-mathematically-challenged/

http://www.eleqtriq.com/2010/05/css-3d-matrix-transformations/

ところで、あなたが経験しているように、これはコーディングにとって簡単ではありません。私たちは煎茶アニメーターのためにそれをしなければならなかった、そしてそれは獣だった。

于 2012-08-18T00:27:16.533 に答える
7

getBoundingClientRect()問題は、jQuery UI を使用するかどうかにかかわらず、要素をドラッグ可能にする関数が、要素の位置などを把握するためにネイティブ関数に大きく依存していることです。

回転などの CSS3 変換を適用すると、jQuery UI で使用されるgetBoundingClientRect()または同等の jQueryoffset()関数の値が期待どおりに機能しなくなり、回転後に要素のサイズが突然間違っているため、マウス ポインターの位置がめちゃくちゃになります。 .

これを修正するには、値を再計算する何らかのヘルパー関数を追加する必要があります。これには、jQuery UI のドラッグ可能で動作するモンキー パッチが用意されています。

同じパッチをカスタム コードで機能させる方法については何も言えませんが、おそらく何らかの方法でカスタム関数に統合する必要があり、それにはコーディングが必要であり、思いつくのはさらに困難です。見たことのないカスタムコードの箱から出してヘルパー関数として機能するものであり、これらの計算を行うことにかなり関与していることに注意してください。以下のコードを参照してください。

function monkeyPatch_mouseStart() {
     var oldFn = $.ui.draggable.prototype._mouseStart ;
     $.ui.draggable.prototype._mouseStart = function(event) {

            var o = this.options;

           function getViewOffset(node) {
              var x = 0, y = 0, win = node.ownerDocument.defaultView || window;
              if (node) addOffset(node);
              return { left: x, top: y };

              function getStyle(node) {
                return node.currentStyle || // IE
                       win.getComputedStyle(node, '');
              }

              function addOffset(node) {
                var p = node.offsetParent, style, X, Y;
                x += parseInt(node.offsetLeft, 10) || 0;
                y += parseInt(node.offsetTop, 10) || 0;

                if (p) {
                  x -= parseInt(p.scrollLeft, 10) || 0;
                  y -= parseInt(p.scrollTop, 10) || 0;

                  if (p.nodeType == 1) {
                    var parentStyle = getStyle(p)
                      , localName   = p.localName
                      , parent      = node.parentNode;
                    if (parentStyle.position != 'static') {
                      x += parseInt(parentStyle.borderLeftWidth, 10) || 0;
                      y += parseInt(parentStyle.borderTopWidth, 10) || 0;

                      if (localName == 'TABLE') {
                        x += parseInt(parentStyle.paddingLeft, 10) || 0;
                        y += parseInt(parentStyle.paddingTop, 10) || 0;
                      }
                      else if (localName == 'BODY') {
                        style = getStyle(node);
                        x += parseInt(style.marginLeft, 10) || 0;
                        y += parseInt(style.marginTop, 10) || 0;
                      }
                    }
                    else if (localName == 'BODY') {
                      x += parseInt(parentStyle.borderLeftWidth, 10) || 0;
                      y += parseInt(parentStyle.borderTopWidth, 10) || 0;
                    }

                    while (p != parent) {
                      x -= parseInt(parent.scrollLeft, 10) || 0;
                      y -= parseInt(parent.scrollTop, 10) || 0;
                      parent = parent.parentNode;
                    }
                    addOffset(p);
                  }
                }
                else {
                  if (node.localName == 'BODY') {
                    style = getStyle(node);
                    x += parseInt(style.borderLeftWidth, 10) || 0;
                    y += parseInt(style.borderTopWidth, 10) || 0;

                    var htmlStyle = getStyle(node.parentNode);
                    x -= parseInt(htmlStyle.paddingLeft, 10) || 0;
                    y -= parseInt(htmlStyle.paddingTop, 10) || 0;
                  }

                  if ((X = node.scrollLeft)) x += parseInt(X, 10) || 0;
                  if ((Y = node.scrollTop))  y += parseInt(Y, 10) || 0;
                }
              }
            }

                this.helper = this._createHelper(event);
                this._cacheHelperProportions();

                if($.ui.ddmanager)
                    $.ui.ddmanager.current = this;

                this._cacheMargins();

                this.cssPosition = this.helper.css("position");
                this.scrollParent = this.helper.scrollParent();

            this.offset = this.positionAbs = getViewOffset(this.element[0]);
                this.offset = {
                    top: this.offset.top - this.margins.top,
                    left: this.offset.left - this.margins.left
                };

                $.extend(this.offset, {
                    click: {
                        left: event.pageX - this.offset.left,
                        top: event.pageY - this.offset.top
                    },
                    parent: this._getParentOffset(),
                    relative: this._getRelativeOffset()
                });

                this.originalPosition = this.position = this._generatePosition(event);
                this.originalPageX = event.pageX;
                this.originalPageY = event.pageY;

                (o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));

                if(o.containment)
                    this._setContainment();

                if(this._trigger("start", event) === false) {
                    this._clear();
                    return false;
                }

                this._cacheHelperProportions();

                if ($.ui.ddmanager && !o.dropBehaviour)
                    $.ui.ddmanager.prepareOffsets(this, event);

                this.helper.addClass("ui-draggable-dragging");
                this._mouseDrag(event, true);

                if ( $.ui.ddmanager ) $.ui.ddmanager.dragStart(this, event);
                return true;
     };
 }
monkeyPatch_mouseStart();

そして、jQuery UI のドラッグ可能およびサイズ変更可能で期待どおりに動作することを示すFIDDLEがあります。

于 2012-08-20T20:40:37.737 に答える
5

私はこれを見つけました...これは、実際の例に加えて、情報、デモ、およびダウンロードリンクです。

jquery-ui-rotation-using-css-transform -> live-demo

彼は自分のライブラリを使用していますが、この主題に興味がある場合は、彼がどのようにそれを入手したかを読んで学ぶことができます.

乾杯と幸運。

Gmo.-

ところで、ウェブはロシア語ですが、グーグル翻訳で管理できます;-)

于 2012-08-20T07:12:07.887 に答える
3

jQuery のバグではありません。単にサポートされていません。jQuery UI ソース コードを確認すると、変換されたオブジェクトとページの違いを計算するために変換マトリックスを使用していないことがわかります。

あなたの例、そしておそらくすべてのjQ UIドラッグ実装は、JQ UIソースコードの2つのメソッドのこの問題の原因に悩まされています( jquery.ui.draggable.js ファイル v1.8.23 の約314行)。回転は要素の中心で行われるため、計算されたオフセットはオフセットの変化に関係ありません。

その変化が何であるかを計算する必要があります。ここに回避策があります。迅速で汚いです。アイデアは、変換された要素の境界ボックスの違いを確認することです。

ここでサンプルを確認してくださいhttp://jsfiddle.net/mjaric/9Nqrh/

最初の 2 つのローテーションの部分は無視します。これらは、コード行を最小限に抑えるために行われます。3 つ目は、計算された差の座標系の変換です。翻訳が実行された後、左と上にオフセットされます (フィルターの最初にあることに注意してください)。

最初の 2 つの回転フィルターを避けたい場合は、2D 回転の式を使用してコードを作成できます。

x' = x cos f - y sin f

y' = y cos f + x sin f

ここで、f は回転角度ですが、それほど単純ではなく、x と y の座標が x と比較される左上隅の初期角度が必要なため、元のバウンディング ボックスの対角を計算する必要があるコード行も多く含まれています。軸 (正の部分)。次に、xx' と yy' の変化を計算します。しかし、変更の兆候に関するいくつかの問題と、コーディング/デバッグには現在よりも時間がかかると予測しています。申し訳ありませんが、この投稿を読んだ後に何をすべきかを理解できると確信しています。

于 2012-08-24T00:00:52.390 に答える
1

cursorAt をオーバーライドすると見栄えが良くなります。

$("#foo").mousedown(function (e) { 
    var x = e.pageX - this.offsetLeft;
    var y = e.pageY - this.offsetTop;
    console.log(x);
    $("#foo").draggable("option", "cursorAt", {left: x, top:y});
});

更新されたフィドル: http://jsfiddle.net/johnkoer/Ja4dY/8/

</p>

于 2012-08-17T15:08:31.807 に答える
0

これは確かに、jQueryのバグのようです。div簡単な回避策は次のとおりです。サイズ変更可能なものをコンテナで囲みdivます。.draggable()を外側div.resizable()内側に設定しdivます。これは、Ubuntuで実行されているChromiumでは正常に機能しているようです。フィドルを参照してください

divボンネットの下で何が起こっているのかがわかるように、外側に色を付けました。

于 2012-08-23T17:09:00.043 に答える
0

JQuery ソリューションには興味がないとおっしゃいましたが、

  • 1つの解決策は次のとおりです。

    独自のドラッグおよびサイズ変更関数を作成することをお勧めします。回転したオブジェクトのサイズ変更とドラッグを処理して、上と左にその程度のサインとコサインを追加できます。

  • 別の解決策は次のとおりです。

    Raphael JS などのライブラリを使用して、変換、ドラッグ、およびサイズ変更するオブジェクトを作成できます。Raphael JS は svg を使用しています!

    Raphael JS の詳細については、

  • さらに別の解決策は次のとおりです。

    Raphael JS のようなライブラリを使用したくない場合は、JQuery で SVG を直接使用できます。

    SVG の詳細については、

詳細については今は書けません。明日、このソリューションを拡張します。

これらが今のところ役立つことを願っています。

于 2012-08-20T09:25:58.973 に答える