html - 如何在条形图 D3 JS 中添加多行文本工具提示
问题描述
我正在寻找一种如何使用 d3.v3.min.js 在一个框工具提示中添加多行文本的方法。我的插图行为是这样的:
我制作的代码是这样的:
HTML , CSS , Javascript
function responsivefy(svg) {
// get container + svg aspect ratio
var container = d3.select(svg.node().parentNode),
width = parseInt(svg.style("width")),
height = parseInt(svg.style("height")),
aspect = width / height;
// add viewBox and preserveAspectRatio properties,
// and call resize so that svg resizes on inital page load
svg.attr("viewBox", "0 0 " + width + " " + height)
.attr("perserveAspectRatio", "xMinYMid")
.call(resize);
d3.select(window).on("resize." + container.attr("id"), resize);
// get width of container and resize svg to fit it
function resize() {
var targetWidth = parseInt(container.style("width"));
svg.attr("height", Math.round(targetWidth / aspect));
svg.attr("width", targetWidth);
}
}
var arrData = [
{"category":"Diversity & Inlusion 1", "actual":4.2, "target":5, "prediction":40, "skala":"20%"},
{"category":"Image 1", "actual":4.5, "target":4.2,"prediction":60, "skala":"40%"},
{"category":"Image 2", "actual":4.1, "target":4,"prediction":80, "skala":"60%"},
{"category":"Job Security 1", "actual":4.4, "target":4.3,"prediction":60, "skala":"100%"},
{"category":"Job Security 2", "actual":4.4, "target":4.3,"prediction":40, "skala":"100%"},
{"category":"Job Security 3", "actual":4.4, "target":4.3,"prediction":20, "skala":"100%"},
{"category":"Image 3", "actual":4.4, "target":4.3,"prediction":10, "skala":"100%"},
{"category":"Diversity & Inlusion 2", "actual":4.4, "target":4.3,"prediction":30, "skala":"100%"},
{"category":"Values", "actual":4.4, "target":4.3,"prediction":75, "skala":"100%"},
{"category":"Collaboration", "actual":4.4, "target":4.3,"prediction":45, "skala":"100%"}
];
//console.log(arrData);
//set up svg using margin conventions - we'll need plenty of room on the left for labels
var margin = {
top: 15, right: 95, bottom: 15, left: 60
};
var marginBar2 = {
top:10
};
var width = 650 - margin.left - margin.right;
var height = 768 - margin.top - margin.bottom;
var svgColor = "white";
var barHeight = 200;
//Create Main SVG
var svg = d3.select("body").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.style("background-color", svgColor);
// .call(responsivefy);
//Create xScale and yScale
var xScale1 = d3.scale.linear()
.range([0, width * 0.70])
.domain([0, d3.max(arrData, function (d) {
return d.prediction;
})]);
var xScale2 = d3.scale.linear()
.range([0, width * 0.70])
.domain([0, d3.max(arrData, function (d) {
return d.target;
})]);
var xScale3 = d3.scale.ordinal()
.rangeRoundBands([0, width * 0.93])
.domain(arrData.map(function (d) {
return d.skala;
}));
var yScale = d3.scale.ordinal()
.rangeRoundBands([0, height])
.domain(arrData.map(function (d) {
return d.category;
}));
//Make yAxis to Show Category
var yAxis = d3.svg.axis()
.scale(yScale)
.tickSize(0)
.orient("left");
var gyAxis = svg.append("g")
//.attr("class", "y axis")
.attr("transform", "translate(" + width * 0.35 + "," + height * 0 + ")")
.style("text-anchor", "start")
.style("font-size", 12)
.style("font-weight", "bold")
.style("fill", "#212121")
.call(yAxis);
//Make xAxis to Show Category
// var xAxis = d3.svg.axis()
// .scale(xScale3)
// .tickSize(5)
// .orient("bottom");
// var gxAxis = svg.append("g")
// .attr("class", "x axis")
// .style("font-size", 14)
// .style("font-weight", "bold")
// .style("fill", "#212121")
// .attr("transform", "translate(" + width * 0.385 + "," + height * 1 + ")")
// .call(xAxis);
var bars1 = svg.selectAll(".bar")
.data(arrData).enter()
.append("g")
.attr("transform", "translate(" + width * 0.50 + "," + 0 + ")");
bars1.append("rect")
.attr("class", "bar")
.attr("y", function (d) {
return yScale(d.category);
})
.attr("height", barHeight - 140)
.attr("x", 0)
// .style("fill", "#c0c0c0")
.attr("width", function(d){
return xScale2(d.target);
})
.on("mouseover", function(){
tooltip1.style("display", null);
})
.on("mouseout", function(){
tooltip1.style("display", "none");
})
.on("mousemove", function(d){
var xPos = d3.mouse(this)[0] - 10;
var yPos = d3.mouse(this)[1] - 15;
tooltip1.attr("transform", "translate(" + xPos + "," + yPos +")");
tooltip1.selectAll("text").text("DI4");
tooltip1.selectAll("rect")
.attr("width", 250)
.attr("width", (function(d) {
return this.parentNode.getBBox().width;
}));
});
var bars2 = svg.selectAll(".bar2nd")
.data(arrData).enter()
.append("g")
.attr("transform", "translate(" + width * 0.50 + "," + marginBar2.top + ")");
bars2.append("rect")
.attr("class", "bar2nd")
.attr("y", function (d) {
return yScale(d.category);
})
.attr("height", barHeight - 160)
.attr("x", 0)
.attr("width", function (d) {
return xScale1(d.prediction);
})
.on("mouseover", function(){
tooltip2.style("display", null);
})
.on("mouseout", function(){
tooltip2.style("display", "none");
})
.on("mousemove", function(d){
var xPos = d3.mouse(this)[0] - 10;
var yPos = d3.mouse(this)[1] - 15;
tooltip2.attr("transform", "translate(" + xPos + "," + yPos +")");
tooltip2.selectAll("text").html("DI3");
tooltip2.selectAll("rect")
.attr("width", 250)
.attr("width", (function(d) {
return this.parentNode.getBBox().width;
}));
});
var barValue1 = svg.selectAll(".barValue1")
.data(arrData).enter()
.append("g")
.attr("transform", "translate(" + width * 0.40 + "," + height * 0.055 + ")");
barValue1.append("text")
.attr("class", "barValue1")
.attr("y", function (d) {
return yScale(d.category);
})
.attr("x", 0)
.style("font-size", 18)
.style("font-weight", "bold")
.style("fill", "#212121")
.html(function(d){
return d3.format(",.2r")(d.actual);
});
var barValue2 = svg.selectAll(".barValue2")
.data(arrData).enter()
.append("g")
.attr("transform", "translate(" + width * 0.51 + "," + height * 0.055 + ")");
barValue2.append("text")
.attr("class", "barValue2")
.attr("y", function (d) {
return yScale(d.category);
})
.attr("x", 0)
.style("font-size", 18)
// .style("font-weight", "bold")
.style("fill", "white")
.text(function(d){
return d3.format(".2%")(d.prediction / 100);
});
var tooltip1 = svg.selectAll("g.tooltip1")
.data(arrData)
.enter()
.append("g")
.attr("class", "tooltip")
.style("display", "none");
tooltip1.append("rect")
// .attr("width", width * 0.7)
.attr("height", height * 0.2)
.style("fill", "white")
.style("stroke", "#969696")
.attr("stroke-width",1)
.style("opacity", 1);
tooltip1.append("text")
.attr("id", "txt1")
.attr("x", width * 0.05)
.attr("dy", height * 0.05)
.attr("font-size", 18)
.attr("font-weight", "bold");
var tooltip2 = svg.selectAll("g.tooltip1")
.data(arrData)
.enter()
.append("g")
.attr("class", "tooltip")
.style("display", "none");
tooltip2.append("rect")
// .attr("width", width * 0.7)
.attr("height", height * 0.2)
.style("fill", "white")
.style("stroke", "#969696")
.attr("stroke-width",1)
.style("opacity", 1);
tooltip2.append("text")
.attr("id", "txt1")
.attr("x", width * 0.05)
.attr("dy", height * 0.05)
.attr("font-size", 18)
.attr("font-weight", "bold");
body{
font-family: "Arial", sans-serif;
}
.bar{
fill: #c0c0c0;
}
.bar:hover{
fill:rgb(95, 109, 148);
}
.bar2nd{
fill:#00315b;
}
.bar2nd:hover{
fill:#3e73b8;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.17/d3.min.js"></script>
有没有人可以帮助解决我的问题?因为我需要在工具提示框中获取多行文本的代码。
解决方案
使用 div 而不是 svg rects 附加工具提示可能更直接 - 例如,如果您添加:
var tooltip = d3.select("body").append("div")
.attr("class", "tooltip")
.style("opacity", 0);
在您的代码中,您可以使其出现和消失,并使用以下命令添加多行文本:
.on("mouseover", function(d){
var xPos = d3.mouse(this)[0];
var yPos = d3.mouse(this)[1];
tooltip.style("left", xPos + "px")
.style("top", yPos + "px")
.html("<p class='tooltip'>" + d.category + "<br><br>Line 2<br><br>Etc</p>")
.transition().delay(200).style("opacity", 0.9);
})
.on("mouseout", function(){
tooltip.transition().delay(0).style("opacity", 0);
})
您可以添加与使用 CSS 属性之前相同的样式,如下所示:
div.tooltip {
width: 200px;
height: 125px;
background-color: white;
border: 1px solid #969696;
position: absolute;
}
p.tooltip {
font-size: 18;
font-weight: 1em;
padding-left: 10px;
}
我在这里的 JSFiddle 中对此进行了模拟-它可能缺少您的一些代码,如果是这样,我们深表歉意-但是如果您想使用该代码,它应该提供一个好主意如何将其合并。如果您有任何问题,请告诉我!如果您也需要,您应该能够从这里获得更多信息。
推荐阅读
- localhost - 够奇怪的!http://laravel6.com 指向本地主机 127.0.0.1 - 我办公室的每个系统
- javascript - Colspan 和 Rowspan 使用 JSPDF AutoTable 示例
- r - 重新排列R中的字符串列
- python - 将 VTK 窗口加载到 PyQT 窗口时出现问题
- python - 字符串到 JSON 到 BytesIO
- r - 用 apply 函数替换 for 循环
- sqlite - 离子 Sqlite SELECT IN 语句不返回正确的结果
- javascript - 如何在 Puppeteer 的 `await page.evaluate(indexTotal => {` 中使用我现有的函数 global.parseData(id, name, url)?
- stripe-payments - 如何对前端的 Stripe PaymentIntent 成功 webhook 做出反应
- java - 为什么我不能使用过滤器作为我在流中的最后一步