javascript - 如何使用 d3 在条形图中添加标记

标签 javascript d3.js bar-chart

我需要使用 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 的标记

考虑使用堆叠条形图,但在这种情况下它不起作用,因为后面的线给出了整个值,突出显示的颜色给出了该文档中的搜索术语,并且同一行可能会重复几次.

最佳答案

您可以添加第二组条形图,并根据标记的起点和终点指定 x宽度

假设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>

还有一个 fiddle 链接:http://jsfiddle.net/wc4q3r1y/

希望这有帮助。

关于javascript - 如何使用 d3 在条形图中添加标记,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53776899/

相关文章:

javascript - Highcharts - 没有意义的工具提示\十字线

javascript - 使用 PhantomJS 生成单页 .pdf

javascript - 我想在服务器响应之间加载本地存储(使 javascript 代码同步)

javascript - 如何在元素上设置默认 focus()

javascript - d3 - 对象恒常性、关键功能和(更新、进入、退出)

java - JFreeChart 更改现有条形图中的数据

r - 在水平条形图中的刻度标签之间添加部分标题

javascript - d3.js 中单个节点内的复杂符号,其中符号依赖于数据

javascript - 如何在D3.js中绘制JSON列表?

javascript - 创建矩形后如何动态附加文本