【问题标题】:How to select the second to last tag in a list?如何选择列表中倒数第二个标签?
【发布时间】:2019-12-18 14:17:30
【问题描述】:

我是前端开发和使用 d3.js 的新手。我在标签列表中选择某个标签时遇到问题。

我创建了一些图表,我需要将图像添加到某些节点。我尝试使用d3.select('g') 选择所需的标签,但这会选择第一个标签。但是我觉得最大的问题是标签叫法一样,比如倒数第二个标签不知道怎么选。

这是我的 HTML 代码(短版):

<svg _ngcontent-c1="" width="1366" height="99">
   <gr _ngcontent-c1="" ng-reflect-zoomable-of="[object SVGSVGElement]">
      <g _ngcontent-c1="" _nghost-c2="" ng-reflect-link="[object Object]">
         <line _ngcontent-c2="" class="link" x1="1" y1="-2" x2="3" y2="-1"> </line>
      </g>
      <g _ngcontent-c1="" _nghost-c2="" ng-reflect-link="[object Object]">
         <line _ngcontent-c2="" class="link" x1="5" y1="2" x2="9" y2="4"> </line>
      </g>

   <g _ngcontent-c1="" ng-reflect-node="[object Object]" ng-reflect-draggable-node="[object Object]" ng-reflect-draggable-in-graph="[object Object]">
      <g transform="translate(3,4)">
         <text class="node-name" x="13" y="-3" font-size="20px">one</text>
      </g>
   </g>

   <g _ngcontent-c1="" ng-reflect-node="[object Object]" ng-reflect-draggable-node="[object Object]" ng-reflect-draggable-in-graph="[object Object]">
      <g transform="translate(5,6)">
             <text class="node-name" x="13" y="-3" font-size="20px">two </text>
          </g>
       </gr>

我尝试添加图片:

var svg = d3.select('svg').select('gr').select('g')
  .append('svg')
  .attr('width', 64)
  .attr('height', 64)
  .style('border', '1px solid black');
var imgs = svg.selectAll('image').data([0]);
imgs.enter()
  .append('image')
  .attr('xlink:href', '/assets/ToNode.png')
  .attr('width', '64')
  .attr('height', '64');

【问题讨论】:

    标签: javascript typescript d3.js dom


    【解决方案1】:

    仅从标题来看,您的问题是重复的,:last-child 是显而易见的选择。有几个重复的目标,例如this one。但是,没有答案显示如何选择倒数第二个元素。实际上,如果您在 标签中搜索penultimate,您的问题就是唯一的结果。

    对于通过给定索引选择元素:nth-child() 是最常见的选项,或者,因为您从末尾开始计数,所以:nth-last-child()。但我想给你一个答案,展示如何结合使用第二个和第三个参数(大多数 D3 方法)。

    在几个 D3 方法中(如filter,我将在此答案中使用),第二个参数是元素相对于选择的索引,而第三个参数是当前组或节点,它组成那个选择。这些参数通常命名为in,但您可以随意命名它们。这里的重要信息是n.length 为我们提供了元素的数量。

    因此,如果我们选择所有 &lt;g&gt; 元素,我们可以使用以下方法获得倒数第二个:

    yourSelection.filter(function(_, i, n) {
        return i === n.length - 2
      })
    

    在这里,我使用n.length - 2,因为索引是从零开始的,因此n.length - 1 是最后一个元素。另外,_ 只是一个约定,表示我们不会在函数的任何地方使用第一个参数。

    这是一个演示,如果您检查 SVG,您会看到一个虚拟元素 &lt;foo&gt; 已添加到倒数第二组:

    d3.selectAll("g").filter(function(_, i, n) {
        return i === n.length - 2
      })
      .append("foo")
    <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
    <svg>
      <g></g>
      <g></g>
      <g></g>
      <g></g>
      <g></g>
    </svg>

    【讨论】:

    • 最明显的选择可能是g:nth-last-child(2)。不过答案很好。我真的很喜欢指出不同的、不明显的方法的答案。唉,一个人很可能会因为发布这样的答案而受到打击。
    • 为了干净、可维护的代码,应该坚持使用单一的、经常使用的方法。 el:nth-last-child(n) 是针对正是这个用例实现的(选择倒数第 n 个元素)。为什么要使用不同的东西?
    • @ThomasPötzsch 因为这是 D3。有时用户需要在selection.each 中选择元素,或者在attrstyle 方法的回调中,或者在selection.on 定义的事件监听器中...用过。
    • 哦,好的。我只是出于好奇而询问,谢谢您的回答!
    • @ThomasPötzsch 正如 OP 所说 “我在标签列表中选择某个标签时遇到问题。”和 “我不知道如何选择例如倒数第二个标签”,Gerardo 的方法是最普遍适用的解决方案(至少涉及 D3)。重读这篇文章,我感觉选择倒数第二个元素更多的是一个例子,而不是一个特定的用例;这个问题似乎只是一个XY问题。只要我们不知道 OP 的目标,这个答案就和其他答案一样有效,因为没有衡量其适用性的指标。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-04-01
    • 1970-01-01
    • 2022-01-22
    • 2011-07-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多