gojs 使用itemArray导致其他元素消失的问题及如何避免

场景

PanelitemArray 属性,配合 itemTemplate:go.Panel。可以实现将数组内每个元素都映射到图表上。

最初的实现逻辑大致如下。

下面是节点定义:

GO(go.Node, "Spot",
    {itemTemplate: nodePortTemplate},
    new go.Binding("itemArray", "portArray"),
    makeNodeTemplate(type, stretch, size),
}

其中 makeNodeTemplate 就是返回了 go.Picture|go.Shape 对象。

nodePortTemplate 如下:

GO(go.Panel, "Spot",
    {background: "black", desiredSize: new go.Size(5, 5), cursor:"pointer"},
    new go.Binding("portId", "portId"),
    new go.Binding("alignment", "alignment", go.Spot.parse).makeTwoWay(go.Spot.stringify),
    new go.Binding("fromLinkable", "fromLinkable"),
    new go.Binding("toLinkable", "toLinkable"),
    new go.Binding("fromSpot", "fromSpot", go.Spot.parse).makeTwoWay(go.Spot.stringify),
    new go.Binding("toSpot", "toSpot", go.Spot.parse).makeTwoWay(go.Spot.stringify),
    new go.Binding('fromMaxLinks', 'fromMaxLinks'),
    new go.Binding('toMaxLinks', 'toMaxLinks'),
    new go.Binding('background', '', (data)=>{
        return data['isHighlighted']? 'yellow': 'black'
    }),
    {
        toolTip: GO('ToolTip',
            GO(go.TextBlock, { margin: 4 }, new go.Binding('text', 'name'))
        )
    }
)

可以不必细看,就是根据数组内定义的位置等信息来实现节点的端口。同时也是为了使用 PortShiftingTool 用于端口移动。

起初结果很满意大致如下。同时端口可以自由移动。

在这里插入图片描述

问题发现

后来突发奇想,想在节点上显示该节点的名称。

于是修改了节点的代码,添加了 go.TextBlock 如下:

GO(go.Node, "Spot",
    {itemTemplate: nodePortTemplate},
    new go.Binding("itemArray", "portArray"),
    makeNodeTemplate(type, stretch, size),
    GO(go.TextBlock, new go.Binding('text', name))
}

拖入时没有问题

在这里插入图片描述

但是当添加了节点后,就会发现文字不见了。

在这里插入图片描述

思路和尝试

起初以为是将端口用了 go.Panel 挡住文字了。后来发现定义过了大小,而是 go.TextBlock 确实不见了。

继续研究官网 API 之后,发现对于 itemArray 有这么一句描述。

Replacing this array results all of this panel’s child objects being replaced with a copy of the Panel found in itemTemplateMap for each particular item in the Array.

替换此数组会导致此面板的所有子对象替换为在 itemTemplateMap 中找到的数组中每个特定项的面板副本。

大致意思或许是,使用了 itemArrayitemTemplate 后,会把面板原来有的子对象都替换成数组下的特定的模板。

但此时仍有疑问,makeNodeTemplate() 的返回值 go.Picture|go.Shape 明明也是和 itemArray 在同一个 go.Node 节点下的,那么对于图片来说也是这个节点的子对象,但是图片并没有消失。

后来尝试把函数直接换成一个 GO(go.Picture,...) 或者 GO(go.Shape, ...) 发现都依然存在,能够生效。但如果存在两个,则后一个对象在生成端口时,就会不见。情况和上述添加了 go.TextBlock 一致。

后来认为难道是,最前的元素算是这个节点的主元素,所以不归为子对象吗?也就是说作为主元素是不会被替换的吗?关于 isPanelMain

于是做了以下尝试。

GO(go.Node, "Spot",
    {itemTemplate: nodePortTemplate},
    new go.Binding("itemArray", "portArray"),
    //makeNodeTemplate(type, stretch, size), 
    GO(go.Shape, "Rectangle", {fill:'white'}),
    GO(go.Shape, "Rectangle", {desiredSize: new go.Size(10, 10), fill:'red', isPanelMain:true}),
}

发现和预想的不一样,仍然是后面的元素消失了。难道是位置在起作用?

GO(go.Node, "Spot",
        {itemTemplate: nodePortTemplate},
        new go.Binding("itemArray", "portArray"),
        GO(go.TextBlock, {stroke:"red"}, new go.Binding("text", "name")),
        makeNodeTemplate(type, stretch, size),
    )

于是互换了一下位置进行尝试。发现然如此。

拖入时,并不是没有文字,只是被盖住了。

在这里插入图片描述

添加节点后。

只剩下文字了。

在这里插入图片描述

那么就可以得出一个可用的结论。

结论

使用 itemArrayitemTemplate 确实会对该节点下的子对象产生影响,导致其他子对象不能显示。但是存在一个例外,就是该节点的第一个元素/对象,却是会被保留的。

那么如果我需要既显示图片又显示文字该怎么办?简单来说,使用 go.Panel 把两者包裹起来成为一个对象,将 go.Panel 放置在使用了 itemArraygo.Node 下的第一个位置即可。

解决方法如下:

GO(go.Node, "Spot",
        {itemTemplate: nodePortTemplate},
        new go.Binding('angle').makeTwoWay(),
        new go.Binding("itemArray", "portArray"),
        GO(go.Panel, "Spot",
            makeNodeTemplate(type, stretch, size),
            GO(go.TextBlock, {stroke:"red"}, new go.Binding("text", "name")),
        )
    )

但我并不认为这是一个比较好的方法,只是通过某种方式绕开了限制,或许也可能是我对 itemArrayitemTemplate 的使用存在问题。

但是官方 API 并没有对这个特点阐述,导致一开始以为所有的子对象都会被影响替换。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Doberman

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值