使用overflow-y:scroll时拖动子元素出容器的方法

10

我有一个容器,里面有一个列表。列表项可以被拖动,跟随鼠标移动。

该容器具有滚动功能:

overflow-y: scroll;

通过设置这个属性,Chrome会自动将overflow-x属性设置为'auto'。如果我设置overflow-x: visible,Chrome会忽略它。如果我设置overflow-x: hidden,那么显然项目会被裁剪。
当我将列表项拖出容器的左侧或上侧时,它会被裁剪到容器的边缘。如果我将其从右侧或底部边缘拖出,则容器会滚动以适应它。我希望该项能够在不被裁剪的情况下被拖出容器,并且不触发滚动。
考虑到容器必须设置为overflow-y: scroll,这反过来又强制Chrome设置overflow-x: auto,我是否可以实现这一点,还是不可能呢?
Codepen:http://codepen.io/Pedr/pen/azLWeY 注:我知道我可以通过使用填充来偏移容器(使容器的限制实际上超出其可见边缘),但在我的情况下,这不是一个选择。

$(function() {
  $('.Wrapper').mousemove(function(event){
    $('.Item').offset({left: event.pageX, top: event.pageY});
  });
})
html,
body {
  height: 100%;
}

.Wrapper {
  width: 100%;
  height: 100%;
  position: absolute;
}

.Container {
  background: grey;
  position: absolute;
  width: 50%;
  left: 25%;
  min-height: 100%;
  overflow-y: scroll;
  overflow-x: hidden; // Clips Item
  // If left at auto it will clip the item on the top and left edge and scroll if the item overlaps the bottom or right edge.
}

.Item {
  padding: 20px;
  background: red;
  position: absolute;
  width: 600px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="Wrapper">
  <div class="Container">
    <div class="Item">ITEM</div>
  </div>
</div>


7
哈哈,这个标题吸引了我的注意!“从容器中拖出一个孩子”...什么?哦,那个... - Wouter Thielen
记录一下,我不相信你应该在遇到不是你想要的答案时就给它们投反对票。 - deebs
@deebs 我只会给那些毫无用心的回答投下反对票。 - Undistraction
如果有答案,那么“零努力”是不可能的。我想你可以说“最小努力”……那更容易理解一些。无论哪种方式,你能够确定每个人付出的努力是非常了不起的。 - deebs
@deeps 我一定是真的惹你生气了,才会让你在一天后回来编辑你的评论。这不是一个人气比赛。如果一个答案显示出很少的努力(我认为用JS解决CSS问题需要很少的努力),或者不能以我满意的方式解决问题,那么我会打分因为我认为它没有用处。 - Undistraction
7个回答

5

ITEM设置为position fixed,以使其与其他内容分离

它的工作原理如下所示

$(function() {
  $('.Wrapper').mousemove(function(event){
      $('.Item').css('position', 'fixed');
      $('.Item').offset({left: event.pageX, top: event.pageY});
    });
})

请看以下代码片段:

$(function() {
  $('.Wrapper').mousemove(function(event){
      $('.Item').css('position', 'fixed');
      $('.Item').offset({left: event.pageX, top: event.pageY});
    });
})
.Wrapper {
  width: 100%;
  height: 100%;
  position: absolute;
}

.Container {
  background: grey;
  position: absolute;
  width: 50%;
  left: 25%;
  min-height: 100%;
  overflow-y: scroll;
  overflow-x: hidden; // Clips Item
  // If left at auto it will clip the item on the top and left edge and scroll if the item overlaps the bottom or right edge.
}

.Item {
  padding: 20px;
  background: red;
  position: absolute;
  width: 600px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="Wrapper">
  <div class="Container">
    <div class="Item">ITEM</div>
  </div>
</div>


3
这里是我的编辑:http://codepen.io/anon/pen/MYrxGJ 我所做的是将“Wrapper”的位置设置为相对定位,删除“Container”的位置CSS,并将其设置为“margin-left: 25%; margin-right: 25%;”(与“margin:0px auto;”产生相同效果)。这样,“Item” div的绝对定位就是相对于“Wrapper” div而不是“Container” div。

1
我相信这可以解决你的overflow-y问题。基本上,在.mousemove()上“关闭”overflow-y,并最初将项目元素设置在容器外部。您可以从容器中删除position: absolute,并使用以下内容:http://codepen.io/anon/pen/jEaRaz
$(function() {
  $('.Wrapper').mousemove(function(event){
  $('.Item').offset({left: event.pageX, top: event.pageY});
  $('.Container').css('overflow-y', 'hidden')
  });
})

1

个人而言,我会使用position:fixed - 它会将可拖动的元素从容器的渲染树中移除,因此对于容器来说,它与溢出没有任何关系,只会直接在窗口上绘制,没有滚动条或裁剪。

$('.Wrapper').on("mousedown", ".Item", function(event){
    $(event.target)
        .css('position', 'fixed')
        .on("mousemove", function(event){
            // Take into account offset within element
            $(this).offset({left: event.pageX, top: event.pageY});
        })
        .one("mouseup", function(event){
            // Finish dealing with element and clear position and event
            $(this)
                .off("mousemove")
                .css('position', '');
        })
});

-1
当选中项目时,您可以在容器外复制该项目,然后在放置后将其删除。

http://codepen.io/anon/pen/OPOMMp

此外,我会在包装器上隐藏溢出。
.Wrapper {
  width: 100%;
  height: 100%;
  position: absolute;
  overflow: hidden;
}

虽然这样做可以解决问题,但也是在回避它。不幸的是,我受到 JS 组件限制的约束,该组件不允许拖动的项目存在于原始容器之外。 - Undistraction

-1

我认为可以通过将大多数元素设为“in-layout”,并将可拖动的项设为“out-of-layout”来实现这一点,结果证明我是正确的。如果从您的包装器(wrapper)和容器(container)中删除 position: absolute(使它们呈现在布局中),然后给容器设置 margin-left: 25%,您仍然保持与以前相同的效果,但由于该项本身是 position: absolute,没有相对或绝对定位的父元素,因此它被定位为“out-of-layout”,这意味着它可以从该容器中出来。请参阅此示例:http://codepen.io/anon/pen/vEWGaa

(SO要求我提供带有codepen链接的代码,因此这是新的CSS):

html,
body {
  height: 100%;
}

.Wrapper {
  width: 100%;
  height: 100%;
}

.Container {
  background: grey;
  width: 50%;
  margin-left: 25%;
  min-height: 100%;
  overflow-y: scroll;
  overflow-x: hidden; // Clips Item
  // If left at auto it will clip the item on the top and left edge and scroll if the item overlaps the bottom or right edge.
}

.Item {
  padding: 20px;
  background: red;
  position: absolute;
  width: 600px;
}

编辑:此外,如果您在 body 上设置 overflow: hidden,则可以避免在拖动的项目超出屏幕时出现滚动条。


-1

试试这种方式,我已经克隆了可拖动的元素并将其添加到页面的主体部分。

JS

var cloneItem = $('.Item').clone().hide().appendTo("body");

http://codepen.io/nandhakumaru/pen/VYyMqr


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