【问题标题】:How to Add Multiline Text Tooltips in Bar Chart D3 JS如何在条形图 D3 JS 中添加多行文本工具提示
【发布时间】:2020-10-24 00:49:05
【问题描述】:

我正在寻找一种如何使用 d3.v3.min.js 在一个框工具提示中添加多行文本的方法。我的插图行为是这样的:

而我做的代码是这样的:

HTMLCSSJavascript

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>

有没有人可以帮助解决我的问题?因为我需要在工具提示框中获取多行文本的代码。

【问题讨论】:

    标签: html css d3.js svg


    【解决方案1】:

    使用 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 here 中对此进行了模拟 - 它可能缺少您的一些代码,如果是这样,我们深表歉意 - 但如果您想使用代码,它应该提供一个好主意如何将其合并。如果您有任何问题,请告诉我!如果您也需要,您应该可以从here 获得更多信息。

    【讨论】:

    • 哇,真是个好朋友。对我很有帮助。是的,它必须缺少代码。我认为 d3.v3.min.js 无法在工具提示中声明 .html 。谢谢朋友。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-11-24
    • 2013-09-15
    • 1970-01-01
    • 2013-12-02
    • 1970-01-01
    • 2018-05-12
    • 2017-08-12
    相关资源
    最近更新 更多