You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Ruby on Rails中通过JS为每组图表的Dot元素添加SVG连线问题

解决方案

1. 修正ERB结构(按图表分组生成元素)

当前ERB会为每个匹配项单独生成.result-bar,导致每个点处于独立容器,无法组成完整图表。需要先将数组按3个图表分组(每组4个元素),让同一图表的点归属于同一个容器:

<% # 将数组按每组4个元素拆分,对应3个图表 %>
<% ary.in_groups_of(4).each do |chart_points| %>
  <div class="val" style="height: calc(100% / 3);">
    <div class="result-bar">
      <% chart_points.each do |x| %>
        <% if x == val %>
          <div class="dot"></div>
        <% end %>
      <% end %>
      <svg class="chart-svg"></svg>
    </div>
  </div>
<% end %>
<div class="letter-bar-range">
  <%= content_tag(:p, "#{letter}") %>
</div>

2. 调整CSS定位与SVG样式

给.result-bar设置相对定位,确保.dot的绝对定位基于当前图表容器;同时给SVG设置宽高,让它覆盖整个图表区域:

.val {
  width: 100%;
  position: relative;
  transform: translateX(70%);
  z-index: 1;
  display: flex;
  align-items: center;
  border: solid 1px blue;

  .result-bar {
    border: solid 1px red;
    position: relative; /* 作为内部元素的定位父级 */
    width: 100%;
    height: 100%;

    .dot {
      position: absolute;
      width: 10px;
      height: 10px;
      border-radius: 100%;
      background: $soft-blue;
      /* 可根据需求调整每个点的top/left位置,实现垂直排列 */
    }

    .chart-svg {
      position: absolute;
      top: 0;
      left: 0;
      width: 100%;
      height: 100%;
      pointer-events: none; /* 避免遮挡交互 */
    }
  }

  p {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
  }
}

3. 重写JS逻辑:为每个图表单独连线

遍历每个图表容器,收集内部所有点的坐标,用SVG<polyline>一次性连接所有点(比多个<line>更高效):

document.addEventListener('DOMContentLoaded', function() {
  // 遍历每个图表容器
  document.querySelectorAll('.result-bar').forEach(chart => {
    const dots = chart.querySelectorAll('.dot');
    const svg = chart.querySelector('.chart-svg');
    if (dots.length < 2) return;

    // 获取图表容器的位置,用于计算相对坐标
    const chartRect = chart.getBoundingClientRect();
    // 收集每个点相对于容器的中心坐标
    const points = Array.from(dots).map(dot => {
      const dotRect = dot.getBoundingClientRect();
      const x = dotRect.left + dotRect.width/2 - chartRect.left;
      const y = dotRect.top + dotRect.height/2 - chartRect.top;
      return `${x},${y}`;
    }).join(' ');

    // 创建多段线元素
    const polyline = document.createElementNS('http://www.w3.org/2000/svg', 'polyline');
    polyline.setAttribute('points', points);
    polyline.setAttribute('stroke', 'red');
    polyline.setAttribute('stroke-width', '1');
    polyline.setAttribute('fill', 'none');

    svg.appendChild(polyline);
  });
});

核心问题修正说明

  1. ID冲突:原代码用固定id="_svg",多个图表时只会选中第一个SVG,改用class后每个图表对应独立的SVG。
  2. 容器分组错误:原ERB将每个点放在独立容器,调整后同一图表的点归属于同一个.result-bar,便于批量处理。
  3. 坐标基准错误:将.result-bar设为相对定位,确保点的坐标计算基于当前图表容器,而非整个文档。

内容的提问来源于stack exchange,提问作者Jose Manuel Mendez Benitez

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 03:43:21