是否可以使用不同的布局算法创建自定义<ul>?</ul>

时间:2014-01-25 13:27:01

标签: dart dart-polymer web-component

我正在尝试创建具有以下特征的自定义Web组件:

  • 可以有多个子<li>元素(例如<ul><ol>
  • 具有子<li>元素的自定义布局算法。确切地说,我想根据渲染的大小来布局<li>元素,所以我需要一种方法来衡量每个孩子的大小。

我一直在尝试使用CSS和polymer.dart,但是现在我几乎被卡住了。有没有办法使用polymer.dart创建这样的元素?

当前实现呈现如下图:

Imgur

每个框都是<li>元素,具有绝对坐标。这些盒子目前是随机定位的,但我真正想做的是布置每个盒子,使它们不会相互重叠。

目前的问题是,在实际渲染之前,我无法测量每个孩子的大小。我尝试使用隐藏的虚拟元素预先测量大小,但似乎聚合物直到事后才更新DOM,所以我甚至不能使用虚拟元素。

目前的实施可以在https://github.com/rillomas/xclamm-gae/tree/51061a3bf33fe15724103517437d3281fe6ec495/web/lib/components找到。我正在尝试的组件是<remark-presenter>(自定义<ul>组件)和<remark-view>(自定义<li>组件)。

2 个答案:

答案 0 :(得分:1)

感谢Günter,我能够使用<ul>实现自定义的<ul>(一个MutationObserver包装网络组件),并且效果很好。

我制作了一个示例项目,演示了如果有人感兴趣我如何使用Polymer.dart MutationObserver

https://github.com/rillomas/custom-list

在示例中,我使用了MutationObserver,如下所示:

@override
void enteredView() {
    super.enteredView();
    _root = shadowRoot.querySelector("#root");

    // observe change of child elements for a 2 pass layout approach
    var mo = new MutationObserver(onChildMutation);
    mo.observe(_root, childList:true);
    _observer = mo;
}

/// Called when a mutation occurs to the target element
void onChildMutation(List<MutationRecord> changes, MutationObserver observer) {
    // layout children depending on its rendering size

    int itemCount = 0;
    int bounceBackDelta = bouncebacknum - 1;
    int nextBounceBack = bounceBackDelta;
    int xOffset = 0;
    int yOffset = 0;
    bool offsetRight = true;
    for (var record in changes) {
        var added = record.addedNodes;
        var removed = record.removedNodes;
        for (var a in added) {
            if (!(a.nodeType == Node.ELEMENT_NODE && a is CustomListItem)) {
                // ignore nodes expect for the one we want
                continue;
            }
            var elem = a as CustomListItem;
            var width = elem.clientWidth;
            var height = elem.clientHeight;
            // print("${width}x${height}");

            var unit = "px";
            if (elem.item.entered) {
                // This item is already displayed
                // so place the view at the same position

                var l = "${elem.item.rect.left}${unit}";
                var t = "${elem.item.rect.top}${unit}";
                elem.style.left = l;
                elem.style.top = t;
            } else {
                // This item is a new one.
                //  Layout the remark at a sufficient position
                Rectangle<int> posRect;
                if (offsetRight) {
                    posRect = new Rectangle<int>(xOffset,yOffset,width, height);
                } else {
                    posRect = new Rectangle<int>(xOffset-width, yOffset, width, height);
                }
                var l = "${posRect.left}${unit}";
                var t = "${posRect.top}${unit}";
                elem.style.left = l;
                elem.style.top = t;
                elem.item.rect = posRect;
                applyAnimation(elem, "fadein", 250);
                elem.item.entered = true;
            }

            // update offset depending on direction
            if (offsetRight) {
                xOffset += width;
            } else {
                xOffset -= width;
            }

            // update bounceback state
            if (offsetRight && itemCount == nextBounceBack) {
                offsetRight = false;
                xOffset -= width;
                nextBounceBack += bounceBackDelta;
            } else if (!offsetRight && itemCount == nextBounceBack) {
                offsetRight = true;
                xOffset += width;
                nextBounceBack += bounceBackDelta;
            }

            yOffset += height;
            itemCount++;
        }
    }
}

答案 1 :(得分:0)

元素在渲染之前没有大小。
您仍然可以在元素渲染后修改大小。

我删除了我的评论,但我仍然认为这与Polymer无关。

编辑根据您的评论 好的,这与聚合物有关。 您不能指望StackOverflow上的某人检查您的项目。您应该提供一个允许重现问题的最小示例,而不是指向包含整个项目的存储库的链接。

我认为两个2遍布局是你唯一的选择。 只要这是您的方法:

  • 您可以查询元素并更新HTML绑定的字段。 这可能很棘手,因为它们是使用template repeat进行的。也许mutationObservers在这里很有用(我还没有用过它)。
  • 你可以在重复的li中尝试使用它的模型(Remark)来调用组件的方法,这样你就可以识别它并将它的大小作为参数(不知道是否有效)并相应地更新您的评论列表位置。如果存储位置的对象是可观察的,则应该启动重新渲染。你必须谨慎,这不会导致无休止的更新循环。