我正在尝试创建具有以下特征的自定义Web组件:
<li>
元素(例如<ul>
和<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>
组件)。
答案 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遍布局是你唯一的选择。 只要这是您的方法:
template repeat
进行的。也许mutationObservers
在这里很有用(我还没有用过它)。li
中尝试使用它的模型(Remark
)来调用组件的方法,这样你就可以识别它并将它的大小作为参数(不知道是否有效)并相应地更新您的评论列表位置。如果存储位置的对象是可观察的,则应该启动重新渲染。你必须谨慎,这不会导致无休止的更新循环。