2 votes

Calculer la hauteur d'une barre en pixels à partir d'une valeur Y dans un graphique D3

J'ai une petite question. J'essaie de déterminer la hauteur en pixels d'une barre de graphique. C'est pour une implémentation D3, et mon graphique a un axe des ordonnées logarithmique.

  1. Je connais la valeur Y de la barre que j'essaie de tracer.
  2. Je connais également la hauteur de l'axe en pixels (600px).
  3. Je connais les valeurs min et max de l'axe Y

J'ai essayé plusieurs calculs, mais je n'arrive pas à calculer la hauteur de la barre de manière à ce qu'elle relie la valeur Y à l'axe des x.

L'image ci-dessous devrait illustrer visuellement ce que j'essaie de faire. Pour l'instant, je n'arrive pas à faire les choses correctement... Je pense qu'il s'agit essentiellement d'un problème de mathématiques, pas vraiment de D3. Je vous remercie !

*** EDIT ****

C'est l'échelle de l'axe des y que j'utilise :

var y = d3.scale.log()
.range([height, 0])
.domain([d3.min(sampleData, function(d) {
      return d.y;
    }),
    d3.max(sampleData, function(d) {
      return d.y;
    })
  ]);

enter image description here

2voto

Gerardo Furtado Points 61849

Je ne suis toujours pas sûr de votre problème, car la hauteur réelle de la barre est calculée par l'échelle même que vous utilisez pour ajouter les rectangles. Et, si vous ajoutez effectivement les rectangles, vous définissez déjà la valeur de l'élément height attribut !

Voyons un exemple. Il s'agit d'un diagramme à barres utilisant votre échelle logarithmique (j'utilise ici D3 v4, mais le principe est le même) et ces données fictives :

var data = [2000, 5000, 3000, 8000, 1500];

Comme vous pouvez le constater, il y a un minimum et un maximum. J'ai mis un padding de 20px dans l'échelle :

var yScale = d3.scaleLog()
    .range([height - padding, padding])
    .domain([d3.min(data), d3.max(data)]);

La première valeur de la plage est donc h - padding et notre dernière valeur est juste padding . Voici le tableau :

var width = 300,
  height = 400,
  padding = 20;
var svg = d3.select("body")
  .append("svg")
  .attr("width", width)
  .attr("height", height);

var data = [2000, 5000, 3000, 8000, 1500];

var xScale = d3.scaleBand()
  .range([50, width])
  .domain(d3.range(data.length))
  .padding(0.2);

var yScale = d3.scaleLog()
  .range([height - padding, padding])
  .domain([d3.min(data), d3.max(data)]);

var bars = svg.selectAll("foo")
  .data(data)
  .enter()
  .append("rect")
  .attr("x", (d, i) => xScale(i))
  .attr("width", xScale.bandwidth())
  .attr("height", d => height - padding - yScale(d))
  .attr("y", d => yScale(d))
  .attr("fill", "teal");

var gX = svg.append("g")
  .attr("transform", "translate(0," + (height - padding) + ")")
  .call(d3.axisBottom(xScale));

var gY = svg.append("g")
  .attr("transform", "translate(50,0)")
  .call(d3.axisLeft(yScale));

<script src="//d3js.org/d3.v4.min.js"></script>

Supposons que vous vouliez calculer la hauteur de la première barre. Nous pouvons voir, en inspectant le DOM, que sa hauteur est de 61.867984771728516 pixels :

var width = 300,
  height = 400,
  padding = 20;
var svg = d3.select("body")
  .append("svg")
  .attr("width", width)
  .attr("height", height);

var data = [2000, 5000, 3000, 8000, 1500];

var xScale = d3.scaleBand()
  .range([50, width])
  .domain(d3.range(data.length))
  .padding(0.2);

var yScale = d3.scaleLog()
  .range([height - padding, padding])
  .domain([d3.min(data), d3.max(data)]);

var bars = svg.selectAll("foo")
  .data(data)
  .enter()
  .append("rect")
  .attr("x", (d, i) => xScale(i))
  .attr("width", xScale.bandwidth())
  .attr("height", d => height - padding - yScale(d))
  .attr("y", d => yScale(d))
  .attr("fill", "teal");

var gX = svg.append("g")
  .attr("transform", "translate(0," + (height - padding) + ")")
  .call(d3.axisBottom(xScale));

var gY = svg.append("g")
  .attr("transform", "translate(50,0)")
  .call(d3.axisLeft(yScale));

console.log(d3.select("rect").node().height.animVal.value)

<script src="//d3js.org/d3.v4.min.js"></script>

Mais il s'agit simplement de la première valeur de l'intervalle ( height - padding ) moins yScale(2000) :

var width = 300,
  height = 400,
  padding = 20;
var svg = d3.select("body")
  .append("svg")
  .attr("width", width)
  .attr("height", height);

var data = [2000, 5000, 3000, 8000, 1500];

var xScale = d3.scaleBand()
  .range([50, width])
  .domain(d3.range(data.length))
  .padding(0.2);

var yScale = d3.scaleLog()
  .range([height - padding, padding])
  .domain([d3.min(data), d3.max(data)]);

var bars = svg.selectAll("foo")
  .data(data)
  .enter()
  .append("rect")
  .attr("x", (d, i) => xScale(i))
  .attr("width", xScale.bandwidth())
  .attr("height", d => height - padding - yScale(d))
  .attr("y", d => yScale(d))
  .attr("fill", "teal");

var gX = svg.append("g")
  .attr("transform", "translate(0," + (height - padding) + ")")
  .call(d3.axisBottom(xScale));

var gY = svg.append("g")
  .attr("transform", "translate(50,0)")
  .call(d3.axisLeft(yScale));

console.log(height - padding - yScale(2000))

<script src="//d3js.org/d3.v4.min.js"></script>

C'est d'ailleurs cette valeur qui est utilisée pour définir la hauteur des barres :

.attr("height", d => height - padding - yScale(d))

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X