javascript - D3.JS 条形图圆角
问题描述
我有一个项目,我需要在其中可视化带有圆角的条形图。我使用 D3.JS 第 6 版创建了一个图表,并在网上找到了一些关于如何添加圆角的文档。但我似乎没有让代码工作。所有在线文档的工作原理相同。
最好的文档之一可以在这里找到:文档
d
他们通过使用以下代码向每个条添加一个属性来应用此边框:
.attr(
"d",
item => `
M${x(item.name)},${y(item.value) + ry}
a${rx},${ry} 0 0 1 ${rx},${-ry}
h${x.bandwidth() - 2 * rx}
a${rx},${ry} 0 0 1 ${rx},${ry}
v${height - y(item.value) - ry}
h${-x.bandwidth()}Z
`
)
这是我的项目的完整代码,其中包含工作条和上面用于添加圆角的代码:
<!DOCTYPE html>
<html>
<head>
<title></title>
<script src="https://unpkg.com/vue"></script>
<script src="https://d3js.org/d3.v6.js"></script>
</head>
<body>
<div class="p-3 flex flex-col" id="one">
<div class="w-full flex-1">
<div id="my_dataviz"></div>
</div>
</div>
<script>
new Vue({
el: '#one',
data: {
type: Array,
required: true,
},
mounted() {
var data = [
{ key: "One", value: 33 },
{ key: "Two", value: 30 },
{ key: "Three", value: 37 },
{ key: "Four", value: 28 },
{ key: "Five", value: 25 },
{ key: "Six", value: 15 }
];
// set the dimensions and margins of the graph
var margin = { top: 20, right: 20, bottom: 30, left: 40 },
width = 500 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
// set the ranges
var x = d3
.scaleBand()
.range([0, width])
.padding(0.1);
var y = d3.scaleLinear().range([height, 0]);
// append the svg object to the body of the page
// append a 'group' element to 'svg'
// moves the 'group' element to the top left margin
var svg = d3
.select("#my_dataviz")
.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 + ")");
// format the data
data.forEach(function(d) {
d.value = +d.value;
});
// Scale the range of the data in the domains
x.domain(
data.map(function(d) {
return d.key;
})
);
y.domain([
0,
d3.max(data, function(d) {
return d.value;
})
]);
//Defenining the tooltip div
let tooltip = d3
.select("body")
.append("div")
.attr("class", "tooltip")
.style("position", "absolute")
.style("top", 0)
.style("left", 0)
.style("opacity", 0);
// append the rectangles for the bar chart
const rx = 12;
const ry = 12;
svg
.selectAll(".bar")
.data(data)
.enter()
.append("rect")
.attr("class", "bar")
.attr("x", function(d) {
return x(d.key);
})
.attr("width", x.bandwidth())
.attr("y", function(d) {
return y(d.value);
})
.attr("height", function(d) {
return height - y(d.value);
})
.attr("fill", "#206BF3")
.attr(
"d",
item => `
M${x(item.name)},${y(item.value) + ry}
a${rx},${ry} 0 0 1 ${rx},${-ry}
h${x.bandwidth() - 2 * rx}
a${rx},${ry} 0 0 1 ${rx},${ry}
v${height - y(item.value) - ry}
h${-x.bandwidth()}Z
`
)
.on("mouseover", (e, i) => {
d3.select(e.currentTarget).style("fill", "red");
tooltip
.transition()
.duration(200)
.style("opacity", 0.9);
tooltip
.html(
`<div><h1>${i.key} 2020</h1><p>${this.addPointsToEveryThousand(
i.value
)} kWh</p></div>`
)
.style("left", e.pageX + "px")
.style("top", e.pageY - 28 + "px");
})
.on("mouseout", e => {
d3.select(e.currentTarget).style("fill", "#206BF3");
tooltip
.transition()
.duration(500)
.style("opacity", 0);
});
// add the x Axis
svg
.append("g")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x));
// add the y Axis
svg.append("g").call(d3.axisLeft(y));
},
methods: {
addPointsToEveryThousand(amount) {
return amount.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ".");
}
}
});
</script>
</body>
</html>
解决方案
您可以向矢量图形添加样式,并可以添加边框或对其进行更改。
请检查这是否是您要查找的内容。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<!DOCTYPE html>
<html>
<head>
<title></title>
<script src="https://unpkg.com/vue"></script>
<script src="https://d3js.org/d3.v6.js"></script>
</head>
<body>
<div class="p-3 flex flex-col" id="one">
<div class="w-full flex-1">
<div id="my_dataviz"></div>
</div>
</div>
<script>
new Vue({
el: '#one',
data: {
type: Array,
required: true,
},
mounted() {
var data = [
{ key: "One", value: 33 },
{ key: "Two", value: 30 },
{ key: "Three", value: 37 },
{ key: "Four", value: 28 },
{ key: "Five", value: 25 },
{ key: "Six", value: 15 }
];
// set the dimensions and margins of the graph
var margin = { top: 20, right: 20, bottom: 30, left: 40 },
width = 500 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
// set the ranges
var x = d3
.scaleBand()
.range([0, width])
.padding(0.1);
var y = d3.scaleLinear().range([height, 0]);
// append the svg object to the body of the page
// append a 'group' element to 'svg'
// moves the 'group' element to the top left margin
var svg = d3
.select("#my_dataviz")
.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})`);
const xAxis = d3.axisBottom(x);
const yAxis = d3.axisLeft(y).ticks(5);;
// format the data
data.forEach(function(d) {
d.value = +d.value;
});
// Scale the range of the data in the domains
x.domain(
data.map(function(d) {
return d.key;
})
);
y.domain([
0,
d3.max(data, function(d) {
return d.value;
})
]);
//Defenining the tooltip div
let tooltip = d3
.select("body")
.append("div")
.attr("class", "tooltip")
.style("position", "absolute")
.style("top", 0)
.style("left", 0)
.style("opacity", 0);
// append the rectangles for the bar chart
const rx = 12;
const ry = 12;
svg
.selectAll(".bar")
.data(data)
.enter()
.append("path")
.attr("class", "bar")
.attr("x", function(d) {
return x(d.key);
})
.attr("width", x.bandwidth())
.attr("y", function(d) {
return y(d.value);
})
.attr("height", function(d) {
return height - y(d.value);
})
.attr("fill", "#206BF3")
.attr(
"d",
item => `
M${x(item.key)},${y(item.value) + ry}
a${rx},${ry} 0 0 1 ${rx},${-ry}
h${x.bandwidth() - 2 * rx}
a${rx},${ry} 0 0 1 ${rx},${ry}
v${height - y(item.value) - ry}
h${-x.bandwidth()}Z
`
)
.on("mouseover", (e, i) => {
d3.select(e.currentTarget).style("fill", "red");
tooltip
.transition()
.duration(200)
.style("opacity", 0.9);
tooltip
.html(
`<div><h1>${i.key} 2020</h1><p>${this.addPointsToEveryThousand(
i.value
)} kWh</p></div>`
)
.style("left", e.pageX + "px")
.style("top", e.pageY - 28 + "px");
})
.on("mouseout", e => {
d3.select(e.currentTarget).style("fill", "#206BF3");
tooltip
.transition()
.duration(500)
.style("opacity", 0);
});
// add the x Axis
svg
.append("g")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x));
// add the y Axis
svg.append("g").call(d3.axisLeft(y));
},
methods: {
addPointsToEveryThousand(amount) {
return amount.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ".");
}
}
});
</script>
</body>
</html>
</body>
</html>
我只添加了这个属性来使它工作
M${x(item.key)},${y(item.value) + ry}
a${rx},${ry} 0 0 1 ${rx},${-ry}
h${x.bandwidth() - 2 * rx}
a${rx},${ry} 0 0 1 ${rx},${ry}
v${height - y(item.value) - ry}
h${-x.bandwidth()}Z
推荐阅读
- r - 如何使用 `exams2nops` 在 `exams` 生成的 pdf 中添加一行?
- swift - 协议的二级实现被忽略,有利于默认实现
- node.js - Discord.js 机器人:组织命令
- bash - libcurl c 代码中的 CURLOPT_COOKIEFILE 选项
- java - 使用 Java 的 Apache Sedona (Geospark) SQL:SQL 语句期间出现 ClassNotFoundException
- android - 是否可以在不需要用户更新到新版本的情况下对已发布的应用程序进行小的更改
- winapi - “自定义”键盘布局的安全 KLID?
- python-3.x - 如果列表中存在正确的值,则更改列中的值(熊猫)
- elasticsearch - 在更新查询弹性搜索无痛中获取日期值
- reporting-services - DistinctCount 正在计算 ssrs 中的空间