我正在尝试使用下面的网页制作一个动态图。
https://twitter.com/ThingsWork/status/1124378131328929792/video/1
我不太清楚如何定义问题。我对条的宽度没有问题,但是由于宽度的变化,所以订购它们的事实。
我已经意识到,在一个元素中,一次只能有一个活动过渡。现在我不知道如何继续。
有人可以让我知道制作此图形的步骤吗?我最大的问题是,考虑到x坐标必须不断更新,如何同时更新x和y轴上的条。
这是文件test.txt的内容
org jan19 feb19 mar19
9911-Org 1 4.14 8.54 11.54
9912-Org 2 7.51 5.51 9.51
9913-Org 3 10.36 22.36 15.36
9914-Org 4 4.65 8.65 8.65
9916-Org 5 1.54 1.54 1.54
9936-Org 6 13.02 13.02 13.02
9937-Org 7 61.92 41.92 55.92
9938-Org 8 3.95 3.95 3.95
9940-Org 9 15.08 15.08 15.08
9943-Org 10 10.60 10.60 10.60
9945-Org 11 5.83 5.83 5.83
9976-Org 12 36.29 45.29 45.29
<!DOCTYPE html>
<meta charset="utf-8">
<!-- Load js library -->
<script src="./libraries/d3/d3.js"></script>
<style type="text/css">
svg {border:1px solid #eb830d1f;}
</style>
<div id="d3_graph1"></div>
<script>
// Intervals
var transition_value;
var transition_interval;
// Principal column name
name_ppal_col = "org"
// Dynamic columns names
name_dinamic_cols = ["jan19", "feb19", "mar19"]
// set the dimensions and margins of the graph
var margin = {top: 20, right: 30, bottom: 40, left: 290},
width = 660 - margin.left - margin.right,
height = 400 - margin.top - margin.bottom;
// append the svg object to the body of the page
var svg = d3.select("#d3_graph1")
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform",
"translate(" + margin.left + "," + margin.top + ")");
var actual_state;
var idens;
// Parse the Data
d3.tsv("./data/test.txt").then(function(data) {
// we order the first column from highest to lowest
if (data.length>=2) {
data.sort(function (a, b) {
return (b[name_dinamic_cols[0]] - a[name_dinamic_cols[0]])
})
}
// id - principal column asociation
idens = new Object();
for (i = 0; i < data.length; i++) {
idens[data[i][name_ppal_col]] = i + 1;
}
// Add X axis
var x = d3.scaleLinear()
.domain([0, 70])
.range([ 0, width]);
svg.append("g")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x))
.selectAll("text")
.attr("transform", "translate(-10,0)rotate(-45)")
.style("text-anchor", "end")
;
// Y axis
var y = d3.scaleBand()
.range([ 0, height ])
.domain(data.map(function(d) { return d[name_ppal_col]; }))
.padding(.1);
svg.append("g")
.call(d3.axisLeft(y))
//Bars
svg.selectAll("myRect")
.data(data)
.enter()
.append("rect")
.attr("x", x(0))
.attr("y", function(d) { return y(d[name_ppal_col]); })
.attr("width", function(d) { return x(d[name_dinamic_cols[0]]); })
.attr("height", y.bandwidth() )
.attr("fill", "#FF9A00")
.attr("value", function(d) { return d[name_dinamic_cols[0]]; })
.attr("id", function(d) { return "rect" + idens[d[name_ppal_col]] ; })
// Labels
svg.append("g")
.attr("fill", "black")
.attr("text-anchor", "end")
.style("font", "12px sans-serif")
.selectAll("text")
.data(data)
.join("text")
.attr("x", d => x(d[name_dinamic_cols[0]]) + 35)
.attr("y", d => y(d[name_ppal_col]) + y.bandwidth() / 2)
.attr("dy", "0.35em")
.attr("id", function(d) { return "label" + idens[d[name_ppal_col]];})
.text(d => d[name_dinamic_cols[0]]);
if (data.length > 2) {
var n_transicion = 1;
// we keep the order by identifier
actual_state = [];
d3.selectAll("#d3_graph1 rect").each(function(d,i) {
id_actual = d3.select(this).attr("id");
y_actual = d3.select(this).attr("y");
// Quitamos la cadena rect
id_actual = id_actual.slice(4,id_actual.length);
actual_state[id_actual] = id_actual;
})
//console.log("orden",actual_state);
function update_X() {
for (j = 0; j < data.length; j++) {
var rect = "#rect" + idens[(data[j][name_ppal_col])]
var label = "#label" + idens[(data[j][name_ppal_col])]
// Bar
d3.select(rect)
.transition()
.duration(3000)
.attr("width", x(data[j][name_dinamic_cols[n_transicion]]))
.attr("value", data[j][name_dinamic_cols[n_transicion]])
// Label
n_transicion_ant = n_transicion - 1;
n_transicion_act = n_transicion;
d3.select(label)
.transition()
.duration(3000)
.attr("x", d => x(d[name_dinamic_cols[n_transicion]]) + 35)
.tween("text", function(d) {
var i = d3.interpolate(d[name_dinamic_cols[(n_transicion_ant)]], d[name_dinamic_cols[n_transicion_act]]);
return function(t) {
d3.select(this).text(d3.format(",.2f")(i(t)));};
});
}
n_transicion++;
}
function update_Y() {
// el orden
values = [];
actual_state = [];
// Sort values
d3.selectAll("#d3_graph1 rect").each(function(d,i) {
id_actual = d3.select(this).attr("id");
valor_actual = d3.select(this).attr("value");
// Quitamos la cadena rect
id_actual = id_actual.slice(4,id_actual.length);
values[i] = { id: parseInt(id_actual),
value: valor_actual
};
})
values.sort(function(a,b) {
return (b.value - a.value);
})
pos = 0;
values.forEach(function (reg) {
actual_state[pos]= reg.id;
pos++;
});
console.log("values:",values);
console.log("actual_state:",actual_state);
data.sort(function(a,b) {
index_a = idens[a.red];
index_b = idens[b.red];
//console.log("index_a:"+index_a);
//console.log("index_b:"+index_b);
//console.log("red:",a.red,"index_a:",index_a,"actual_state:",actual_state.indexOf(index_a));
//console.log("red:",b.red,"index_b:",index_b,"actual_state:",actual_state.indexOf(index_b));
return (actual_state.indexOf(index_b) - actual_state.indexOf(index_a));
})
console.log("data:",data);
// if do transition, stop the transition of X!! doesn't work. I don't know how to continue
}
update_X();
transition_value = d3.interval(function(interval) {
if ((n_transicion < Object.keys(data[0]).length - 1)) {
// axis X
update_X();
}
else {
transition_value.stop();
transition_interval.stop();
}
} , 3000);
// Axis y
// every 200 ms we check if the order has changed
transition_interval = d3.interval(function(interval) {
update_Y();
}, 200);
}
})
</script>