Я совершенно новичок ie в D3, и у меня действительно большая проблема. Я сделал разработку, чтобы показать многополосную диаграмму c, которая отлично работает, и вы можете проверить здесь:
![Edit MultipleBarChart](https://codesandbox.io/static/img/play-codesandbox.svg)
Я скопировал эту разработку на свой приложение, и у меня есть ошибка, и я не знаю, почему это произошло.
Это код моего приложения:
import React, { Component } from "react";
import * as d3 from "d3";
import "../../../css/content.css";
const HEIGHT = 360;
let WIDTH = 0;
const OFFSET_TOP = 30;
const OFFSET_BOTTOM = 30;
const OFFSET_LEFT = 80;
const OFFSET_RIGHT = 50;
/**
* To build this graphic we need to pass some values in these props:
* - idContainer: id of the div container. This must be unique
* - data: data to build the graphic. This is an array of json objects where each json object has the next structure:
* {
* shoot: String with the name of shoot,
* abrev_home_team: % of shoot for that team,
* abrev_away_team: % of shoot for that team
* }
* - groupKey: Name of the key which are goingto use to group the bars
* - keys: Array with the strings of all the keys which we are going to group around the groupKey
* - y_label: String with the name of Y Axis
* - lang: language to use to show the float numbers
*/
let data = [
{
name: "SPAR CITYLIFT GIRONA",
ortg: 95.17,
drtg: 81.96
},
{
name: "PERFUMERIAS AVENIDA",
ortg: 109.08,
drtg: 79.26
},
{
name: "IDK EUSKOTREN",
ortg: 89.50,
drtg: 95.13
},
{
name: "QUESOS EL PASTOR",
ortg: 87.30,
drtg: 99.58
},
{
name: "VALENCIA B.C.",
ortg: 93.40,
drtg: 86.81
},
{
name: "DURÁN MAQUINARIA ENSINO",
ortg: 93.12,
drtg: 95.69
},
{
name: "CADI LA SEU",
ortg: 95.37,
drtg: 94.97
},
{
name: "RPK ARASKI",
ortg: 89.50,
drtg: 88.85
},
{
name: "EMBUTIDOS PAJARIEL BEMBIBRE PD",
ortg: 81.85,
drtg: 95.47
},
{
name: "CAMPUS PROMETE",
ortg: 86.38,
drtg: 92.29
},
{
name: "CIUDAD DE LA LAGUNA TENERIFE",
ortg: 88.69,
drtg: 96.81
},
{
name: "MANN-FILTER CASABLANCA",
ortg: 85.44,
drtg: 93.78
},
{
name: "LOINTEK GERNIKA BIZKAIA",
ortg: 100.12,
drtg: 85.28
},
{
name: "NISSAN AL-QÁZERES EXTREMADURA",
ortg: 81.39,
drtg: 99.10
}
];
class MultipleBarChart extends Component {
constructor(props) {
super();
this.props = props;
this.state = {
loaded: false
};
}
componentDidMount() {
//Don't do anything!!!
}
componentWillReceiveProps(nextProps){
this.props = nextProps;
console.log("OFFSET_TOP: " + OFFSET_TOP);
console.log("FFSET_BOTTOM: " + OFFSET_BOTTOM);
console.log("OFFSET_LEFT: " + OFFSET_LEFT);
console.log("OFFSET_RIGHT): " + OFFSET_RIGHT);
let data2 = this.props.data.map((item, index) =>{
let item2 = {};
item2.name = item.name;
item2.ortg = parseFloat(item.ortg).toFixed(2);
item2.drtg = parseFloat(item.drtg).toFixed(2);
console.log("DATA name: " + typeof data[index].name + " PROPS name: " + typeof item2.name);
console.log("DATA ortg: " + typeof data[index].ortg.toFixed(2) + " PROPS ortg: " + typeof item2.ortg);
console.log("DATA drtg: " + typeof data[index].drtg.toFixed(2) + " PROPS drtg: " + typeof item2.drtg);
return item2;
});
let canvas = this.setCanvas();
let colors = this.setColors();
let scales = this.setScales(data2, this.props.keys);
//let scales = this.setScales(data, this.props.keys, this.props.groupKey);
this.setAxis(canvas, scales);
this.setLegend(canvas, colors, this.props.keys);
this.setBars(canvas, data2, scales, this.props.keys, colors, this.props.lang, this.props.groupKey);
//this.setBars(canvas, data, scales, this.props.keys, colors, this.props.lang, this.props.groupKey);
this.setState({
loaded: (typeof data2 !== "undefined" && typeof this.props.keys !== "undefined") ? true : false
});
}
setAxis(canvas, scales) {
//x axis
canvas
.append("g")
.attr("class", "axis")
.attr(
"transform",
"translate(" + 0 + ", " + (HEIGHT - OFFSET_TOP - OFFSET_BOTTOM) + ")"
)
.call(d3.axisBottom(scales.x0Scale))
.selectAll("text")
.style("text-anchor", "middle")
.style("font-weight", "bold")
.attr("font-size", "10pt")
.attr("dx", "-.1em");
//y axis
console.log("OFFSET_LEFT: " + OFFSET_LEFT);
canvas
.append("g")
.attr("class", "axis")
//.call(d3.axisLeft(scales.yScale).ticks(null, ".00%"))
.call(d3.axisLeft(scales.yScale).tickFormat(d3.format(".2f")))
//.selectAll("text")
.style("font-size", "8pt")
.style("font-weight", "bold")
.attr("transform", "translate(" + OFFSET_LEFT + ", 0)")
.append("text")
.attr("x", OFFSET_LEFT / 2 + 12)
.attr("y", OFFSET_TOP)
.attr("dx", "-3em")
.attr("dy", "-1em")
.attr("fill", "#FFFFFF")
.style("font-weight", "bold")
.style("font-size", "8pt")
.attr("text-anchor", "end")
.text(this.props.y_label);
//return { xAxis: xAxis, yAxis: yAxis };
}
setBars(canvas, data, scales, keys, colors, lang, groupKey) {
let height = HEIGHT - OFFSET_TOP - OFFSET_BOTTOM;
//var formatPercent = d3.format(".0%");
let bar = canvas
.append("g")
.selectAll("g")
.data(data)
.enter()
.append("g")
.attr("transform", function(d) {
//return "translate(" + scales.x0Scale(d.shoot) + ",0)";
console.log("d[groupKey]: " + d[groupKey]);
console.log("scales1: " + scales.x0Scale(d[groupKey]));
return "translate(" + scales.x0Scale(d[groupKey]) + ",0)";
});
//Here, you append rects to the groups:
bar
.selectAll("rect")
.data(function(d) {
return keys.map(function(key) {
return {
key: key,
value: d[key]
};
});
})
.enter()
.append("rect")
.attr("class", "rect")
.attr("x", function(d) {
return scales.x1Scale(d.key);
})
.attr("y", function(d) {
return scales.yScale(d.value);
})
.attr("width", scales.x1Scale.bandwidth())
.attr("height", function(d) {
return height - scales.yScale(d.value);
})
.attr("fill", function(d) {
return colors(d.key);
});
//Finally, here, you append texts to the groups:
bar
.selectAll("text")
.data(function(d) {
return keys.map(function(key) {
return {
key: key,
value: d[key]
};
});
})
.enter()
.append("text")
.attr("text-anchor", "middle")
.attr("class", "label-multiple-bar")
.attr("x", function(d, i) {
return scales.x1Scale.bandwidth() * (i + 0.5);
})
.attr("y", function(d, i) {
return scales.yScale(d.value) - 5;
})
.text(function(d) {
return lang === "es"
? String(d.value).replace(".", ",") + "%"
: d.value + "%";
});
}
setCanvas() {
console.log("WIDTH: " + d3.select("#" + this.props.idContainer).style("width"));
WIDTH = parseFloat(
d3.select("#" + this.props.idContainer).style("width")
).toFixed(2);
let svg = d3
.select("#" + this.props.idContainer)
.append("svg")
.style("background-color", "#354560")
.style("color", "#FFFFFF") //With this we've got the color of the axis too
.attr("height", HEIGHT)
.attr("width", WIDTH);
return svg;
}
setColors() {
return d3
.scaleOrdinal()
.range(["#DC3545", "#FFC107", "#007BFF", "#28A745", "#17A2B8", "#cf0eed"]);
}
/**
* Set a legend to the graphic at the top right of it
*
* @param {*} canvas
* @param {*} colors
* @param {*} keys
*/
setLegend(canvas, colors, keys) {
let legend = canvas
.append("g")
.selectAll("g")
.data(keys.slice())
.enter()
.append("g")
.attr("transform", function(d, i) {
return "translate(0," + i * 20 + ")";
});
legend
.append("rect")
.attr("x", WIDTH - OFFSET_RIGHT - OFFSET_LEFT)
.attr("y", 12)
.attr("width", 25)
.attr("height", 10)
.attr("fill", colors);
legend
.append("text")
.attr("x", WIDTH - OFFSET_RIGHT - OFFSET_LEFT + 60)
.attr("y", 18)
.attr("dy", "0.32em")
.text(function(d) {
return d;
})
.attr("fill", "#FFFFFF")
.attr("font-family", "Roboto")
.style("font-size", "10pt")
.style("font-weight", "bold")
.attr("text-anchor", "end");
}
setScales(data, keys, groupKey) {
let xRange = [OFFSET_LEFT + 0.05, WIDTH - OFFSET_RIGHT];
let yRange = [HEIGHT - OFFSET_TOP - OFFSET_BOTTOM, OFFSET_TOP];
let x0 = d3
.scaleBand()
.domain(
data.map(function(d) {
return d[groupKey];
})
)
.rangeRound(xRange)
.paddingInner(0.2);
let x1 = d3
.scaleBand()
.domain(keys)
.rangeRound([0, x0.bandwidth()])
.padding(0);
var y = d3
.scaleLinear()
.domain([
0,
d3.max(data, function(d) {
return d3.max(keys, function(key) {
return parseFloat(d[key]);
});
})
])
.nice()
.rangeRound(yRange);
return {
x0Scale: x0,
x1Scale: x1,
yScale: y,
xRange: xRange,
yRange: yRange
};
}
render() {
return (
<div>
<div id={this.props.idContainer} style = {{width: 1155 + "px"}}></div>
</div>
);
}
}
module.exports.MultipleBarChart = MultipleBarChart;
Этот компонент может работать как с получением данных, так и с данными из переменной "data" в начале кода. Если я запускаю свой код, беря данные из переменной «data», приложения работают нормально. ![enter image description here](https://i.stack.imgur.com/DN6aV.png)
Вы можете увидеть все столбчатые диаграммы, сгруппированные по два. Пожалуйста, не заботьтесь о наложении сейчас:)
В созданном вами журнале вы можете проверить, правильно ли создается xScale, потому что он возвращает правильное значение. Вы можете проверить это на этой картинке:
![enter image description here](https://i.stack.imgur.com/VcJOO.png)
Хорошо, все правильно. Но, если я прокомментирую эти строки, которые вы можете найти в componentWillReceiveProps
let scales = this.setScales(data, this.props.keys, this.props.groupKey);
this.setBars(canvas, data, scales, this.props.keys, colors, this.props.lang, this.props.groupKey);
, и раскомментируйте другие тезисы, которые также находятся в componentWillReceiveProps:
//this.setBars(canvas, data2, scales, this.props.keys, colors, this.props.lang, this.props.groupKey);
//let scales = this.setScales(data2, this.props.keys);
Чтобы взять данные из реквизита (получаются из другого компонента) мы получили такой результат:
![enter image description here](https://i.stack.imgur.com/qgjTM.png)
Это связано с ошибкой с xScale, в этом журнале вы можете увидеть, как это возвращает undefined:
![enter image description here](https://i.stack.imgur.com/y2olt.png)
Эта ошибка возвращается с помощью этого кода:
let bar = canvas
.append("g")
.selectAll("g")
.data(data)
.enter()
.append("g")
.attr("transform", function(d) {
//return "translate(" + scales.x0Scale(d.shoot) + ",0)";
console.log("d[groupKey]: " + d[groupKey]);
console.log("scales1: " + scales.x0Scale(d[groupKey]));
return "translate(" + scales.x0Scale(d[groupKey]) + ",0)";
});
Этот фрагмент кода вы можете найти по адресу начало setBars. Итак, ошибка в return "translate( + scales.X0Scale(d[groupKey]
", 0)" `
Но я не знаю почему !!! Я схожу с ума !!! : S
Я искал информацию и обнаружил, что при создании шкал вам нужно назначить массив для функций диапазона и домена из Scale, но я добавил функцию диапазона, дающую массив и удаляющую rangeBound из мой код, но он по-прежнему не работает.
Почему работает нормально, когда я беру данные из переменной данных, а неправильно работает с данными из другого компонента? Ничего не понимаю ...