jQuery Drag/Resize с помощью CSS Transform Scale

Я применяю CSS-преобразование (и специфичные для браузера -webkit, -o и т. Д.):

преобразование: матрица (0,5, 0, 0, 0,5, 0, 0);

в div с использованием плагинов jQuery draggable() и resizable() для дочерних элементов указанного div.

Проблема, с которой я столкнулся, заключалась в том, что при перетаскивании или изменении размера дочерних элементов изменения, сделанные jQuery, были "не синхронизированы" с мышью с коэффициентом, равным применяемой шкале.

Я нашел решение для stackru (хотя я тупо не закладывал его и теперь не могу найти его…), которое предлагало исправление плагинов, и оно работало чудесно. Это пошло по этой линии:

function monkeyPatch_mouseStart() {
  // don't really need this, but in case I did, I could store it and chain
  // var oldFn = $.ui.draggable.prototype._mouseStart ;
  $.ui.draggable.prototype._mouseStart = function(event) {

    var o = this.options;

    //Create and append the visible helper
    this.helper = this._createHelper(event);

    //Cache the helper size
    this._cacheHelperProportions();

    //If ddmanager is used for droppables, set the global draggable
    if($.ui.ddmanager)
      $.ui.ddmanager.current = this;

    /*
     * - Position generation -
     * This block generates everything position related - it's the core of draggables.
     */

    //Cache the margins of the original element
    this._cacheMargins();

    //Store the helper's css position
    this.cssPosition = this.helper.css("position");
    this.scrollParent = this.helper.scrollParent();

    //The element's absolute position on the page minus margins

    //PATCH CODE
    this.offset = this.positionAbs = getViewOffset(this.element[0]);
    //END

    this.offset = {
      top: this.offset.top - this.margins.top,
      left: this.offset.left - this.margins.left
    };

    $.extend(this.offset, {
      click: { //Where the click happened, relative to the element
        left: event.pageX - this.offset.left,
        top: event.pageY - this.offset.top
      },
      parent: this._getParentOffset(),
      relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
    });

    //Generate the original position
    this.originalPosition = this.position = this._generatePosition(event);
    this.originalPageX = event.pageX;
    this.originalPageY = event.pageY;

    //Adjust the mouse offset relative to the helper if 'cursorAt' is supplied
    if(o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt)){
    }

    //Set a containment if given in the options
    if(o.containment)
      this._setContainment();

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

    //Recache the helper size
    this._cacheHelperProportions();

    //Prepare the droppable offsets
    if ($.ui.ddmanager && !o.dropBehaviour)
      $.ui.ddmanager.prepareOffsets(this, event);

    this.helper.addClass("ui-draggable-dragging");
    this._mouseDrag(event, true); //Execute the drag once - this causes the helper not to be visible before getting its correct position

    //If the ddmanager is used for droppables, inform the manager that dragging has started (see #5003)
    if ( $.ui.ddmanager && $.ui.ddmanager.dragStart) $.ui.ddmanager.dragStart(this, event);

    return true;
  }
 }

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;
    }
  }
}
var isNumber = function(value) {
  return !isNaN(parseInt(value, 10));
};

Я сделал свои собственные изменения, такие как (вы можете видеть на 6-7 строках умножение движения на "коэффициент масштабирования"):

 $.ui.draggable.prototype._generatePosition = function(event) {
    var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
    var pageX = event.pageX;
    var pageY = event.pageY;
    //PATCH CODE
    if($(this.element[0]).hasClass('item')){
        pageY = this.originalPageY + ((pageY - this.originalPageY)*(1/$.viewbox.foreground.scale));
        pageX = this.originalPageX + ((pageX - this.originalPageX)*(1/$.viewbox.foreground.scale));
    }
    //END
    /*
     * - Position constraining -
     * Constrain the position to a mix of grid, containment.
     */

    if(this.originalPosition) { //If we are not dragging yet, we won't check for options

      if(this.containment) {
        if(event.pageX - this.offset.click.left < this.containment[0]) pageX = this.containment[0] + this.offset.click.left;
        if(event.pageY - this.offset.click.top < this.containment[1]) pageY = this.containment[1] + this.offset.click.top;
        if(event.pageX - this.offset.click.left > this.containment[2]) pageX = this.containment[2] + this.offset.click.left;
        if(event.pageY - this.offset.click.top > this.containment[3]) pageY = this.containment[3] + this.offset.click.top;
      }

      if(o.grid) {
        var top = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1];
        pageY = this.containment ? (!(top - this.offset.click.top < this.containment[1] || top - this.offset.click.top > this.containment[3]) ? top : (!(top - this.offset.click.top < this.containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top;

        var left = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0];
        pageX = this.containment ? (!(left - this.offset.click.left < this.containment[0] || left - this.offset.click.left > this.containment[2]) ? left : (!(left - this.offset.click.left < this.containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left;
      }
    }
    return {
      top: (
        pageY                               // The absolute mouse position
        - this.offset.click.top                         // Click offset (relative to the element)
        - this.offset.relative.top                        // Only for relative positioned nodes: Relative offset from element to offset parent
        - this.offset.parent.top                        // The offsetParent's offset without borders (offset + border)
        + ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ))
      ),
      left: (
        pageX                               // The absolute mouse position
        - this.offset.click.left                        // Click offset (relative to the element)
        - this.offset.relative.left                       // Only for relative positioned nodes: Relative offset from element to offset parent
        - this.offset.parent.left                       // The offsetParent's offset without borders (offset + border)
        + ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ))
      )
    };

  }

Огромное спасибо всем, кто это предложил.

Итак, мой вопрос! Кто-нибудь сталкивался с хорошим способом иметь перетаскиваемые / изменяемые размеры событий внутри масштабируемого элемента, который не требует исправления jQuery? Я гуглил, и это было лучшее решение, которое я мог найти. Кто-нибудь знает альтернативу jquery, которая, возможно, работает в этих условиях, с преобразованиями CSS?

Большое спасибо за любые отзывы.

13 ответов

Решение

Прошло много времени с тех пор, как был задан этот вопрос. Я нашел (на самом деле создал) ответ. Все, что для этого нужно - это установить обработчики обратного вызова. Не нужно редактировать jquery-ui!

Примечание: zoomScale в этом примере является глобальной переменной, и преобразование задается с помощью animate (с помощью jquery.transform.js), например так:

target.animate({
    transform: 'scale(' + zoomScale + ')'
});

Взгляните на это:

transform scale () исправление для изменяемого размера:

$(this).resizable({
    minWidth: -(contentElem.width()) * 10,  // these need to be large and negative
    minHeight: -(contentElem.height()) * 10, // so we can shrink our resizable while scaled
    resize: function(event, ui) {

        var changeWidth = ui.size.width - ui.originalSize.width; // find change in width
        var newWidth = ui.originalSize.width + changeWidth / zoomScale; // adjust new width by our zoomScale

        var changeHeight = ui.size.height - ui.originalSize.height; // find change in height
        var newHeight = ui.originalSize.height + changeHeight / zoomScale; // adjust new height by our zoomScale

        ui.size.width = newWidth;
        ui.size.height = newHeight;

    }
});

transform scale () исправление для перетаскиваемого объекта:

$(this).draggable({
    handle: '.drag-handle',
    start: function(event, ui) {
        ui.position.left = 0;
        ui.position.top = 0;
    },
    drag: function(event, ui) {

        var changeLeft = ui.position.left - ui.originalPosition.left; // find change in left
        var newLeft = ui.originalPosition.left + changeLeft / (( zoomScale)); // adjust new left by our zoomScale

        var changeTop = ui.position.top - ui.originalPosition.top; // find change in top
        var newTop = ui.originalPosition.top + changeTop / zoomScale; // adjust new top by our zoomScale

        ui.position.left = newLeft;
        ui.position.top = newTop;

    }
});

Дайте мне знать, если вы найдете какие-либо проблемы или дальнейшие улучшения по этому вопросу.:)

Ссылка: jQuery-UI изменяемый размер / перетаскивание с помощью transform: scale() set

Я пытался исправить трансформацию scale() для изменяемого размера, размещенного gungfoo на элементе, отображаемом в 10% от его реального размера, и метод не работал. Курсор все еще перемещался от элемента во время изменения размера.

Я изменил последние две строки метода resizeFix, чтобы напрямую обновить ширину и высоту элемента, и это решило мою проблему.

function resizeFix(event, ui) {

    var changeWidth = ui.size.width - ui.originalSize.width; // find change in width
    var newWidth = ui.originalSize.width + changeWidth / zoomScale; // adjust new width by our zoomScale

    var changeHeight = ui.size.height - ui.originalSize.height; // find change in height
    var newHeight = ui.originalSize.height + changeHeight / zoomScale; // adjust new height by our zoomScale

    ui.originalElement.width(newWidth);
    ui.originalElement.height(newHeight);
}

Мой собственный "ответ" в этом случае состоял в том, чтобы адаптировать jQuery UI, перетаскиваемый для создания отдельного взаимодействия, называемого "traggable".

https://github.com/paullth/JS-libs

http://jsfiddle.net/paul_herve/ws27C/4/

Хотелось бы услышать о любых альтернативах...

У меня была похожая проблема с преобразованием, и я решил ее с помощью CSS:

transform-origin

http://www.w3schools.com/cssref/css3_pr_transform-origin.asp

Ты это пробовал? возможно это поможет.

Другой подход - добавить плагин, который компенсирует преобразование (не забудьте добавить "transform: true" к инициализации плагина.

Необходимо передать ui.draggable через обратную матрицу преобразования, чтобы поместить элемент в нетрансформированное пространство, которое браузер позже преобразует на дисплее.

Для "перетаскиваемого" у меня сработало следующее ( jqueryui 1.10) (матричный расчет, который я взял из jquery.panzoom):

var Matrix = function(a, b, c, d, e, f, g, h, i) {
    if ($.type(a) === 'array') {
        this.elements = [
            +a[0], +a[2], +a[4],
            +a[1], +a[3], +a[5],
                0,     0,     1
        ];
    } else {
        this.elements = [
            a, b, c,
            d, e, f,
            g || 0, h || 0, i || 1
        ];
    }
};

Matrix.prototype = {
    /**
     * Multiply a 3x3 matrix by a similar matrix or a vector
     * @param {Matrix|Vector} matrix
     * @return {Matrix|Vector} Returns a vector if multiplying by a vector
     */
    x: function(matrix) {
        var isVector = matrix instanceof Vector;

        var a = this.elements,
            b = matrix.elements;

        if (isVector && b.length === 3) {
            // b is actually a vector
            return new Vector(
                a[0] * b[0] + a[1] * b[1] + a[2] * b[2],
                a[3] * b[0] + a[4] * b[1] + a[5] * b[2],
                a[6] * b[0] + a[7] * b[1] + a[8] * b[2]
            );
        } else if (b.length === a.length) {
            // b is a 3x3 matrix
            return new Matrix(
                a[0] * b[0] + a[1] * b[3] + a[2] * b[6],
                a[0] * b[1] + a[1] * b[4] + a[2] * b[7],
                a[0] * b[2] + a[1] * b[5] + a[2] * b[8],

                a[3] * b[0] + a[4] * b[3] + a[5] * b[6],
                a[3] * b[1] + a[4] * b[4] + a[5] * b[7],
                a[3] * b[2] + a[4] * b[5] + a[5] * b[8],

                a[6] * b[0] + a[7] * b[3] + a[8] * b[6],
                a[6] * b[1] + a[7] * b[4] + a[8] * b[7],
                a[6] * b[2] + a[7] * b[5] + a[8] * b[8]
            );
        }
        return false; // fail
    },
    /**
     * Generates an inverse of the current matrix
     * @returns {Matrix}
     */
    inverse: function() {
        var d = 1 / this.determinant(),
            a = this.elements;
        return new Matrix(
            d * ( a[8] * a[4] - a[7] * a[5]),
            d * (-(a[8] * a[1] - a[7] * a[2])),
            d * ( a[5] * a[1] - a[4] * a[2]),

            d * (-(a[8] * a[3] - a[6] * a[5])),
            d * ( a[8] * a[0] - a[6] * a[2]),
            d * (-(a[5] * a[0] - a[3] * a[2])),

            d * ( a[7] * a[3] - a[6] * a[4]),
            d * (-(a[7] * a[0] - a[6] * a[1])),
            d * ( a[4] * a[0] - a[3] * a[1])
        );
    },
    /**
     * Calculates the determinant of the current matrix
     * @returns {Number}
     */
    determinant: function() {
        var a = this.elements;
        return a[0] * (a[8] * a[4] - a[7] * a[5]) - a[3] * (a[8] * a[1] - a[7] * a[2]) + a[6] * (a[5] * a[1] - a[4] * a[2]);
    }
};

var Vector = function (x, y, z) {
    this.elements = [ x, y, z ];
};

/**
 * Get the element at zero-indexed index i
 * @param {Number} i
 */
Vector.prototype.e = Matrix.prototype.e = function(i) {

    if( this.elements[ i ] != undefined ){
        return this.elements[ i ];    
    }

    return this.elements;
};    

$.ui.plugin.add("draggable", "transform", {

    start: function( event, ui ) {

        if(!$(this).data('ui-draggable')){
            return false;
        }            

        var inst = $(this).data("ui-draggable");

        inst.matrix = new Matrix(function(matrix){

            var rmatrix = new RegExp(
                    '^matrix\\(' +
                    '(\\-?[\\d\\.e]+)' + '\\,?\\s*' +
                    '(\\-?[\\d\\.e]+)' + '\\,?\\s*' +
                    '(\\-?[\\d\\.e]+)' + '\\,?\\s*' +
                    '(\\-?[\\d\\.e]+)' + '\\,?\\s*' +
                    '(\\-?[\\d\\.e]+)' + '\\,?\\s*' +
                    '(\\-?[\\d\\.e]+)' + '\\)$'
            );                

            var matrix = rmatrix.exec( matrix );
            if (matrix) {
                matrix.shift();
            }
            return matrix || [ 1, 0, 0, 1, 0, 0 ];

        }([$(this).parents('[style*="transform"]').css('transform')]));            
    },
    drag: function( event, ui ) {

        if(!$(this).data('ui-draggable')){
            return false;
        }            

        var inst = $(this).data("ui-draggable");

        var t_pos = inst.matrix.inverse().x(new Vector(ui.position.left, ui.position.top, 0));

        ui.position.left = t_pos.e(0);
        ui.position.top = t_pos.e(1);                   

        if(inst.options.grid) {
            ui.position.left = ui.position.left - ui.position.left % inst.options.grid[0];
            ui.position.top  = ui.position.top - ui.position.top % inst.options.grid[1];                
        }

        if( inst.containment ){

            if( ui.position.left < inst.containment[0] ){
                ui.position.left = inst.containment[0];
            }

            if( ui.position.left > inst.containment[2] ){
                ui.position.left = inst.containment[2];
            }                

            if( ui.position.top < inst.containment[1] ){
                ui.position.top = inst.containment[1];
            }  

            if( ui.position.top > inst.containment[3] ){
                ui.position.top = inst.containment[3];
            }
        }
    },     
});

Главный ответ работал на меня, пока я не нашел сбой на перетаскиваемом:(

Когда сама защитная оболочка также масштабируется:

  • он не может быть полностью перетащен в свою ячейку содержания, если масштаб < 1
  • при масштабировании> 1 его можно перетащить за пределы защитной коробки

К счастью, я нашел решение здесь

Давно удивляюсь почему @GungFoo Решение не работает для меня для Jquery Resizable, но некоторые люди сказали, что это сработало. Наконец, я обнаружил, что есть 4 пункта для использования jQuery Draggable и Resizable с CSS Transform Scale:

  1. Используя решения @GungFoo!
  2. Использование отдельных div для перетаскивания и изменения размера!
  3. Использование правильного CSS Transform Origin для divs!
  4. Используя правильное направление CSS для divs!

Проверьте некоторые из этих проблем:

function resizeDiv(event, ui) {
        debugger;
        var changeWidth = ui.size.width - ui.originalSize.width; 
        var newWidth = ui.originalSize.width + changeWidth / 4; 

        var changeHeight = ui.size.height - ui.originalSize.height;
        var newHeight = ui.originalSize.height + changeHeight / 4; 

        ui.size.width = newWidth;
        ui.size.height = newHeight;

};
$('#box').resizable({
    minWidth: -($(this).width()) * 10,
    minHeight: -($(this).height()) * 10, 
    resize: resizeDiv
});

$('#box2').resizable({
    minWidth: -($(this).width()) * 10,
    minHeight: -($(this).height()) * 10, 
    resize: resizeDiv
});

$('#box3').resizable({
    minWidth: -($(this).width()) * 10,
    minHeight: -($(this).height()) * 10, 
    resize: resizeDiv
});

$('#box4').resizable({
    minWidth: -($(this).width()) * 10,
    minHeight: -($(this).height()) * 10, 
    resize: resizeDiv
});
.box{
  position:absolute;
  width:30px;
  height:30px;
  border:1px solid black;
  font-size:3pt;
  overflow:hidden;
  -webkit-transform:scale(4);
  direction:ltr;
}
#box{
  transform-origin: top left;
  top: 0;
  left:0;
}
#box2{
  transform-origin: bottom left;
  top: 250px;
  left:0;
}
#box3{
  direction:rtl;
  left: 250px;
  top: -10px;
}
<link href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.10.3/themes/smoothness/jquery-ui.css" rel="stylesheet" type="text/css" />
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
     
    <script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.9.2/jquery-ui.min.js"></script>

<div id= 'box' class="box"> 
True styles
</div>

<div id= 'box2' class="box"> 
Bad transform-orgin
</div>

<div id= 'box3' class="box"> 
Bad direction
</div>

Спасибо @Guy;)

Я обнаружил, что могу просто обернуть масштабированный элемент другим div и установить вместо него перетаскиваемый элемент.

Вот мое решение. Часть кода, размещенного выше, не работает для меня.

У меня есть перетаскиваемое изображение, и я применяю CSS трансформацию, вращение и масштабирование к этому изображению. После того как я масштабирую / поверну его, положение будет отключено при перетаскивании. Чтобы исправить это, я вычисляю разницу заданных значений от остановки до начала, и при перетаскивании применяю новое заданное значение с учетом разницы.

var $img = $("#my-image-id");

$img.posLeft  = 0;
$img.posTop  = 0;
$img.diffLeft  = 0;
$img.diffTop  = 0;

$img.draggable({
  start: function( event, ui ) {
    //check the difference from start to stop setpoints
    $img.diffLeft  = $img.posLeft-ui.position.left;
    $img.diffTop  = $img.posTop-ui.position.top;
    //console.log('start x: '+Math.floor(ui.position.left)+' y: '+Math.floor(ui.position.top));
    //console.log('diff x: '+Math.floor($img.posLeft-ui.position.left)+' y: '+Math.floor($img.posTop-ui.position.top));
  },
  drag: function( event, ui ) {
    //fix the offset bug that is applied after CSS transform, to do that just add the value difference
    ui.position.left = ui.position.left+$img.diffLeft;
    ui.position.top = ui.position.top+$img.diffTop;
    //console.log('drag x: '+ui.position.left+' y: '+ui.position.top);
  },
  stop: function( event, ui ) {
    //save the last applied setpoints
    $img.posLeft = ui.position.left;
    $img.posTop = ui.position.top;
    //console.log('stop x: '+Math.floor(ui.position.left)+' y: '+Math.floor(ui.position.top));
  }
});

Трюк с CSS-преобразованием исправляет ошибку только для масштаба. Вращение должно быть вокруг центра, поэтому вы хотите оставить значение по умолчанию 50% 50%.

У меня была та же проблема, и самый простой способ для меня - НЕ использовать перетаскиваемую функциональность jquery-ui, поскольку она не поддерживает свойства преобразования CSS3.

Для меня действительно хорошо было реализовать собственную перетаскиваемую функциональность: http://css-tricks.com/snippets/jquery/draggable-without-jquery-ui/

Я знаю, что это не решит вашу проблему на 100%, так как вы все еще хотите использовать перетаскиваемые функции jquery-ui, но это может помочь другим.

Ни одно из этих решений не сработало для меня, так как, например, я не смог преобразовать родителя перетаскиваемых объектов - трансформировались только сами перетаскиваемые объекты.

Вот как я исправил эту проблему:

$('.draggable').draggable(
{
    cancel: '.restrict-drag',
    scroll: false,
    containment: '#contain',

    start: function(event, ui) 
    {
        ui.position.left = 0;
        ui.position.top = 0;
    },

    drag: function(event, ui) 
    {
        ui.position.left = ui.position.left - ($(event.target).width() * Zoom);
        ui.position.top = ui.position.top - ($(event.target).height() * Zoom);
    }
});

Масштаб по умолчанию 0.

Чтобы масштабировать draggables, я сделал следующее:

function changeZoom(zoom)
{
    $('.draggable').each(function() { $(this).css('transform-origin', '50% 50%'); $(this).css('transform', 'scale(' + zoom + ')'); });
    Zoom = zoom; // Global Zoom-variable
}

И все, кажется, работает хорошо.

Для другого угла изменения размера

$('.rect-item').resizable({
        handles: 'n,e,s,w,ne,se,sw,nw',
        resize: (e, ui) => {
          const zoomScale = Your scale;
          const changeWidth = ui.size.width - ui.originalSize.width; // find change in width
          const newWidth = ui.originalSize.width + changeWidth / zoomScale; // adjust new width by our zoomScale

          const changeHeight = ui.size.height - ui.originalSize.height; // find change in height
          const newHeight = ui.originalSize.height + changeHeight / zoomScale; // adjust new height by our zoomScale

          ui.size.width = newWidth;
          ui.size.height = newHeight;

          // here
          const posOrigin = ui.originalPosition;
          if (posOrigin.left !== ui.position.left) {
            ui.position.left = posOrigin.left - changeWidth / zoomScale;
          }
          if (posOrigin.top !== ui.position.top) {
            ui.position.top = posOrigin.top - changeHeight / zoomScale;
          }

        }
      });

Я бы добавил это как комментарий к принятому ответу от Гунг Фу, но у меня нет представителя, чтобы комментировать.

Я обнаружил, что ответы Гунга отлично сработали, однако исправление с изменением размера работало только при перетаскивании из правого нижнего угла. У меня также есть маркеры на трех других углах, и я обнаружил, что элемент сместится, поэтому мне пришлось добавить исправление из перетаскиваемого в изменяемый размер функций.

Может быть, есть лучший способ, или я что-то упустил, но я обнаружил, что измененный изменяемый размер ниже работает для меня со всех ручек:

$(this).resizable({
    minWidth: -(contentElem.width()) * 10,  // these need to be large and negative
    minHeight: -(contentElem.height()) * 10, // so we can shrink our resizable while scaled

    // adjust the initial position to accomodate for the scale
    start: function(event, ui){
        ui.position.left = Math.round(ui.position.left/zoomScale);
        ui.position.top = Math.round(ui.position.top/zoomScale);
        ui.originalPosition.left = ui.position.left;
        ui.originalPosition.top = ui.position.top;
    },

    resize: function(event, ui) {

        var changeWidth = ui.size.width - ui.originalSize.width; // find change in width
        var newWidth = ui.originalSize.width + changeWidth / zoomScale; // adjust new width by our zoomScale

        var changeHeight = ui.size.height - ui.originalSize.height; // find change in height
        var newHeight = ui.originalSize.height + changeHeight / zoomScale; // adjust new height by our zoomScale

        ui.size.width = newWidth;
        ui.size.height = newHeight;

        // if the position is changed by a NW,NE,SW handle resize adjust for the scale
        var changeWidth = ui.size.width - ui.originalSize.width; // find change in width
        var newWidth = ui.originalSize.width + changeWidth / zoomScale; // adjust new width by our zoomScale

        var changeHeight = ui.size.height - ui.originalSize.height; // find change in height
        var newHeight = ui.originalSize.height + changeHeight / zoomScale; // adjust new height by our zoomScale

        ui.size.width = newWidth;
        ui.size.height = newHeight;

    }
});
Другие вопросы по тегам