Home > Back-end >  Dots are not placed perfectly according to the data in line chart
Dots are not placed perfectly according to the data in line chart

Time:11-08

here im facing some small issue line dot points are not placed according to the x-axis points i dont know why dot points are moved 1cm before the actual values of x-points

issue-1 how can we match the dots exact with the x-axis points

issue-2 how can i avoid the zero postion grid line(i dont want to show grid line if value is zero 0 on y-axis)

i want to align like this

enter image description here

but i got like this

enter image description here

here i want to align the months vales and dot points position has to be same when we see x-axis to the dots postions

   const convertRemToPixels = (rem) => {
    return (
      rem * parseFloat(getComputedStyle(document.documentElement).fontSize)
    );
  };
  const data = [
    { x: "Jan", y: "0.03" },
    { x: "Feb", y: "5" },
    { x: "Mar", y: "10" },
    { x: "Apr", y: "6" },
    { x: "May", y: "11" },
    { x: "Jun", y: "2" },
  ];
 const margin = { top: 10, right: 30, bottom: 30, left: 60 },
      width = 600 - margin.left - margin.right,
      height = 400 - margin.top - margin.bottom;

    // append the svg object to the body of the page
    const svg = d3
      .select("#mainChart")
      .attr("width", width   margin.left   margin.right)
      .attr("height", height   margin.top   margin.bottom)
      .select("#mainGroup")
      .attr("transform", `translate(${margin.left},${margin.top})`);


  let tooltip = d3
      .select("#tooltipContainer")
      .style("position", "absolute")
      .style("top", 0)
      .style("left", 0)
      .style("display", "none");

    

    // grid function
    function make_y_gridlines() {
      return d3.axisLeft(y).ticks(6);
    }

    // Add X axis --> it is a date format
    const x = d3.scaleBand().range([0, width]);

    const y = d3
      .scaleLinear()
      .domain([0, d3.max(data.map((e) => parseInt(e.y)))])
      .range([height, 0]);

    var xAxis = d3.axisBottom(x);

    var yAxis = d3.axisLeft(y).ticks(6);
    x.domain(
      data.map(function (d) {
        console.log(d);
        return d.x;
      })
    ).padding([0.2]);
    svg
      .select("#XAxis")
      .transition()
      .attr("transform", "translate(0,"   height   ")")
      .call(xAxis)
      .style("color", "#a4a4a4");

    svg
      .select("#XAxis")
      .call(xAxis)
      .selectAll("text")
      .style("text-anchor", "end")
      .attr("dx", ".6em")
      .attr("dy", "1em")
      .style("font-size", ".8rem")
      .attr("transform", "rotate(0)")
      .style("font-family", '"Roboto", sans-serif');

    // Add Y axis

    svg
      .select("#YAxis")
      .transition()
      .call(yAxis)
      .style("color", "#a4a4a4")
      .style("font-size", ".7rem");

    svg
      .select("#linePath")
      .datum(data)
      .attr("fill", "none")
      .attr("stroke", "#14c884")
      .transition()
      .attr(
        "d",
        d3
          .line()
          .x(function (d) {
            console.log(d);
            return x(d.x);
          })
          .y(function (d) {
            return y(d.y);
          })
          .curve(d3.curveCatmullRom.alpha(1.1))
      );
    const circle = d3.select("#LineDots");

    circle
      .selectAll(".point")
      .data(data)
      .join("circle")
 .on("mouseover", (e, i) => {
        d3.select(e.target).transition().attr("r", 4);

        tooltip.transition().duration(0).style("display", "block");
        tooltip
          .html(`<div>${i.x} : <span>${i.y}</span></div>`)
          .style("left", e.pageX   convertRemToPixels(-1.6)   "px")
          .style("top", e.pageY - convertRemToPixels(2)   "px");
      })
      .on("mouseout", (e) => {
        d3.select(e.target).transition().attr("r", 2);

        tooltip.transition().duration(0);
        tooltip
          .style("left", "0px")
          .style("top", "0px")
          .style("display", "none");
      })
      .transition()
      .attr("class", "point")
      .attr("stroke", "#14c884")
      .attr("fill", function (d, i) {
        return "#14c884";
      })
      .attr("cx", function (d, i) {
        return x(d.x);
      })
      .attr("cy", function (d, i) {
        console.log(d.y);
        return y(d.y);
      })
      .attr("r", function (d, i) {
        return 2;
      })
      .style("opacity", 1);
    d3.select("#Grid")
      .transition()
      .call(make_y_gridlines().tickSize(-width).tickFormat(""))
      .attr("id", "gridSystem");
#gridSystem line{
        stroke: lightgrey;
        stroke-opacity: 0.7;
        shape-rendering: crispEdges;
        stroke-dasharray: 2 2;
        stroke-width : .05rem ;
    }

   #gridSystem path {
        stroke-width: 0;
    }

/* tooltip */
.barTitle{
  text-align: center;
  font-weight: bolder;
  padding: .2em 0;
  font-size: .8rem;
  color: black;
}
#tooltipContainer div span{
  color: #536876;
  font-weight: bold;
}
.bar{
  border-top-left-radius: 1em !important;
}

#tooltipContainer {
    line-height: 1.1;
    font-weight: bold;
    padding: .6em 1em .6em 1em;
    background:white;
   
    color: #9cb3c3;
    border-radius: .4em;
    font-weight: 600;
    box-shadow: 0em 0em .5em rgb(165, 163, 163);
    font-size: .6rem;
    font-family: 'Roboto', sans-serif;
  }
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/7.6.1/d3.min.js"></script>
<div id="tooltipContainer"></div>
   <svg id="mainChart">
        <g id="mainGroup">
          <g id="XAxis"></g>
          <g id="YAxis"></g>
          <g id="Grid"></g>
          <path id="linePath"></path>
          <g id="LineDots"></g>
        </g>
      </svg>

here is the codepan source code for fixing https://codepen.io/codingdarci/pen/ZERpNOG

can anyone please give me some suggetion how to figure it out and how to fix this issue

thanks advance

CodePudding user response:

Regarding the position of the circles, you want a point scale instead of a band scale, because band scales have an associated bandwidth:

const x = d3.scalePoint().range([0, width]);

For the y axis, simply remove the ticks for zero:

axis.selectAll(".tick")
.filter(d => d === 0)
.remove();

Here is your code with those changes:

const convertRemToPixels = (rem) => {
  return (
    rem * parseFloat(getComputedStyle(document.documentElement).fontSize)
  );
};
const data = [{
    x: "Jan",
    y: "0.03"
  },
  {
    x: "Feb",
    y: "5"
  },
  {
    x: "Mar",
    y: "10"
  },
  {
    x: "Apr",
    y: "6"
  },
  {
    x: "May",
    y: "11"
  },
  {
    x: "Jun",
    y: "2"
  },
];
const margin = {
    top: 10,
    right: 30,
    bottom: 30,
    left: 60
  },
  width = 600 - margin.left - margin.right,
  height = 400 - margin.top - margin.bottom;

// append the svg object to the body of the page
const svg = d3
  .select("#mainChart")
  .attr("width", width   margin.left   margin.right)
  .attr("height", height   margin.top   margin.bottom)
  .select("#mainGroup")
  .attr("transform", `translate(${margin.left},${margin.top})`);


let tooltip = d3
  .select("#tooltipContainer")
  .style("position", "absolute")
  .style("top", 0)
  .style("left", 0)
  .style("display", "none");



// grid function
function make_y_gridlines() {
  return d3.axisLeft(y).ticks(6);
}

// Add X axis --> it is a date format
const x = d3.scalePoint().range([0, width]);

const y = d3
  .scaleLinear()
  .domain([0, d3.max(data.map((e) => parseInt(e.y)))])
  .range([height, 0]);

var xAxis = d3.axisBottom(x);

var yAxis = d3.axisLeft(y).ticks(6);
x.domain(
  data.map(function(d) {
    console.log(d);
    return d.x;
  })
).padding([0.2]);
svg
  .select("#XAxis")
  .transition()
  .attr("transform", "translate(0,"   height   ")")
  .call(xAxis)
  .style("color", "#a4a4a4");

svg
  .select("#XAxis")
  .call(xAxis)
  .selectAll("text")
  .style("text-anchor", "end")
  .attr("dx", ".6em")
  .attr("dy", "1em")
  .style("font-size", ".8rem")
  .attr("transform", "rotate(0)")
  .style("font-family", '"Roboto", sans-serif');

// Add Y axis

svg
  .select("#YAxis")
  .transition()
  .call(yAxis)
  .style("color", "#a4a4a4")
  .style("font-size", ".7rem")
  .selectAll(".tick")
  .filter(d => d === 0)
  .remove();

svg
  .select("#linePath")
  .datum(data)
  .attr("fill", "none")
  .attr("stroke", "#14c884")
  .transition()
  .attr(
    "d",
    d3
    .line()
    .x(function(d) {
      console.log(d);
      return x(d.x);
    })
    .y(function(d) {
      return y(d.y);
    })
    .curve(d3.curveCatmullRom.alpha(1.1))
  );
const circle = d3.select("#LineDots");

circle
  .selectAll(".point")
  .data(data)
  .join("circle")
  .on("mouseover", (e, i) => {
    d3.select(e.target).transition().attr("r", 4);

    tooltip.transition().duration(0).style("display", "block");
    tooltip
      .html(`<div>${i.x} : <span>${i.y}</span></div>`)
      .style("left", e.pageX   convertRemToPixels(-1.6)   "px")
      .style("top", e.pageY - convertRemToPixels(2)   "px");
  })
  .on("mouseout", (e) => {
    d3.select(e.target).transition().attr("r", 2);

    tooltip.transition().duration(0);
    tooltip
      .style("left", "0px")
      .style("top", "0px")
      .style("display", "none");
  })
  .transition()
  .attr("class", "point")
  .attr("stroke", "#14c884")
  .attr("fill", function(d, i) {
    return "#14c884";
  })
  .attr("cx", function(d, i) {
    return x(d.x);
  })
  .attr("cy", function(d, i) {
    console.log(d.y);
    return y(d.y);
  })
  .attr("r", function(d, i) {
    return 2;
  })
  .style("opacity", 1);
d3.select("#Grid")
  .transition()
  .call(make_y_gridlines().tickSize(-width).tickFormat(""))
  .attr("id", "gridSystem")
  .selectAll(".tick")
  .filter(d => d === 0)
  .remove();
#gridSystem line {
  stroke: lightgrey;
  stroke-opacity: 0.7;
  shape-rendering: crispEdges;
  stroke-dasharray: 2 2;
  stroke-width: .05rem;
}

#gridSystem path {
  stroke-width: 0;
}


/* tooltip */

.barTitle {
  text-align: center;
  font-weight: bolder;
  padding: .2em 0;
  font-size: .8rem;
  color: black;
}

#tooltipContainer div span {
  color: #536876;
  font-weight: bold;
}

.bar {
  border-top-left-radius: 1em !important;
}

#tooltipContainer {
  line-height: 1.1;
  font-weight: bold;
  padding: .6em 1em .6em 1em;
  background: white;
  color: #9cb3c3;
  border-radius: .4em;
  font-weight: 600;
  box-shadow: 0em 0em .5em rgb(165, 163, 163);
  font-size: .6rem;
  font-family: 'Roboto', sans-serif;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/7.6.1/d3.min.js"></script>
<div id="tooltipContainer"></div>
<svg id="mainChart">
        <g id="mainGroup">
          <g id="XAxis"></g>
          <g id="YAxis"></g>
          <g id="Grid"></g>
          <path id="linePath"></path>
          <g id="LineDots"></g>
        </g>
      </svg>

  • Related