简体   繁体   中英

Show all data for a variable in box next to d3 chart on mouseover

I have a d3 linechart I've put together with a tooltip when I mouseover the line that shows the topNewFeature data point in the json object below. In addition to that tooltip I would like to iterate through the features variable and list on mouseover all the featureDescriptions in a box next to the chart. Here is what my data structure looks like:

data = [{
        date : 2015-01-01,
        topNewFeature : XYZ,
        sigFeatures : 12,
        cumCPA : 43,
        features : [
            {coeff : 0.3345, featureDescription : ABC},
            {coeff : 0.7232, featureDescription : XYZ}, 
            ...
        ]
    },

        ...
]

My json file is to big to upload to jsfiddle, myjson or html/css/javascript editor offered by stack overflow so I made a little flask app to server it up: JSON DATA

Here are the relevant js, html and css files:

  var margin = { top: 30, right: 200, bottom: 30, left: 50 }, width = 960 - margin.left - margin.right, height = 470 - margin.top - margin.bottom; var parseDate = d3.time.format("%d-%b-%y").parse; var formatDate = d3.time.format("%e %B"); // ******** var bisectDate = d3.bisector(function(d) { return d.date; }).left; // Set chart ranges var x = d3.time.scale().range([0, width]); var y0 = d3.scale.linear().range([height, 0]); var y1 = d3.scale.linear().range([height, 0]); // Define X-Axis var xAxis = d3.svg.axis().scale(x) .orient("bottom").ticks(5); // Define Left Y-Axis var yAxisLeft = d3.svg.axis().scale(y0) .orient("left").ticks(5) .tickFormat(d3.format("$")); // Define Right Y-Axis var yAxisRight = d3.svg.axis().scale(y1) .orient("right").ticks(5); // Define cumulative CPA line var valueline = d3.svg.line() .x(function(d) { return x(d.date); }) .y(function(d) { return y0(d.cumCPA); }); // Define significant features line var valueline2 = d3.svg.line() .x(function(d) { return x(d.date); }) .y(function(d) { return y1(d.sigFeatures); }); // Define the div for the tooltip var tooldiv = d3.select("body").append("div") .attr("class", "tooltip") .style("opacity", "0") .style("display", "none"); // Add svg canvas var svg = d3.select("#chart") .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 + ")"); // Add tooltip line & focus element var lineSvg = svg.append("g"); // Get the data d3.json("princess_cruise.json", function(error, data) { data.forEach(function(d) { d.date = parseDate(d.date); d.sigFeatures = +d.sigFeatures; d.cumCPA = +d.cumCPA; d.features = d.features; d.topNewFeature = d.topNewFeature; }); // Scale the range of the data x.domain(d3.extent(data, function(d) { return d.date; })); y0.domain([0, d3.max(data, function(d) { return Math.max(d.cumCPA); })]); y1.domain([0, d3.max(data, function(d) { return Math.max(d.sigFeatures); })]); // Add cumulative CPA path svg.append("path") .style("stroke", "#158BD5") .attr("d", valueline(data)); // Add significant features path svg.append("path") .style("stroke", "#00B151") .attr("d", valueline2(data)); // Add the X Axis (date) svg.append("g") .attr("class", "x axis") .attr("transform", "translate(0," + height + ")") .call(xAxis); // Add Y axis (cumulative CPA) svg.append("g") .attr("class", "y axis") .style("fill", "#158BD5") .call(yAxisLeft); // Add Y axis (significant features) svg.append("g") .attr("class", "y axis") .attr("transform", "translate(" + width + " ,0)") .style("fill", "#00B151") .call(yAxisRight); // START TOOLTIP INTEGRATION var focus = svg.append("g") .style("display", "none"); // append the x line focus.append("line") .attr("class", "x") .style("stroke", "#555555") .style("stroke-dasharray", "3,3") .style("opacity", 0.5) .attr("y1", 0) .attr("y2", height); // append the y line focus.append("line") .attr("class", "y") .style("stroke", "#555555") .style("stroke-dasharray", "3,3") .style("opacity", 0.5) .attr("x1", width) .attr("x2", width / 2); // append the circle at the intersection // place the significant features at the intersection var tooltip = focus.append("g") .data(data) .attr("class","toolbox"); tooltip.append("rect") .style("fill", "#fff") .style("stroke", "#eee") .style("stroke-width", 2) .style("opacity", 1) .attr("width", 200) .attr("height", 35); tooltip.append("rect") .style("fill", "#eee") .style("opacity",0.8) .attr("width", 200) .attr("height", 15); tooltip.append("text") .attr("dx", 8) .attr("dy", 12) .text("Top New Feature:"); tooltip.append("text") .attr("class","featText") .attr("dx", 8) .attr("dy", 30); tooltip.append("circle") .attr("class", "y") .style("fill", "#fff") .style("stroke", "#00B151") .style("stroke-width", 2) .attr("r", 6); // append the rectangle to capture mouse svg.append("rect") .attr("width", width) .attr("height", height) .style("fill", "none") .style("pointer-events", "all") .on("mouseover", function(d) { focus.style("display", null); }) .on("mouseout", function(d) { focus.style("display", "none"); }) .on("mousemove", mousemove); function mousemove() { var x0 = x.invert(d3.mouse(this)[0]), i = bisectDate(data, x0, 1), d0 = data[i - 1], d1 = data[i], d = x0 - d0.date > d1.date - x0 ? d1 : d0; focus.select(".toolbox") .attr("transform", "translate(" + x(d.date) + "," + y1(d.sigFeatures) + ")"); focus.select(".featText") .text(d.topNewFeature); focus.select(".x") .attr("transform", "translate(" + x(d.date) + "," + y1(d.sigFeatures) + ")") .attr("y2", height - y1(d.sigFeatures)); focus.select(".y") .attr("transform", "translate(" + width * -1 + "," + y1(d.sigFeatures) + ")") .attr("x2", width + width) .attr("x1", x(d.date) - (width * -1)); } }); 
  body { font: 12px Arial;} path { stroke: steelblue; stroke-width: 2; fill: none; } .axis path, .axis line { fill: none; stroke: grey; stroke-width: 1; shape-rendering: crispEdges; } div.tooltip { position: absolute; text-align: left; font: 12px sans-serif; padding-top: 2px; padding-bottom: 2px; padding-right: 6px; padding-left: 6px; background: white; border: 1px; border-style: solid; pointer-events: none; } 
 <!DOCTYPE html> <html> <head> <title></title> <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet"/> <script src="https://d3js.org/d3.v3.min.js" charset="utf-8"></script> <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script> </head> <body> <div class="container-fluid"> <div class="row"> <div class="col-md-8"> <div id="chart"></div> </div> <div class="col-md-4"> <h5>Features for day being hovered over</h5> <div id="showdata"></div> </div> </div> </div> <script src="/js/chart.js" type="text/javascript"></script> </body> </html> 

You can do something like this in mouse over function :

//remove all the old selection this can me moved to mouse out as well
d3.select("#showdata").selectAll("*").remove();
//here we will append feature description to the div showdata 
d.features.forEach(function(m){
  d3.select("#showdata")
    .append("div")
    .text(m.featureDescription)
})

Working code here

Hope this helps!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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