Потоковый график: два вопроса
Я играл с D3.js и пытаюсь сделать визуализацию потокового графика, используя данные в реальном времени.
Я очень много изучал эту статью http://bost.ocks.org/mike/path/
Я также прочитал этот вопрос и отвечает, что Svg clip-path внутри прямоугольника не работает, но это для строки. У меня есть объект d3.svg.area
Затем я прочитал эту статью D3 в режиме реального времени (графическая визуализация данных), но все еще не мог найти ответы
Мои два вопроса:
при рисовании потокового графа я заметил, что график всегда установлен внизу. Каждое обновление вычисляющей функции находит максимум данных и устанавливает нижнюю часть графика в нижней части элемента, где вы рисуете свой график.
var area = d3.svg.area() .x(function(data) { return data.x * width / Xmaximum; }) .y0(function(data) { return height - data.y0 * height / Ymaximum; }) .y1(function(data) { return height - (data.y + data.y0) * height / Ymaximum; });
Как я могу сделать, чтобы график в середине оси? Я думаю, мне нужно поиграть с x, y0 и y1 области, но как именно?
если вы попробуете мой код, часть графика будет показана слева. я знаю, что что-то не так с:
vis.append("defs").append("clipPath") .attr("id", "clip") .append("rect") .attr("width", width) .attr("height", height); vis.append("g") .attr("clip-path", "url(#clip)");
Я ищу любой ответ в других темах и по всему Интернету, но я застрял здесь!
Вот мой код:
<!DOCTYPE html>
<html>
<head>
<title>Test visu</title>
<style>
.line {
fill: none;
stroke: #000;
stroke-width: 1.5px;
}
.axis path, .axis line {
margin-left: 30px;
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
svg {
font: 10px sans-serif;
}
#restart{
visibility: hidden;
}
#visu{
margin-left: 70px;
//border: 5px solid black;
width: 900px;
height: 500px;
}
</style>
</head>
<body>
<div id="visu">
<script src="http://mbostock.github.com/d3/d3.js?2.7.2"></script>
var CONS = 100;
var layers_number = 4;
var samples_number = 50;
var margin = {top: 6, right: 0, bottom: 6, left: 40};
var width = 900 - margin.right;
var height = 500 - margin.top - margin.bottom;
var Xmaximum = samples_number - 1;
var Ymaximum = CONS * layers_number;
var initial_table = new Array();
for (var i = 0 ; i < layers_number ; ++i){
initial_table[i] = new Array();
for (var j = 0 ; j < samples_number ; ++j){
initial_table[i][j] = randomNber();
}
}
var values = new Array();
for (var i = 0 ; i < layers_number ; ++i)
values[i] = new Array();
var data0 = d3.layout.stack().offset("wiggle")(init_layers(layers_number,samples_number));
function color (indice){
if (indice == 0)
return "green";
else if (indice == 1)
return "blue";
else if (indice == 2)
return "red";
else if (indice == 3)
return "black";
return "black";
}
var y = d3.scale.linear()
.domain([0, Ymaximum])
.range([height, 0]);
var area = d3.svg.area()
.x(function(data) { return data.x * width / Xmaximum; })
.y0(function(data) { return height - data.y0 * height / Ymaximum; })
.y1(function(data) { return height - (data.y + data.y0) * height / Ymaximum; });
var vis = d3.select("div")
.append("svg")
.style("margin-left", -margin.left + "px")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
vis.append("defs").append("clipPath")
.attr("id", "clip")
.append("rect")
.attr("width", width)
.attr("height", height);
vis.append("g")
.attr("clip-path", "url(#clip)");
vis.selectAll("path")
.data(data0)
.enter()
.append("path")
.style("fill", function(data, indice) { return color(indice); })
.attr("d", area);
vis.append("g")
.attr("class", "y axis")
.call(d3.svg.axis().scale(y).ticks(5).orient("left"));
transition();
function transition() {
data0 = d3.layout.stack().offset("wiggle")(update_layers(layers_number,samples_number));
vis.selectAll("path")
.data(data0)
.attr("d", area)
.attr("transform", null)
.transition()
.duration(860)
.ease("linear")
.attr("transform", "translate(" + -(width / samples_number) + ")")
.each("end", function (data,indice) {
if (indice==0) transition();
});
for (var i = 0 ; i < values.length ; ++i)
values[i].shift();
}
function init_layers(layers_number, samples_number) {
return d3.range(layers_number).map(function(data,indice) {
for (var i = 0 ; i < samples_number ; i++)
values[indice][i] = initial_table[indice][i];
return values[indice].map(stream_index);
});
}
function update_layers(layers_number, samples_number) {
return d3.range(layers_number).map(function(data,indice) {
values[indice][samples_number] = randomNber();
return values[indice].map(stream_index);
});
}
function stream_index(data, indice) {
return {x: indice, y: Math.max(0, data)};
}
function randomNber(){
return parseInt(Math.random()*100)+1;
}
</div>
</body>
</html>
1 ответ
К вопросу о центрировании потока - используйте функцию смещения макета стека: