【问题标题】:How to add marking in bar chart using d3如何使用 d3 在条形图中添加标记
【发布时间】:2018-12-14 09:32:46
【问题描述】:

我需要使用 d3 创建一个条形图,并在起点和终点之间突出显示(如标记)。这是我的代码 sn-p。

<!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>

在此,我需要添加一个类似于此图像的标记

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

【问题讨论】:

  • 为标记添加第二组条,并使用 xScale 根据标记开始结束值确定矩形的 xwidth

标签: javascript d3.js bar-chart


【解决方案1】:

您可以添加第二组条形图并根据标记的起点和终点分配xwidth

假设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);
    });

代码 sn-p(包括多行中的突出显示):

<!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/

希望这会有所帮助。

【讨论】:

  • 非常感谢,Shashank 这就是我要找的。​​span>
猜你喜欢
  • 1970-01-01
  • 2012-10-25
  • 1970-01-01
  • 2019-03-16
  • 1970-01-01
  • 1970-01-01
  • 2016-12-03
  • 2023-04-04
  • 1970-01-01
相关资源
最近更新 更多