简体   繁体   English

D3中有两个数据源的工具提示问题

[英]Tooltip issue with two data sources in d3

I have a d3 chart which is generated from some json that is, in turn, generated by php. 我有一个d3图表,它是从json生成的,而json是由php生成的。 All of that works well -- the php correctly formats the json and the chart displays properly. 所有这些都很好-php正确设置了json格式,图表正确显示。 It can be seen here , and I'm including the full code for the javascript portion below: 可以在这里看到,我在下面包含了javascript部分的完整代码:

            var margin = {top: 50, right: 150, bottom: 50, left: 150},
            w = 2500 - margin.left - margin.right,
            h = 500 - margin.top - margin.bottom;


var json = <?php echo $json; ?>;

console.log(json);

d3.json("MM_chart.json", function(error, json) {
  if (error) throw error;

           var items = json.items;

           var locations = json.locations;

           var directions = json.stage_directions;

           console.log(items);
           console.log(locations);
           console.log(directions);

            var stage_directions = ([44, 49, 114, 140, 209, 217, 249, 257, 265, 277, 305, 334, 358, 381, 398, 409, 440, 470, 491, 547, 555, 564, 572, 587, 614, 630, 640, 691, 704, 725, 743, 775, 793, 818, 823, 841, 845, 868, 872, 888, 902, 910, 920, 925, 963, 993, 1005, 1023, 1031, 1047, 1061, 1096, 1125, 1133, 1143, 1178, 1210, 1228, 1281, 1293, 1336, 1349, 1376, 1395, 1439, 1446, 1454, 1538, 1554, 1562, 1578, 1598, 1610, 1618, 1642, 1646, 1716, 1725, 1743, 1781, 1791, 1797, 1843, 1863, 1887, 1915, 1923, 1939 ,1972, 1989, 2019, 2031, 2039, 2045, 2073, 2085, 2101, 2123]);

            var x = d3.scale.linear()
            .domain([0, 2200])
            .range([0, w]);

            var y = d3.scale.ordinal()
            .domain(locations.map(function(d) {return d["location"];})) 
            .rangeBands([0, h]);

            var yAxis = d3.svg.axis()
            .scale(y)
            .orient("left");

            var xAxis = d3.svg.axis()
            .scale(x)
            .orient("bottom");

            var tip = d3.tip()
            .attr('class', 'd3-tip')
            .offset([-10, 0])
            .html(function(d, i) {return console.log(d.line_text) + "<strong>(" + d.starting_line + ")</strong> <i>" + d.character + "</i>: " + d.line_text;});

            var stage_tip = d3.tip()
            .attr('class', 'd3-tip')
            .offset([-10, 0])
            .html(function(d, i) {return console.log(d.direction_text) + "<strong>(" + d.line_after + ") s.d.</strong> <i>" + d.direction_text;});

            var svg = d3.select("body").append("svg")
            .attr("width", w + margin.left + margin.right)
            .attr("height", h + margin.top + margin.bottom)
            .append("g")
            .attr("transform", "translate(" + margin.left + "," + margin.top + ")");


            svg.append("text") 
            .attr("transform", "translate(" + (w / 2) + " ," + (h + margin.bottom - 5) +")")
            .style("text-anchor", "middle")
            .text("Line Number");

            var stage_bars = svg.selectAll(".stage_bar")
                .data(directions)
                .enter()
                .append("rect")
                .attr("class", "overlay")
                .attr("class", function(d, i) {return "stage_bar " + d.direction_text;})
                .attr("x", function(d, i) {return d.line_after;})
                .attr("width", 1)
                .attr("height", h)
                .style("fill", "black")
                .style("opacity",0.3)
                .call(stage_tip)
                .on('mouseover', stage_tip.show)
                .on('mouseout',stage_tip.hide);

            svg.append("rect")
            .attr("class", "overlay")
            .attr("x",1)
            .attr("width", 1133)
            .attr("height", h)
            .style ("fill", "red")
            .style ("opacity", 0.1);

            svg.append("rect")
            .attr("class", "overlay")
            .attr("x",1133)
            .attr("width", 857)
            .attr("height", h)
            .style ("fill", "yellow")
            .style ("opacity", 0.1);

            svg.append("rect")
            .attr("class", "overlay")
            .attr("x",1990)
            .attr("width", 134)
            .attr("height", h)
            .style ("fill", "green")
            .style ("opacity", 0.1);

          svg.append("rect")
          .attr("class", "overlay")
          .attr("x",5)
          .attr("y", 10)
          .attr("width", 485)
          .attr("height", 155)
          .style ("fill", "aliceblue")
//              .style ("opacity", 0.1);

            svg.append("g")
            .attr("class", "x axis")
            .attr("transform", "translate(0," + h + ")")
            .call(xAxis);

            svg.append("g")
            .attr("class", "y axis")
            .call(yAxis)
            //.call(bars);  

            var bars = svg.selectAll(".bar")
            .data(items)
            .enter()
            .append("rect")
            .attr("class", function(d, i) {return "bar " + d.character;})
            .attr("x", function(d, i) {return d.starting_line;})
            .attr("y", function(d, i) {return y(d.location);})
            .attr("width", function(d, i) {return d.duration;})
            .attr("height", 15)
            .style("fill", function(d,i) {return "#" + d.color;})
            .call(tip)
            .on('mouseover', tip.show)
            .on('mouseout', tip.hide);


                   var listCharacters = d3.set(items.map(function(d) {return d.character})).values();

                   listColors = [];

                   listPositions = [];

                   for (l = 0; l < listCharacters.length; l++) {
                       for (var key in items) {
                           if (listCharacters[l] === items[key].character) {
                               if (listColors.indexOf(items[key].color) > -1) {} else {
                                   listColors.push(items[key].color);
                                   var xlegend = (Math.floor(l / 10) * 100);
                                   var ycounter;
                                   var ylegend;
                                   var oldxlegend;

                                   if (l === 0) {
                                       ycounter = 1;
                                   }

                                   if (ycounter < 10) {
                                       listPositions.push(ycounter * 15);
                                       ycounter++;
                                   } else {
                                       listPositions.push(ycounter * 15);
                                       ycounter = 1;
                                   }

                               }
                           } else {}
                       }
                   }


console.log(listCharacters);
console.log(listColors);
console.log(listPositions);

            var legend = svg.selectAll(".legend")
            .data(listCharacters)
            .enter().append("g")
            .attr("class", "legend")
            .attr("transform", function(d, i) { return "translate(" + (Math.floor(i / 10)  * 105) + ", " + listPositions[i] + ")"; })

            legend.append("rect")
            .attr("x", 10)
            .attr("width", 10)
            .attr("height", 10)
            .attr("fill", function(d,i) {return "#" + listColors[i];});



            legend.append("text")
            .attr("x", 22)
            .attr("y", 5)
            .attr("dy", ".35em")
            .text(function(d,i){ return listCharacters[i]});

            svg.append("g")
            .attr("class", "legend")
            .call(legend)

        });

My issue is that I have two tooltips I would like to include, which draw from two separate subsections of the JSON. 我的问题是,我想包含两个工具提示,它们来自JSON的两个单独的小节。 The tooltips are defined by the following two var declarations: 工具提示由以下两个var声明定义:

            var tip = d3.tip()
            .attr('class', 'd3-tip')
            .offset([-10, 0])
            .html(function(d, i) {return console.log(d.line_text) + "<strong>(" + d.starting_line + ")</strong> <i>" + d.character + "</i>: " + d.line_text;});

            var stage_tip = d3.tip()
            .attr('class', 'd3-tip')
            .offset([-10, 0])
            .html(function(d, i) {return console.log(d.direction_text) + "<strong>(" + d.line_after + ") s.d.</strong> <i>" + d.direction_text;});

And declared within the two calls for the bars for items and directions: 并在两个调用栏内声明了项和方向:

    var stage_bars = svg.selectAll(".stage_bar")
        .data(directions)
        .enter()
        .append("rect")
        .attr("class", "overlay")
        .attr("class", function(d, i) {return "stage_bar " + d.direction_text;})
        .attr("x", function(d, i) {return d.line_after;})
        .attr("width", 1)
        .attr("height", h)
        .style("fill", "black")
        .style("opacity",0.3)
        .call(stage_tip)
        .on('mouseover', stage_tip.show)
        .on('mouseout',stage_tip.hide);

    var bars = svg.selectAll(".bar")
        .data(items)
        .enter()
        .append("rect")
        .attr("class", function(d, i) {return "bar " + d.character;})
        .attr("x", function(d, i) {return d.starting_line;})
        .attr("y", function(d, i) {return y(d.location);})
        .attr("width", function(d, i) {return d.duration;})
        .attr("height", 15)
        .style("fill", function(d,i) {return "#" + d.color;})
        .call(tip)
        .on('mouseover', tip.show)
        .on('mouseout', tip.hide);

My issue is that the tooltip for bars (the ones that call tip) works, but the tooltip for stage_bars (the ones that call stage-tip) does not. 我的问题是,bar的工具提示(称为tip的工具)有效,而stage_bars的工具提示(称为stage-tip的工具提示)却无效。 I think the issue is that I'm calling the same class in both tip and stage_tip, but declaring it as something other than tip makes no difference. 我认为问题在于我在tip和stage_tip中都调用了相同的类,但是将其声明为非tip没什么区别。

My question is how to get both tooltips functional. 我的问题是如何使两个工具提示都起作用。 Is this even possible? 这有可能吗? I've seen examples that seem to do it but the code isn't clear. 我看过似乎可以做到的示例,但是代码不清楚。

The solution was actually really simple. 该解决方案实际上非常简单。 I had the stage_bars variable declared before the svg.append("rect") statements, which meant that the lines which indicates the stage directions were below the other objects. 我在svg.append(“ rect”)语句之前声明了stage_bars变量,这意味着指示阶段方向的线在其他对象之下。 So the mouse could never mouse over them to trigger the tooltip. 因此,鼠标永远无法将鼠标悬停在其上方以触发工具提示。 Moving the var declaration to a spot after those svg.append statements solved the issue. 在这些svg.append语句解决后,将var声明移到某个位置。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM