Jquery перетаскивается с проблемой масштабирования

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

Чтобы решить эту проблему, я попытался сделать некоторую математику относительно положения перетаскиваемого компонента, но кажется, что даже если визуально его исправить, "истинная" позиция не пересчитывается.

Вот некоторый код, чтобы объяснить лучше:

var zoom = Math.round((parseFloat($("body").css("zoom")) / 100)*10)/10;

var x = $(this).data('draggable').position;
$(this).data('draggable').position.left = Math.round(x.left/zoom);
$(this).data('draggable').position.top = Math.round(x.top/zoom);

Любая помощь будет принята с благодарностью

6 ответов

Потребовалось много времени и усилий, чтобы это исправить, но, наконец, у меня есть решение, которое работает.

Это решение работает как для Firefox, так и для IE. #canvas - это div, содержащий перетаскиваемый объект. Обратите внимание, что мы должны убедиться, что элементы остаются внутри холста вручную.

Это также работает, если холст имеет другой уровень масштабирования, чем остальная часть страницы.

var pointerX;
var pointerY;
$(c).draggable({
  start : function(evt, ui) {
    pointerY = (evt.pageY - $('#canvas').offset().top) / zoom - parseInt($(evt.target).css('top'));
    pointerX = (evt.pageX - $('#canvas').offset().left) / zoom - parseInt($(evt.target).css('left'));
  },
  drag : function(evt, ui) {
    var canvasTop = $('#canvas').offset().top;
    var canvasLeft = $('#canvas').offset().left;
    var canvasHeight = $('#canvas').height();
    var canvasWidth = $('#canvas').width();

    // Fix for zoom
    ui.position.top = Math.round((evt.pageY - canvasTop) / zoom - pointerY); 
    ui.position.left = Math.round((evt.pageX - canvasLeft) / zoom - pointerX); 

    // Check if element is outside canvas
    if (ui.position.left < 0) ui.position.left = 0;
    if (ui.position.left + $(this).width() > canvasWidth) ui.position.left = canvasWidth - $(this).width();  
    if (ui.position.top < 0) ui.position.top = 0;
    if (ui.position.top + $(this).height() > canvasHeight) ui.position.top = canvasHeight - $(this).height();  

    // Finally, make sure offset aligns with position
    ui.offset.top = Math.round(ui.position.top + canvasTop);
    ui.offset.left = Math.round(ui.position.left + canvasLeft);
  }
});
var zoom = $('#canvas').css('zoom');    
$('#dragme').draggable({
        drag: function(evt,ui)
        {
             var factor = (1 / zoom) -1);

             ui.position.top += Math.round((ui.position.top - ui.originalPosition.top) * factor);
             ui.position.left += Math.round((ui.position.left- ui.originalPosition.left) * factor);    
        }                 
    });

Для дальнейшего использования - если кто-то когда-либо столкнется с той же проблемой - аналогичный вопрос + рабочий ответ можно найти здесь.

Если CSS Zoom выполняется специально для html тела, это очень легко исправить, но для этого нужно изменить источник. Для некоторых это не пойдет, но я все равно выложу решение здесь.

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

Так что включите это:

    return {
        top: (

            // The absolute mouse position
            pageY -

            // Click offset (relative to the element)
            this.offset.click.top -

            // Only for relative positioned nodes: Relative offset from element to offset parent
            this.offset.relative.top -

            // The offsetParent's offset without borders (offset + border)
            this.offset.parent.top +
            ( this.cssPosition === "fixed" ?
                -this.offset.scroll.top :
                ( scrollIsRootNode ? 0 : this.offset.scroll.top ) )
        )/ ,
        left: (

            // The absolute mouse position
            pageX -

            // Click offset (relative to the element)
            this.offset.click.left -

            // Only for relative positioned nodes: Relative offset from element to offset parent
            this.offset.relative.left -

            // The offsetParent's offset without borders (offset + border)
            this.offset.parent.left +
            ( this.cssPosition === "fixed" ?
                -this.offset.scroll.left :
                ( scrollIsRootNode ? 0 : this.offset.scroll.left ) )
        )
    };

в

    var zoomLevel = parseFloat($('body').css("zoom") || "1.0");

    return {
        top: (

            // The absolute mouse position
            pageY -

            // Click offset (relative to the element)
            this.offset.click.top -

            // Only for relative positioned nodes: Relative offset from element to offset parent
            this.offset.relative.top -

            // The offsetParent's offset without borders (offset + border)
            this.offset.parent.top +
            ( this.cssPosition === "fixed" ?
                -this.offset.scroll.top :
                ( scrollIsRootNode ? 0 : this.offset.scroll.top ) )
        ) / zoomLevel,
        left: (

            // The absolute mouse position
            pageX -

            // Click offset (relative to the element)
            this.offset.click.left -

            // Only for relative positioned nodes: Relative offset from element to offset parent
            this.offset.relative.left -

            // The offsetParent's offset without borders (offset + border)
            this.offset.parent.left +
            ( this.cssPosition === "fixed" ?
                -this.offset.scroll.left :
                ( scrollIsRootNode ? 0 : this.offset.scroll.left ) )
        ) / zoomLevel
    };

Это все. Я предлагаю сохранить его под определенным именем, чтобы было легко узнать, что он был изменен. Например: jquery-ui.ZOOMFIX.js

Я использовал jquery-ui.js файл из следующего пакета: https://jqueryui.com/resources/download/jquery-ui-1.12.1.zip

Я боролся с этим в течение нескольких часов. У меня была сетка, где я начал с масштабирования, установив размер шрифта (125% и т. Д. На контейнере). Это работало хорошо, пока я не вошел в изображения, которые не масштабируются с сеткой.

Думал, что вместо этого использовал бы увеличение, и это сработало блестяще. Затем я изменил с помощью draggable/droppable, не масштабируясь с ним, хм.. Потратил несколько часов, пытаясь уничтожить и заново запустить объекты jqueryUI, но ничего не получалось.

Затем, наконец, я понял, что могу использовать комбинацию размера шрифта для масштабирования сетки и css-zoom для изображений. Теперь все работает, и я могу перетаскивать с тем же экземпляром jQueryUI.

Надеюсь, что этот подход помогает кому-то еще.:-)

Принимаете ли вы во внимание положение прокрутки, поля и отступы? Такие как:

x.left + 
parseInt($(this).css('margin-left')) + 
parseInt($(this).css('padding-left')) + 
parseInt($(this).parent().scrollLeft());

x.top + 
parseInt($(this).css('margin-top')) + 
parseInt($(this).css('padding-top')) + 
parseInt($(this).parent().scrollTop());

Затем настройте значение масштабирования по мере необходимости?

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