0

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

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

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

当前的实现如下图所示:

伊姆古尔

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

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

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

4

2 回答 2

1

感谢 Günter,我能够使用它来实现一个自定义<ul><ul>准确地说是一个包装器 Web 组件)MutationObserver,并且效果很好。

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

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++;
        }
    }
}
于 2014-02-01T09:42:47.793 回答
0

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

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

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

我认为两个 2-pass 布局是您唯一的选择。如果这是您的方法:

  • 您可以查询您的元素并更新您的 HTML 绑定到的字段。这可能很棘手,因为它们是使用template repeat. 也许mutationObservers在这里很有用(我自己还没用过)。
  • 您可以尝试在重复li中使用它的模型()调用组件的方法的绑定,Remark以便您可以识别它并将它的大小作为参数(不知道这是否有效)并相应地更新您的 remarkLists 位置。如果存储位置的对象是可观察的,则应该启动重新渲染。您必须小心,这不会导致无休止的更新循环。
于 2014-01-25T13:43:26.977 回答