Home > Net >  bar graph ticks labels are not updating when data changed in d3.js
bar graph ticks labels are not updating when data changed in d3.js

Time:11-03

here is my full working code

const outerWidth = 600;
const outerHeight = 300;
const margin = 60;
const height = outerHeight - 2*margin;
const width = outerWidth - 2*margin;

var data = [
{ group: 'A', value: 5 },
{ group: 'B', value: 15 },
{ group: 'C', value: 10 },
{ group: 'D', value: 15 },
{ group: 'E', value: 10 },
{ group: 'F', value: 5 },
];

const update = (data)=>{
const svg = d3.select("#containerSvg")
.attr("width", outerWidth)
.attr("height", outerHeight);

const graph = svg
.select("#graphGroup")
.attr("transform", "translate("   margin   ","   margin  ")");

const sx = d3.scaleBand()
.domain(data.map(d => d.group))
.range([0, width])
.padding(.1);
const maxing = d3.max(data.map(d=> d.value))
const sy = d3.scaleLinear()
.domain([0, maxing])
.range([height, 0]);

const getUnique = [...new Set(data.map(d => d.value))].sort(d3.ascending)
//console.log(getUnique);
// you can see what is happening in console while updating data
// every time unique values are not three as we have expected as tick label it may more then that
// how can we reduce the array length according to the tick points and there i want to show there [Low, Medium , High]
const tickScale = d3.scaleOrdinal()
.domain([...new Set(data.map(d => d.value))].sort(d3.ascending))
.range(["Low", "Medium", "High"])
.unknown("");

const xAxis = d3.axisBottom(sx);
const yAxis = d3.axisLeft(sy)
.ticks(3)
.tickFormat(tickScale);
const bar = graph.selectAll(".bar").data(data);

bar.join("rect")
.attr('class', 'bar')
.attr("x", d => sx(d.group))
.attr("y", d => sy(d.value))
.attr("width", sx.bandwidth())
.attr("height", d => height - sy(d.value));

svg.select("#XAxis")
.attr("transform", "translate(0,"   height   ")")
.call(xAxis)

svg.select("#YAxis")
.call(yAxis)
}

update(data);

const buttonData1Access = document.getElementById("Data-button1")
const buttonData2Access = document.getElementById("Data-button2")
const buttonData3Access = document.getElementById("Data-button3")
const buttonData4Access = document.getElementById("Data-button4")

buttonData1Access.addEventListener("click" , (e)=>{
data = [
{ group: 'A', value: 5 },
{ group: 'B', value: 15 },
{ group: 'C', value: 10 },
{ group: 'D', value: 15 },
{ group: 'E', value: 10 },
{ group: 'F', value: 5 },
]
update(data);
})
buttonData2Access.addEventListener("click" , (e)=>{
data = [
{ group: 'y', value: 9 },
{ group: 'o', value: 3 },
{ group: 'u', value: 1 },
{ group: 'D', value: 8 },
{ group: 'E', value: 17 },
{ group: 'F', value: 5 },
]
update(data);
})
buttonData3Access.addEventListener("click" , (e)=>{
data = [
{ group: 'D', value: 1 },
{ group: 'E', value: 3 },
{ group: 'F', value: 9 },
{ group: 'y', value: 9 },
{ group: 'o', value: 3 },
{ group: 'u', value: 1 },
]
update(data);
})
buttonData4Access.addEventListener("click" , (e)=>{
data = [
{ group: 'y', value: 9 },
{ group: 'o', value: 3 },
{ group: 'u', value: 1 },
{ group: 'D', value: 8 },
{ group: 'E', value: 17 },
{ group: 'F', value: 5 },
]
update(data);
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/7.6.1/d3.min.js"></script>
<div >
  <button  id="Data-button1">Data 1</button>
  <button  id="Data-button2">Data 2</button>
   <button  id="Data-button3">Data 3</button>
  <button  id="Data-button4">Data 4</button>
</div>
<svg id="containerSvg">
  <g id="graphGroup">
     <g id="XAxis"></g>
     <g id="YAxis"></g>
  </g>

</svg>

whenever i update the graph with new data labels in the y-axies not updating properly according the new data and tick points it seems like label points are taking the old data values reference and one more thing array values in the y-axis are not always same as like tick points

mistake

seems like this is the part i have done mistake, you can see this code

const maxing = d3.max(data.map(d=> d.value))
    const sy = d3.scaleLinear()
    .domain([0, maxing])
    .range([height, 0]);

    const getUnique = [...new Set(data.map(d => d.value))].sort(d3.ascending)
    //console.log(getUnique);
    // you can see what is happening in console while updating data
    // every time unique values are not three as we have expected as tick label it may more then that
    // how can we reduce the array length according to the tick points and there i want to show there [Low, Medium , High]
    const tickScale = d3.scaleOrdinal()
    .domain([...new Set(data.map(d => d.value))].sort(d3.ascending))
    .range(["Low", "Medium", "High"])
    .unknown("");

    const xAxis = d3.axisBottom(sx);
    const yAxis = d3.axisLeft(sy)
    .ticks(3)
    .tickFormat(tickScale);
    const bar = graph.selectAll(".bar").data(data);

i want to update the y-axis labes properly with 3 ticks and this [low, medium, high] data on each point even when data changes

i'm wishing someone would help me

thanks advance !

CodePudding user response:

If I understand well, you always want to have 3 labels "Low", "Medium", "High" on the Y axis, whatever the input data are ? In that case you can simply use an ordinal scale based on the input domain:

const maxing = d3.max(data.map(d=> d.value));
const yAxisDomain = [0, maxing / 3, 2 * maxing / 3, maxing];
const tickScale = d3.scaleOrdinal()
  .domain(yAxisDomain)
  .range([height, 2 * height / 3, height / 3, 0]);

This scale is used on the Y axis to evenly place the ticks. You can then use another ordinal scale to map the values to the labels:

const yAxis = d3.axisLeft(tickScale)
  .tickValues(yAxisDomain)
  .tickFormat(d3.scaleOrdinal(yAxisDomain, ["0", "Low", "Medium", "High"]));

I used the tickValues function instead of ticks to be sure to have 3 ticks on the axis.

Here is an example: https://codepen.io/ccasenove/pen/oNyxQXK

  • Related