Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/svg/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Svg 添加恒定水平线_Svg_D3.js - Fatal编程技术网

Svg 添加恒定水平线

Svg 添加恒定水平线,svg,d3.js,Svg,D3.js,我画了一个多折线图,根据一些用户输入进行更改。我想添加一条参考线,使其始终以y=100的值显示。我可以手动放置一条线,但它并不总是精确地位于y=100 撇开格式问题不谈,这是我为一个可能的用户输入所做的。如您所见,参考线略低于100: 我的代码是: const svg = d3.select("svg"); const width = +svg2.attr("width"); const height = +svg2.attr("h

我画了一个多折线图,根据一些用户输入进行更改。我想添加一条参考线,使其始终以y=100的值显示。我可以手动放置一条线,但它并不总是精确地位于y=100

撇开格式问题不谈,这是我为一个可能的用户输入所做的。如您所见,参考线略低于100:

我的代码是:

  const svg = d3.select("svg");
  const width = +svg2.attr("width");
  const height = +svg2.attr("height");

  const render = data =>{
    const xValue = d => +d.week;
    const yValue = d => +d.power_score;
    const margin = {top:50, right:70, bottom:60, left:20};
    const innerWidth = width - margin.left - margin.right;
    const innerHeight = height - margin.top - margin.bottom;
  
    const colorValue = d => d.team;
  
    // define scales
    const xScale = d3.scaleLinear()
      .domain([1, d3.max(data, xValue)])
      .range([0, innerWidth-250])
      .nice();
  
    const yScale = d3.scaleLinear()
      .domain([d3.min(data, yValue)-10, d3.max(data, yValue)+10])
      .range([innerHeight, 0])
      .nice();
  
    const colorScale = d3.scaleOrdinal(d3.schemeCategory10);
  
    const g = svg2.append("g")
      .attr('transform', 'translate(75, 50)');
  
    // create axes
    const xAxis = d3.axisBottom(xScale)
      .tickSize(-innerHeight-10);
    
    const yAxis = d3.axisLeft(yScale)
      .tickSize(-innerWidth+240);
  
    const xAxisG = g.append("g").call(xAxis)
      .attr("transform", "translate(0, 400)");
  
    xAxisG.select(".domain")
          .remove();
  
    xAxisG.append("text")
      .attr("class", "axis-label")
      .attr("y", 40)
      .attr("x", (innerWidth-250)/2)
      .attr("fill", "black")
      .text("Week");
  
    const yAxisG = g.append("g").call(yAxis)
      .attr("transform", "translate(-10, 0)")
      .select(".domain")
        .remove();
  
    yAxisG.append("text")
      .attr("class", "axis-label")
      .attr("transform", "rotate(-90)")
      .attr("y", -35)
      .attr("x", -innerHeight/4)
      .attr("fill", "black")
      .text("Power Score");
    
    // generate line
    const lineGenerator = d3.line()
      .x(d => xScale(xValue(d)))
      .y(d => yScale(yValue(d)));
    
    // sort data for legend
    const lastYValue = d =>
      yValue(d.values[d.values.length - 1]);
  
    // group data
    const nested = d3.nest()
      .key(colorValue)
      .entries(data)
      .sort((a, b) =>
          d3.descending(lastYValue(a), lastYValue(b)));
  
    colorScale.domain(nested.map(d => d.key));
    
    // manually add horizonal line here
    svg2.append("g")
     .attr("transform", "translate(75, 267)")
     .append("line")
     .attr("x2", innerWidth-250)
     .style("stroke", "black")
     .style("stroke-width", "2px")
     .style("stroke-dasharray", "3, 3");
    
    // add lines with mouseover effect
    g.selectAll(".line-path").data(nested)
      .enter().append("path")
      .attr("class", "line-path")
      .attr("d", d => lineGenerator(d.values))
      .attr("stroke", d => colorScale(d.key))
      .attr("stroke-width", "3")
      .attr("opacity", "0.5")
      .on("mouseover", function(d, i) {
        d3.select(this).transition()
          .duration("50")
          .attr("stroke-width", "5")
          .attr("opacity", "1")})
      .on("mouseout", function(d, i) {
        d3.select(this).transition()
          .duration("50")
          .attr("stroke-width", "3")
          .attr("opacity", "0.5")});
    
    d3.line()
      .x(d => xScale(xValue(d)))
      .y(d => yScale(yValue(d)));
      
    // draw legend
    const colorLegend = (selection, props) => {
      const {
        colorScale,
        circleRadius,
        spacing,
        textOffset
      } = props;

    const groups = selection.selectAll('g')
      .data(colorScale.domain());
    
    const groupsEnter = groups
      .enter().append('g')
        .attr('class', 'tick');
    
    groupsEnter
      .merge(groups)
        .attr('transform', (d, i) =>
          `translate(0, ${i * spacing})`
        );
    groups.exit().remove();

    groupsEnter.append('circle')
      .merge(groups.select('circle'))
        .attr('r', circleRadius)
        .attr('fill', colorScale);

    groupsEnter.append('text')
      .merge(groups.select('text'))
        .text(d => d)
        .attr('dy', '0.32em')
        .attr('x', textOffset);
    }
    
    svg2.append("g")
      .attr("transform", "translate(710, 60)")
      .call(colorLegend, {
        colorScale,
        circleRadius: 4,
        spacing: 15,
        textOffset: 8
    });
  
    // Title
    g.append("text")
      .attr("class", "title")
      .attr("x", (innerWidth-250)/4)
      .attr("y", -10)
      .text("Weekly Power Ranks");
    
};

d3.csv('data.csv').then(data => {
  data.forEach(d => {
    d.week = +d.week;
    d.power_score = +d.power_score;
  });
    render(data);
});

而不是使用神奇的数字

svg2.append("g")
    .attr("transform", "translate(75, 267)")
    //magic numbers---------------^----^
…使用与绘制路径相同的y比例:

g.append("g")
    .attr("transform", `translate(75, ${yScale(100)})`)

另外,将其附加到已翻译的
,或应用相同的翻译(同样,代码中有更多的神奇数字…。

当我使用第二个块时,我会出现以下错误:“属性转换:拖尾垃圾,”translate(0,${yScale(100)})。“@hirshg这是一个模板文字,必须使用反勾(
`
),而不是引号(
)。