【问题标题】:difficult to put code in one svg (svg graph)很难将代码放在一个 svg 中(svg 图)
【发布时间】:2022-01-02 12:08:10
【问题描述】:

我已经在堆积条形图上工作了很长一段时间,我认为我有一个混乱的代码,我在这个图表的两个地方使用了<svg>

请参阅此代码笔https://codepen.io/a166617/pen/dyzEvMG 我尝试将其放在一个 svg 标记下,以便代码看起来更有序且更好,但我没有成功。将代码放在一个 svg 标签中的任何次数的迭代都会导致代码更加混乱,有时条形图根本不会随着我的更改而显示。

有人可以告诉我如何解决我创建的这个烂摊子。非常感谢您对此的任何意见。

最重要的混乱是下面的代码,我为每个单独的条形图放置了 svg。

{entries.map((entry, indx) => (
        <div class="mGraph content-style" key={Math.random()}>
          <svg
            viewBox={`0, 0, 80, 450`}
            height={500}
            width={90}
            style={{ transform: `rotateX(180deg)` }}
          >
            {rows(entry)}
          </svg>
          <div class="x-title">{entry.name}</div>
          { indx === 1 && <text class="label-title">PROJECTS</text>}
        </div>
))}

我尝试重新组织代码,这里是它的代码笔 https://codepen.io/a166617/pen/NWvZGLd

【问题讨论】:

  • 如何解决我造成的这个烂摊子你能说得更具体点吗?
  • @kiner_shah- 抱歉,如果我不清楚的话。我的意思是 1 个图形的两个 svg 使代码看起来很复杂。想知道我如何清理并只使用一个 svg
  • 您是否尝试将行附加到图形 SVG?
  • @kiner_shah- 我确实尝试过,但是当我进行更改时,条没有出现。
  • 如果你还没有看到,我在你的previous question提供了一个答案

标签: javascript html css reactjs svg


【解决方案1】:

我尝试使用纯 JS 来做到这一点。能够为图形创建单个 SVG:

const svgNS = "http://www.w3.org/2000/svg";

const addLine = (parent_g, x1, x2, y1, y2) => {
  var line = document.createElementNS(svgNS, "line");
  line.setAttribute("x1", x1);
  line.setAttribute("y1", y1);
  line.setAttribute("x2", x2);
  line.setAttribute("y2", y2);
  parent_g.appendChild(line);
};

const addText = (parent_g, x, y, text_val, class_ = "", dy = "", textanchor="", transform="") => {
  var text = document.createElementNS(svgNS, "text");
  text.setAttribute("x", x);
  text.setAttribute("y", y);
  
  if (class_ !== "")
    text.classList.add(class_);
  
  if (dy !== "")
    text.setAttribute("dy", dy);
    
  if (textanchor !== "")
    text.setAttribute("textAnchor", textanchor);
    
  if (transform !== "")
    text.setAttribute("transform", transform);
    
  text.innerHTML = text_val;
  parent_g.appendChild(text);
};

const addRect = (parent_g, width, height, x, y, fill) => {
    var rect = document.createElementNS(svgNS, "rect");
    rect.setAttribute("width", width);
    rect.setAttribute("height", height);
    rect.setAttribute("x", x);
    rect.setAttribute("y", y);
    rect.setAttribute("fill", fill);
    parent_g.appendChild(rect);
};

const addBarsToGraph = (entries) => {
  const barWidth = 50;
  const maxBarHeight = 490;
  
  var svgGraph = document.getElementById("svg-graph");
  
  var xpos = 100;
  for (var i = 0; i < entries.length; i++)
  {
    //console.log(entries[i].bars);
    for (var j = 0; j < entries[i].bars.length; j++)
    {
        const height = (entries[i].bars[j].value * maxBarHeight) / entries[i].total;
        const y = maxBarHeight - height - ((entries[i].bars[j].y * maxBarHeight) / entries[i].total);
        //console.log(height, y);
        addRect(svgGraph, 50, height, xpos, y, entries[i].bars[j].color);
        addText(svgGraph, xpos + 15, y + height / 2 - 10, entries[i].bars[j].value, "bar-count", "1.3em", "middle");
    }
    //console.log(xpos, maxBarHeight + 50);
    
    //var graphLabel = document.createElementNS(svgNS, "g");
    var rotateStr = "rotate(-45,"+ xpos + "," + (maxBarHeight + 50) + ")";
    addText(svgGraph, xpos, maxBarHeight + 50, entries[i].name, "x-title", "", "middle", rotateStr);
    
    //svgGraph.appendChild(graphLabel);
    
    xpos += 60;
  }
};

const addGridLinesAndGraphLabel = () => {
  var rootDiv = document.getElementById("root");
  rootDiv.style.display = "flex";
    
  var svg = document.createElementNS(svgNS, "svg");
  svg.setAttribute("id", "svg-graph");
  svg.classList.add("graph");
  
  var xgrid = document.createElementNS(svgNS, "g");
  xgrid.classList.add("grid");
  xgrid.classList.add("x-grid");
  xgrid.setAttribute("id", "xGrid");
  addLine(xgrid, "90", "90", "5", "490");
  svg.appendChild(xgrid);
  
  var ygrid = document.createElementNS(svgNS, "g");
  ygrid.classList.add("grid");
  ygrid.classList.add("y-grid");
  ygrid.setAttribute("id", "yGrid");
  addLine(ygrid, "90", "1805", "490", "490");
  svg.appendChild(ygrid);
  
  var ylabels = document.createElementNS(svgNS, "g");
  ylabels.classList.add("labels");
  ylabels.classList.add("y-labels");
  addText(ylabels, "80", "15", 100);
  addText(ylabels, "80", "131", 75);
  addText(ylabels, "80", "248", 50);
  addText(ylabels, "80", "373", 25);
  addText(ylabels, "80", "500", 0);
  addText(ylabels, "60", "200", "Pass %", "label-title");
  svg.appendChild(ylabels);
  
  addText(svg, "500", "550", "PROJECTS", "label-title");
  
  rootDiv.appendChild(svg);
};

const ReleaseScopeCharts = () => {
  const data = [
    {
      name: 'Transit',
      passed: 20,
      skipped: 50,
      failed: 30,
      untested: 0
    },
    {
      name: 'Access',
      passed: 0,
      skipped: 0,
      failed: 0,
      untested: 100
    },
  ];

  const colors = ['#30D158', '#005EA7', '#FF453A', '#ffcc00'];
 
  const entries = data.map(d => ({
    name: d.name,
    total: ['passed', 'skipped', 'failed', 'untested'].reduce(
      (acc, key) => acc + d[key],
      0
    ),
    bars: ['passed', 'skipped', 'failed', 'untested']
      .map((key, i) => ({
        value: d[key],
        color: colors[i],
        y:
          key === 'passed'
            ? 0
            : key === 'skipped'
            ? d.passed
            : d.skipped + d.passed,
      }))
      .filter(bar => bar.value),
    }));
        
    addGridLinesAndGraphLabel();
    addBarsToGraph(entries);
    
};

window.onload = () => { ReleaseScopeCharts(); }
body {
  font-family: 'Open Sans', sans-serif;
  margin-top: 1rem;
}

.mGraph > svg {
  position: relative;
  left: -60rem;
  top: -.65rem;
}

.mGraph > div {
  position: relative;
  left: -58rem;
  top: -.65rem;
}

.mGraph > text {
  position: relative;
  left: -50rem;
}

.graph .labels.x-labels {
  text-anchor: middle;
}

.graph .labels.y-labels {
  text-anchor: end;
}


.graph {
  height: 600px;
  width: 1200px;
}

.graph .grid {
  stroke: #ccc;
  stroke-dasharray: 0;
  stroke-width: 1;
}

.labels {
  font-size: 13px;
}

.label-title {
  font-weight: bold;
  text-transform: uppercase;
  font-size: 12px;
  fill: black;
  margin-left: 50%
}

.data {
  fill: red;
  stroke-width: 1; 
}

.bar-count {
  fill: white;
  font-size: 12px;
  transform-box: fill-box;
  transform: rotateX(0deg)
}

.x-title {
    color: red;
    margin-top: 20%;
    /*transform: rotate(-45deg)*/
};

.content-style {
  display: flex;
  flex-flow: column;
  align-items: center;
}
<!DOCTYPE html>
<div id="root"></div>

【讨论】:

  • 这是一个很好的练习 ;-)
猜你喜欢
  • 1970-01-01
  • 2021-08-03
  • 2022-01-15
  • 2021-10-20
  • 1970-01-01
  • 2022-01-24
  • 2012-09-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多