Как сделать гибкой высоту горизонтальной гистограммы, чтобы можно было изменять ее размер при добавлении новых данных? - PullRequest
0 голосов
/ 16 января 2020

Если у меня есть контейнер, в этом случае мой холст, как я могу установить гибкость высоты стержня? Короче говоря, если в dataArray будут добавлены новые данные, высота полосы должна измениться, чтобы соответствовать новым данным и остаться внутри моего холста.

Надеюсь, это имеет смысл.

Это код:

var dataArray = [3, 20, 34, 50, 50, 50, 50, 60];

var width = 500;
var height = 500;

var widthScale = d3.scaleLinear()
                    .domain([0, d3.max(dataArray)])
                    .range([0, width - 100]);

var color = d3.scaleLinear()
                .domain([d3.min(dataArray), d3.max(dataArray)])
                .range(["red", "blue"]);

var x_axis = d3.axisBottom()
                .scale(widthScale);

var canvas = d3.select("body")
                .append("svg")
                .attr("width", width)
                .attr("height", height)
                .append("g")
                .attr("transform", "translate(10,0)")

var bars = canvas.selectAll("rect")
                .data(dataArray)
                .enter() //
                    .append("rect") //
                    .attr("width", function (d) { return widthScale(d); })
                    .attr("height", 50)
                    .attr("fill", function(d) { return color(d); })
                    .attr("y", function (d, i) { return (i * 51); });

canvas.append("g")
        .attr("transform", "translate(0,480)")
        .call(d3.axisBottom(widthScale));

Большое вам спасибо за это.

Ответы [ 2 ]

0 голосов
/ 16 января 2020

Решение с использованием d3.scaleBand будет следующим. ScaleBand настроен с отступом 0,1, что означает, что 10% высоты выделяется для заполнения между столбцами и за пределами столбцов. scaleBand.bandwidth () - удобный инструмент для определения высоты столбцов.

var dataArray = [3, 20, 34, 50, 60];

var width = 500;
var height = 500;
var x_axis_margin = 20

var widthScale = d3.scaleLinear()
                    .domain([0, d3.max(dataArray)])
                    .range([0, width - 100]);
  
var y_scale = d3.scaleBand()
	.domain(dataArray.map((d,i) => i)) // create array of indices
	.range([0, (height - x_axis_margin)])
	.padding(0.1)

var barPadding = 1;

var color = d3.scaleLinear()
                .domain([d3.min(dataArray), d3.max(dataArray)])
                .range(["red", "blue"]);

var x_axis = d3.axisBottom()
                .scale(widthScale);

var canvas = d3.select("body") 
                .append("svg")
                .attr("width", width) 
                .attr("height", height)
                .append("g")
                .attr("transform", "translate(10,0)")


var bars = canvas.selectAll("rect")
                .data(dataArray)
                .enter() 
                    .append("rect") 
                    .attr("width", function (d) { return widthScale(d); })
                    .attr("height", y_scale.bandwidth())
                    .attr("fill", function(d) { return color(d); })
                    .attr("y", function (d, i) { return y_scale(i); });

canvas.append("g")
        .attr("transform", "translate(0,"+ (height - x_axis_margin) +")")
        .call(d3.axisBottom(widthScale));
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
0 голосов
/ 16 января 2020

Наконец-то я нашел решение.

Мне пришлось изменить размер высоты столбцов на основе набора данных и высоты холста, минус отступ, который я установил как переменную, в моем случае 1.

После этого мне пришлось указать на «y», чтобы вернуть i * высоту / длину набора данных.

Вот код только баров:

var bars = canvas.selectAll("rect")
                .data(dataArray)
                .enter()
                .append("rect")
                .attr("width", function (d) { return widthScale(d); }) 
                .attr("height", height / dataArray.length - barPadding) 
                .attr("fill", function(d) { return color(d); })
                .attr("y", function (d, i) { return i * (height / dataArray.length) - 20); });

и это окончательная версия кода:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>D3</title>
    <script src="https://d3js.org/d3.v5.min.js"></script>
</head>

<body>


<script>

var dataArray = [3, 20, 34, 50, 60];

var width = 500;
var height = 500;

var widthScale = d3.scaleLinear()
                    .domain([0, d3.max(dataArray)])
                    .range([0, width - 100]);
var barPadding = 1;


var color = d3.scaleLinear()
                .domain([d3.min(dataArray), d3.max(dataArray)])
                .range(["red", "blue"]);

var x_axis = d3.axisBottom()
                .scale(widthScale);



var canvas = d3.select("body") 
                .append("svg")
                .attr("width", width) 
                .attr("height", height)
                .append("g")
                .attr("transform", "translate(10,0)")


var bars = canvas.selectAll("rect")
                .data(dataArray)
                .enter() 
                    .append("rect") 
                    .attr("width", function (d) { return widthScale(d); })
                    .attr("height", height / dataArray.length - barPadding)
                    .attr("fill", function(d) { return color(d); })
                    .attr("y", function (d, i) { return i * (height / dataArray.length) - 20); });

canvas.append("g")
        .attr("transform", "translate(0,480)")
        .call(d3.axisBottom(widthScale));


</script>

</body>

</html>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...