不使用绝对定位来定位元素

3
我有以下要求:
  • 一个填充文本的<p>元素
  • 一个<img>元素
  • 图像的位置坐标(x/y)
现在我想根据服务器端计算出的x和y像素值来定位<img>元素。我不想使用position:absolute,因为我还希望<p>元素内部的文本自动环绕图像。 这里是JsFiddle。 最好只使用CSS,但也可以使用JavaScript。

@somethinghere 服务器正确计算数值,因此这种情况永远不会发生。 - Florian Gl
1
您的服务器无法知道我的屏幕尺寸。 - somethinghere
@somethinghere 如果你的客户告诉他的话,那当然可以 ;) - Florian Gl
@somethinghere 好的,将其放置在 p 元素内是可能的,但我怎么知道在哪里呢?我从服务器获取文本、图像及其大小和位置。现在我必须建立一个类似文章的元素,并确保图像正好位于服务器告诉我的位置。即使我将 img 放在 p 元素内,也无法将其精确定位到坐标 x/y。简而言之,这是一个复杂的产品,为数百个客户提供服务,多年来不断发展,我必须实现一个新功能。^^ - Florian Gl
@somethinghere 只因为你不知道解决方案并不意味着它是不可能的。也许有另一种方法可以满足给定要求并获得所需的结果,但仅仅说“你不能这样做”是无知的。 - Florian Gl
显示剩余6条评论
3个回答

1
在玩具案例中几乎有效的方法是:
  1. 获取<p>元素的完整文本。
  2. 根据x从0到文本长度,将内容分割为“before”、“after”<span>元素。
  3. 进行二分搜索以找到x分割点,使得after.offsetTop是预期值。
  4. 通过添加之前的元素、图像和之后的元素来创建最终内容。
代码如下:
function add(img, textdiv, y) {
    var t = textdiv.textContent;
    var a = 0, b = t.length;
    var bef = document.createElement("span");
    var aft = document.createElement("span");
    while (a < b-1) {
        var x = (a + b) >> 1;
        bef.textContent = t.substr(0, x);
        aft.textContent = t.substr(x);
        textdiv.innerHTML = "";
        textdiv.appendChild(bef);
        textdiv.appendChild(aft);
        if (aft.offsetTop > y) {
            b = x;
        } else {
            a = x;
        }
    }
    textdiv.innerHTML = "";
    textdiv.appendChild(bef);
    textdiv.appendChild(img);
    textdiv.appendChild(aft);
}

这个解决方案中缺少的部分是将检测到的分割点移动到下一个单词边界(目前可能会在单词中间分割文本),但这并不难添加。
在谷歌浏览器和火狐浏览器中,我没有看到任何闪烁(但我只调用了一次,没有在计时器下执行)。
在实际情况中,如果不仅仅是文本而是任意HTML,则事情要复杂得多。

谢谢,非常好的解决方案,但不适合我。我有多个图像,并且段落内还有span和a元素。我认为我需要更深入地进行改变需求。 - Florian Gl

1

你的问题可能有一个解决方案,就是使用shape-outside与旧版本IE/FF/Chrome的polyfill。

我已经在你的示例中添加了一些代码: http://jsfiddle.net/dnmbpa7f/4/

img{
    shape-outside: polygon(10px 200px, 10px 500px, 550px 500px, 550px 200px);
    shape-margin: 1em;
    margin:25px;
    float:left;
    margin-top:200px;
}

div#container{
    clear:both;
}
<div id="container">
    
<img src="https://www.estella-kochlust.de/media/image/thumbnail/burger_520x520.png"/>  
<p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet,   consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, <span>popop</span>sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.

Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.

Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.
        
Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.
    
    </p>
</div>

关于polyfill的更多信息,请查看: http://blogs.adobe.com/webplatform/2014/05/12/css-shapes-polyfill/

最好的祝福, Ionic


您可以在以下链接获取源代码:https://github.com/adobe-webplatform/css-shapes-polyfill(抱歉,由于声望不足,无法发布两个链接) - Ionic

0
经过数小时的尝试和失败,我决定shapes-polyfill不符合我的需求。这就是为什么我构建了自己的解决方案(受shapes-polyfill启发),您可以在此处查看。
因为我们正在使用jQuery,所以我构建了一个使用它的解决方案,但它很容易转换为纯JavaScript(我只使用jQuery来设置一些CSS并附加HTML)。此外,它很快而且有点粗糙,但目前我懒得重构。 ;)

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