d3.js tooltips on path

℡╲_俬逩灬. 提交于 2019-12-30 07:32:48

问题


a lot of what I've read regarding d3.js and tooltips makes reference to having individual points on a graph.

instead, my graph graph is using one long path to render. I was wondering how I would apply mouseover methods to such a path, where I would then tie a tooltip div accordingly

http://jsfiddle.net/ericps/xJ3Ke/6/

svg.append("path")
.attr("class", "area")
.attr("clip-path", "url(#clip)")
.style("fill", "url(#gradient)");

回答1:


You can set a layer of invisible objects representing each point you'd like to have a tooltip for, and add mouse interactions to those objects.

I've updated your jsfiddle with the following -

svg.selectAll("circle")
    .data(data)
  .enter().append("circle")
    .attr("r", 5)
    .style("fill","none")
    .style("stroke","none")
    .style("pointer-events","all")
  .append("title")
    .text(function(d) { return "Date: " + formatDate2(d.date) + " Value: " + d.value; });

This adds a circle element to each data point, and a title element to each of those circles. Note that the "pointer-events","all" allows the mouse interactions even though the elements are invisible

full jsfiddle here: http://jsfiddle.net/xJ3Ke/9/




回答2:


Below is a simple Tooltip class I used.

/**
 * Tooltip helper.
 *
 * Copyright © 2014 Maciej Nux Jaros.
 * License: CC-BY or MIT.
 */
function Tooltip() {
    var _tooltip = this;
    var _container = null;

    /**
     * Tootltip class name (use if you want more then one tooltip).
     * @type String
     */
    this.className = 'tooltip';
    /**
     * Width of the rect.
     * @type String
     */
    this.width = "100";
    /**
     * Height of the rect.
     * @type String
     */
    this.height = "20";
    /**
     * Tootltip source attribute.
     * @type String
     */
    this.textSourceAttrName = 'data-title';
    /**
     * Style of background rectangle.
     * @type String
     */
    this.rectStyle = "opacity:0.9;fill:#ffffff;fill-opacity:1;stroke:#ffcc00;stroke-width:3;";

    /**
     * Init tooltip elements and append to container.
     * 
     * @param {D3} container D3 container element - e.g. main group (chart container).
     */
    this.init = function(container) {
        _container = container;

        container.append("g")
            .attr("class", _tooltip.className)
            .attr("style", "display:none")
            .append("rect")
                .attr("style", _tooltip.rectStyle)
                .attr("width", _tooltip.width)
                .attr("height", _tooltip.height)
                .attr("rx", "10")
                .attr("ry", "10")
        ;
        container.selectAll("." + _tooltip.className)
            .append("text")
                .attr("x", 5)
                .attr("y", 10)
                .attr("dy", ".35em")
        ;
    };

    /**
     * Show tooltip (title) for given point
     *
     * run e.g. onmouseover
     *
     * @param {Element} point Circle element.
     */
    this.show = function(point) {
        var text = point.getAttribute(_tooltip.textSourceAttrName);
        var x = parseFloat(point.getAttribute('cx')) + 10;
        var y = parseFloat(point.getAttribute('cy')) + 5;
        _container
            .selectAll("." + _tooltip.className)
            .attr("style", "")
            .attr("transform", function() { return "translate(" + x + "," + y + ")"; })
        ;
        _container
            .selectAll("." + _tooltip.className + " text")
            .text(function() { return text; })
        ;
    };

    /**
     * Hide tooltip.
     *
     * run e.g. onmouseout
     */
    this.hide = function() {
        _container
            .selectAll("." + _tooltip.className)
            .attr("style", "display:none")
        ;
    };
}

Usage (assuming you have countries data series with date on X and share on Y):

// points
for (var i=0; i<countries.length; i++) {
    var points = svg.selectAll(".points" + i)
        .data(countries[i].values)
        .enter()
        .append("g")
            .attr("class", ".points" + i)
    ;
    // visible points
    points
        .append("circle")
            .attr("class", "point")
            .attr("stroke", "none")
            .attr("fill", "black")
            .attr("cx", function(d, i) { return x(d.date) })
            .attr("cy", function(d, i) { return y(d.share) })
            .attr("r", function(d, i) { return 2 })
    ;
    // bigger (almost) invisible points for tooltip
    points
        .append("circle")
            .attr("class", "blank-point")
            .attr("style", "opacity:0.05;fill-opacity:1;")
            .style("fill", function(d) { return color(countries[i].name); })
            .attr("cx", function(d, i) { return x(d.date) })
            .attr("cy", function(d, i) { return y(d.share) })
            .attr("r", function(d, i) { return 6 })
            .attr("data-title", function(d, i) { return formatDate(d.date) +'; '+ d.share })
            .attr("onmouseover", "tooltip.show(this)")
            .attr("onmouseout", "tooltip.hide()")
    ;
}

// prepare tooltip
tooltip.init(svg);

Note make sure you prepare tooltip after other things on the chart or it will not be visible. Also make sure you have enough room on the right of the chart (e.g. set right margin of the chart to 100 or more).



来源:https://stackoverflow.com/questions/15235944/d3-js-tooltips-on-path

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!