2021年3月7日星期日

Add constant horizontal line

I drew a multi-line chart that changes based on some user input. I want to add a reference line to always appear at the value y=100. I was able to manually place a line, but it is not always exactly at y=100.

Formatting issues aside, this is what I have for one possible user input. As you can see, the reference line is slightly below 100:

line chart

And my code:

  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);  });  
https://stackoverflow.com/questions/66522754/add-constant-horizontal-line March 08, 2021 at 07:56AM

没有评论:

发表评论