如何强制jQuery resizable使用百分比?

12

我正在尝试使用 jQuery resizable 调整我的 div 大小,我已经做得很好了,但是在 stop 事件之后,jQuery UI 会将我的 % 值恢复为像素值。

我在这里有一个工作示例:http://jsfiddle.net/totszwai/j60h38fy/5/

当您第一次拖动 "current" 容器时,它会正确地计算所有值,但在 stop 事件之后,jQuery UI 会更新 % 并将其更改回像素... 所以下次再次拖动它时,% 就丢失了。

如何强制 jQuery 将宽度值设置为 %?技术上我可以使用 setTimeout 这样的东西,但那太丑陋了。

而且我不想通过操纵像素来解决问题,因为我可以在设置中添加 n-个 div,并且带 % 的代码应该适用于 n-个 div。

如果您查看我的 "neighbor" div,% 就保留在那里,只有 "current" 被覆盖了。我也尝试直接操作 ui.element 以及将 ui.size.width 设置为我的 %,但都没有起作用。

更新:一种解决方法是在每次 stop 事件时存储数据,并永远不再在 start 中检查它,但是这仍然无法解决 stop 返回不正确的像素值的问题。请参见更新后的 jsFiddle:http://jsfiddle.net/totszwai/j60h38fy/6/

如果 jQuery resizable 只接受我的 % 值,一切都会按预期工作。

已解决: 好的,我接受了apaul34208的答案,因为我确实询问了如何使用%。然而,要解决我最初想要解决的问题,我最终使用像素。如果下面的答案有帮助,请给它点赞,点击这里查看。

4个回答

10
我遇到了相同的问题,所选的解决方案对我不起作用,因为我需要将其推广至任意数量的列。 此外,codenamezero的答案没有处理原始问题要求使用宽度百分比的事实。
在我的情况下,使用宽度百分比是必不可少的,因为我正在实现一个表格编辑器,保存的表格必须根据呈现位置动态改变大小。
因此,我想出了这个解决方案,它的工作方式类似于codenamezero的解决方案,但最终更改的宽度被设置为百分比:
http://jsfiddle.net/genpsire/4mywcm1x/14/
$(document).ready(function () {

    var container = $(".wrapper");
    var numberOfCol = 3;
    $(".test").css('width', 100/numberOfCol +'%');

    var sibTotalWidth;
    $(".test").resizable({
        handles: 'e',
        start: function(event, ui){
            sibTotalWidth = ui.originalSize.width + ui.originalElement.next().outerWidth();
        },
        stop: function(event, ui){     
            var cellPercentWidth=100 * ui.originalElement.outerWidth()/ container.innerWidth();
            ui.originalElement.css('width', cellPercentWidth + '%');  
            var nextCell = ui.originalElement.next();
            var nextPercentWidth=100 * nextCell.outerWidth()/container.innerWidth();
            nextCell.css('width', nextPercentWidth + '%');
        },
        resize: function(event, ui){ 
            ui.originalElement.next().width(sibTotalWidth - ui.size.width); 
        }
    });
});

请选用这个解决方案,以免其他人像我一样在尝试将apaul34208的解决方案推广到n列的情况时浪费他们的时间。(译者注:apaul34208指的是一位程序员)

1
容器不一定要是表格,因此这也适用于 div。如果您正在使用 <table> 显示表格数据,则可以使用。我同意 <table> 不应该用于格式化页面。在我的情况下,我们正在显示表格数据。 - genspire
谢谢,好的解决方案!它无法通过shift-drag测试(用于纵横比缩放),但是所有使用.resizable()的其他答案也都无法通过(因为在保持shift键时调整大小会改变高度)。然而,这很容易通过在resizablestop事件中执行以下操作来修复:$(this).css('height','')。我fork了你的fiddle,并在此处添加了几个修复和改进:http://jsfiddle.net/8auwgazu/ - nothingisnecessary

2
在又一天的努力后,我终于找到了完美的解决方案。事实上,它比我想象中要简单得多,只是我过于复杂化了问题。
我试图获取 ui.helper 的动态大小,并尝试在 stop 时操作相邻元素。但我真正关心的是 this 元素的宽度及其直接相邻元素的宽度...所以我最终做了以下操作:
    start: function (event, ui) {
        // just remember the total width of self + neighbor
        this.widthWithNeighbor = 
            ui.originalSize.width + ui.element.next().outerWidth();
    },
    resize: function (event, ui) {
        // then simply subtract it!
        ui.element.next().width(this.widthWithNeighbor - ui.size.width);
    },
    stop: function(event, ui) {
        // clean up, is this needed?
        delete this.widthWithNeighbor;
    }

这个解决方案适用于并排放置的 n+1 个 DIV。如果将宽度和高度互换,则也可以用于垂直堆叠的 DIV。:)
祝万事如意! 工作中的 jsFiddle 注意:jQuery-UI 中的 ghost 和 animate 选项仍然存在与之前相同的问题。这是 jQuery 2.0.2 和 jQuery-UI 1.10.3 的情况,希望他们很快就会修复它。

我以为你在尝试使用百分比来使可调整大小的元素工作,我是否误解了问题?你的答案似乎在Firefox和Chrome中都返回像素宽度。 - apaul
嗯...是的,你说得对。最初我想让它使用%,因为我找不到一种正确调整DIV的方法。如果您能将其修订为适用于n+1个DIV,那我想我可以接受您的答案。 - codenamezero
我今天稍后再试一次。 - apaul
2
我认为这样的东西应该可以做到,但还需要大量的工作:http://jsfiddle.net/apaul34208/bqr7eL1c/5/ - apaul
呵呵...这样不行,因为你仍然假设窗口的宽度,所以如果有嵌套元素,它就不起作用。在我的示例中,我使用像素,能够将我的“组件”包含在另一个“组件”中。是的,使用%来实现我想要实现的东西非常棘手,而且可能不值得时间,因为使用像素似乎更容易和更合适。但是,我认为仍然可以做到,但我们需要保存/注意所有的%并使用存储的%计算它们... - codenamezero
我会接受你的答案,感谢你帮助我。 :) - codenamezero

2
我不得不移除ghost和animate,并微调了你的CSS,display: flex;似乎导致了意外的结果,但我想我可能已经找到了一个简单的解决方案:

工作示例

$(document).ready(function() {

  $(".test").resizable({
    handles: 'e',
    resize: function() {
      $('.test:first-of-type').css('width', $('.test:first-of-type').outerWidth() * 100 / $(window).innerWidth() + '%');
      $('.test:nth-of-type(2)').css('width', 100 - ($('.test:first-of-type').outerWidth() * 100 / $(window).innerWidth()) + '%');

    }

  });
});

* {
  -moz-box-sizing: border-box;
  box-sizing: border-box;
}
html,
body {
  height: 100%;
  width: 100%;
  padding: 0;
  margin: 0;
}
.wrapper {
  height: 100%;
  width: 100%;
}
.test {
  float: left;
  border: 3px solid red;
}

<div class="wrapper">
  <div class="test" style="width: 50%; height: 200px;">current</div>
  <div class="test" style="width: 50%; height: 200px;">neighbor</div>
</div>

1

我知道我的答案不是“良好的实践”,因为它要求您自定义一个经常更新的库,但它解决了我的问题: 在jquery-ui.js文件中更改“resize”函数以按您希望的方式操作宽度。 在我的情况下,我需要resize完全忽略宽度,所以我注释掉了“width”更改:

resize: function( event, ui ) {
        var that = $( this ).resizable( "instance" ),
            o = that.options,
            os = that.originalSize,
            op = that.originalPosition,
            delta = {
                height: ( that.size.height - os.height ) || 0,
    ----------->//width: ( that.size.width - os.width ) || 0,
                top: ( that.position.top - op.top ) || 0,
                left: ( that.position.left - op.left ) || 0
            };

            $( o.alsoResize ).each( function() {
                var el = $( this ), start = $( this ).data( "ui-resizable-alsoresize" ), style = {},
                    css = el.parents( ui.originalElement[ 0 ] ).length ?
        ----------------->[ /*"width",*/ "height" ] :
                            [ "width", "height", "top", "left" ];

                $.each( css, function( i, prop ) {
                    var sum = ( start[ prop ] || 0 ) + ( delta[ prop ] || 0 );
                    if ( sum && sum >= 0 ) {
                        style[ prop ] = sum || null;
                    }
                } );

                el.css( style );
            } );
    },

1
是的,这样做可能有效,但从我的经验来看,对第三方库进行黑客攻击很难维护和升级以供未来使用。您还可能引入影响其他松散相关代码的模糊错误,使其成为跟踪、修补/修复/黑客攻击的噩梦。 - codenamezero

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接