Как добавить маркировку в гистограмму, используя d3 - PullRequest
0 голосов
/ 14 декабря 2018

Мне нужно создать гистограмму, используя d3, с подсветкой между начальной и конечной точками (например, маркером).Вот мой фрагмент кода.

<!DOCTYPE html>
<html>

<head>
    <meta charset='utf-8' />
    <title>Simple Bar chart</title>
    <script src="https://d3js.org/d3.v3.min.js" charset="utf-8"></script>
    <style>
        body {
            font-family: "Arial", sans-serif;
        }
        
        .bar {
            fill: #5f89ad;
        }
         .highlight {
            fill: #ff0;
        }
        .axis {
            font-size: 13px;
        }
        
        .axis path,
        .axis line {
            fill: none;
            display: none;
        }
        
        .label {
            font-size: 13px;
        }
    </style>

</head>

<body>

    <div id="graphic"></div>

    <script>
        var data = [{
                "name": "Case 01",
                "value": 2000,
                "xValue": 500,
                "slength": 100,
        },
            {
                "name": "Case 02",
                "value": 1290,
        },
            {
                "name": "Case 03",
                "value": 19000,
        },
            {
                "name": "Case 04",
                "value": 5000,
        },
            {
                "name": "Case 05",
                "value": 1600,
        },
            {
                "name": "Case 06",
                "value": 2600,
        },
            {
                "name": "Case 07",
                "value": 3000,
        },
	{
                "name": "Case 08",
                "value": 7000,
        },
            {
                "name": "Case 09",
                "value": 3290,
        },
            {
                "name": "Case 10",
                "value": 12000,
        },
            {
                "name": "Case 11",
                "value": 10000,
        },
            {
                "name": "Case 12",
                "value": 11600,
        },
            {
                "name": "Case 13",
                "value": 5600,
        },
            {
                "name": "Case 14",
                "value": 6000,
        },{
                "name": "Case 15",
                "value": 8600,
        },
            {
                "name": "Case 16",
                "value": 4280,
        },
            {
                "name": "Case 17",
                "value": 9000,
        },
            {
                "name": "Case 18",
                "value": 5000,
        },
            {
                "name": "Case 19",
                "value": 4300,
        },
            {
                "name": "Case 20",
                "value": 2600,
        },
            {
                "name": "Case 21",
                "value": 6700,
        },{
                "name": "Case 22",
                "value": 12000,
        },
            {
                "name": "Case 23",
                "value": 8290,
        },
            {
                "name": "Case 24",
                "value": 8000,
        },
            {
                "name": "Case 25",
                "value": 7600,
        },
            {
                "name": "Case 26",
                "value": 1600,
        },
            {
                "name": "Case 27",
                "value": 5500,
        },
            {
                "name": "Case 28",
                "value": 4400,
        },{
                "name": "Case 29",
                "value": 8900,
        },
            {
                "name": "Case 30",
                "value": 6790,
        },
            {
                "name": "Case 31",
                "value": 11000,
        },
            {
                "name": "Case 32",
                "value": 5000,
        },
            {
                "name": "Case 33",
                "value": 6600,
        },
            {
                "name": "Case 34",
                "value": 7700,
        },
            {
                "name": "Case 35",
                "value": 3000,
        }];

        //sort bars based on value
        data = data.sort(function (a, b) {
            return d3.descending(a.name, b.name);
        })

        //set up SVG using margin conventions - we'll need plenty of room on the left for labels
        var margin = {
            top: 15,
            right: 100,
            bottom: 15,
            left: 100
        };

        var width = window.innerWidth  - margin.left - margin.right,
            height = window.innerHeight- margin.top - margin.bottom;

        var svg = d3.select("#graphic").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 x = d3.scale.linear()
            .range([0, width])
            .domain([0, d3.max(data, function (d) {
                return d.value;
            })]);

        var y = d3.scale.ordinal()
            .rangeRoundBands([height, 0], .1)
            .domain(data.map(function (d) {
                return d.name;
            }));

        //make y axis to show bar names
        var yAxis = d3.svg.axis()
            .scale(y)
            //no tick marks
            .tickSize(0)
            .orient("left");

        var gy = svg.append("g")
            .attr("class", "y axis")
            .call(yAxis)

        var bars = svg.selectAll(".bar")
            .data(data)
            .enter()
            .append("g")

        //append rects
        bars.append("rect")
            .attr("class", "bar")
            .attr("y", function (d) {
                return y(d.name);
            })
            .attr("height", y.rangeBand())
            .attr("x", 0)
            .attr("width", function (d) {
                return x(d.value);
            })
        //add a value label to the right of each bar
        bars.append("text")
            .attr("class", "label")
            //y position of the label is halfway down the bar
            .attr("y", function (d) {
                return y(d.name) + y.rangeBand() / 2 + 4;
            })
            //x position is 3 pixels to the right of the bar
            .attr("x", function (d) {
                return x(d.value);
            })
            .style('fill', 'darkGray')
            .text(function (d) {
                return d.value;
            });
        
    </script>

</body>

</html>

В этом мне нужно добавить маркер, подобный этому изображению Required implementation

Мысль об использовании гистограммы с накоплением, но это не будет работать в этом случае, поскольку задняя строка дает все значение, а выделенный цвет дает искомый термин в этом документе, и он может повторяться несколько раз для одной и той же строки.

1 Ответ

0 голосов
/ 14 декабря 2018

Вы можете добавить второй набор баров и назначить x и width на основе начальной и конечной точек маркера.

Предполагая xValue в качестве начальной точки и slength в качестве начальнойширина выделения, вот соответствующий код для добавления маркеров:

// add markers
bars.append("rect")
    .attr("class", "highlight")
    .attr("y", function (d) {
        return y(d.name);
    })
    .attr("height", y.rangeBand())
    .attr("x", function (d) {
        return x(d.xValue);
    })
    .attr("width", function (d) {
        return x(d.xValue + d.slength);
    });

Фрагмент кода (включая подсветку еще в нескольких строках):

<!DOCTYPE html>
<html>

<head>
    <meta charset='utf-8' />
    <title>Simple Bar chart</title>
    <script src="https://d3js.org/d3.v3.min.js" charset="utf-8"></script>
    <style>
        body {
            font-family: "Arial", sans-serif;
        }
        
        .bar {
            fill: #5f89ad;
        }
         .highlight {
            fill: #ff0;
        }
        .axis {
            font-size: 13px;
        }
        
        .axis path,
        .axis line {
            fill: none;
            display: none;
        }
        
        .label {
            font-size: 13px;
        }
    </style>

</head>

<body>

    <div id="graphic"></div>

    <script>
        var data = [{
                "name": "Case 01",
                "value": 2000,
                "xValue": 500,
                "slength": 100,
        },
            {
                "name": "Case 02",
                "value": 1290,
                "xValue": 300,
                "slength": 50,
						},
            {
                "name": "Case 03",
                "value": 19000,
                "xValue": 1000,
                "slength": 300,
						},
            {
                "name": "Case 04",
                "value": 5000,
        },
            {
                "name": "Case 05",
                "value": 1600,
        },
            {
                "name": "Case 06",
                "value": 2600,
        },
            {
                "name": "Case 07",
                "value": 3000,
        },
	{
                "name": "Case 08",
                "value": 7000,
        },
            {
                "name": "Case 09",
                "value": 3290,
        },
            {
                "name": "Case 10",
                "value": 12000,
        },
            {
                "name": "Case 11",
                "value": 10000,
        },
            {
                "name": "Case 12",
                "value": 11600,
        },
            {
                "name": "Case 13",
                "value": 5600,
        },
            {
                "name": "Case 14",
                "value": 6000,
        },{
                "name": "Case 15",
                "value": 8600,
        },
            {
                "name": "Case 16",
                "value": 4280,
        },
            {
                "name": "Case 17",
                "value": 9000,
        },
            {
                "name": "Case 18",
                "value": 5000,
        },
            {
                "name": "Case 19",
                "value": 4300,
        },
            {
                "name": "Case 20",
                "value": 2600,
        },
            {
                "name": "Case 21",
                "value": 6700,
        },{
                "name": "Case 22",
                "value": 12000,
        },
            {
                "name": "Case 23",
                "value": 8290,
        },
            {
                "name": "Case 24",
                "value": 8000,
        },
            {
                "name": "Case 25",
                "value": 7600,
        },
            {
                "name": "Case 26",
                "value": 1600,
        },
            {
                "name": "Case 27",
                "value": 5500,
        },
            {
                "name": "Case 28",
                "value": 4400,
        },{
                "name": "Case 29",
                "value": 8900,
        },
            {
                "name": "Case 30",
                "value": 6790,
        },
            {
                "name": "Case 31",
                "value": 11000,
        },
            {
                "name": "Case 32",
                "value": 5000,
        },
            {
                "name": "Case 33",
                "value": 6600,
        },
            {
                "name": "Case 34",
                "value": 7700,
        },
            {
                "name": "Case 35",
                "value": 3000,
        }];

        //sort bars based on value
        data = data.sort(function (a, b) {
            return d3.descending(a.name, b.name);
        })

        //set up SVG using margin conventions - we'll need plenty of room on the left for labels
        var margin = {
            top: 15,
            right: 100,
            bottom: 15,
            left: 100
        };

        var width = window.innerWidth  - margin.left - margin.right,
            height = window.innerHeight- margin.top - margin.bottom;

        var svg = d3.select("#graphic").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 x = d3.scale.linear()
            .range([0, width])
            .domain([0, d3.max(data, function (d) {
                return d.value;
            })]);

        var y = d3.scale.ordinal()
            .rangeRoundBands([height, 0], .1)
            .domain(data.map(function (d) {
                return d.name;
            }));

        //make y axis to show bar names
        var yAxis = d3.svg.axis()
            .scale(y)
            //no tick marks
            .tickSize(0)
            .orient("left");

        var gy = svg.append("g")
            .attr("class", "y axis")
            .call(yAxis)

        var bars = svg.selectAll(".bar")
            .data(data)
            .enter()
            .append("g")

        //append rects
        bars.append("rect")
            .attr("class", "bar")
            .attr("y", function (d) {
                return y(d.name);
            })
            .attr("height", y.rangeBand())
            .attr("x", 0)
            .attr("width", function (d) {
                return x(d.value);
            })
        //add a value label to the right of each bar
        bars.append("text")
            .attr("class", "label")
            //y position of the label is halfway down the bar
            .attr("y", function (d) {
                return y(d.name) + y.rangeBand() / 2 + 4;
            })
            //x position is 3 pixels to the right of the bar
            .attr("x", function (d) {
                return x(d.value);
            })
            .style('fill', 'darkGray')
            .text(function (d) {
                return d.value;
            });

				// add markers
        bars.append("rect")
            .attr("class", "highlight")
            .attr("y", function (d) {
                return y(d.name);
            })
            .attr("height", y.rangeBand())
            .attr("x", function (d) {
            	return x(d.xValue);
            })
            .attr("width", function (d) {
                return x(d.xValue + d.slength);
            })        
    </script>

</body>

</html>

И скриптовая ссылка: http://jsfiddle.net/wc4q3r1y/

Надеюсь, это поможет.

...