-1

I would know how to create two interactive graphs using d3.js,I mean for example one line chart interacting with a scatter plot by clicking on a value of the line chart and visualizing the corresponding one on the scatter plot.How can i obtain such an effect?Basically I dont't know how to call a mouseover function on graph A and seeing the effect of this function on graph B.

  d3.csv("resources/diffusionesitiweb10anni.csv",function(data){
            dataset = data;

            data.forEach(function(d) {
                d["Anno"] = parseDate(d["Anno"].toString());

            });

           yAxis.tickFormat(function(d){return d + "%"});

           yScale.domain([0,d3.max(dataset,function(d){
                    return +d["Italia"];
            })]);

            xScale.domain(d3.extent(data,function(d){
                return +d["Anno"];
            }));

    /***** provo line chart ********/
            svg1.append("g")
               .attr("class","x axis")
               .attr("transform","translate(0," + height +")")
               .call(xAxis);

            svg1.append("g")
               .attr("class","y axis")
               .call(yAxis)
               .append("text")
               .attr("transform", "rotate(-90)")
               .attr("y", 6)
               .attr("dy", ".71em")
               .style("text-anchor", "end")
               .text("Percentage");

            svg1.append("path")
               .attr("class","line")
               .attr("d",line(dataset))
               .style("stroke","black")
               .transition().duration(2500).attrTween("d",pathTween);

            function pathTween() {
                var interpolate = d3.scale.quantile()
                                    .domain([0,1])
                                    .range(d3.range(1, data.length + 1));
                return function(t) {
                    return line(data.slice(0, interpolate(t)));
                };
            }

            svg1.selectAll("circle")
               .data(dataset)
               .enter()
               .append("circle")
               .attr("cx",function(d){
                   return xScale(d["Anno"]);
                })
               .attr("cy",function(d){
                   return yScale(d["Italia"]);
                })
               .attr("r",3)
               .on('mouseover', tip.show).on('mouseout', tip.hide);

        });

This is the first graph(linechart),and the following is the second one

 d3.csv("resources/utilizzoInternet.csv",function(data){

            datiInternet = data;
            var margin = {top: 20, right: 20, bottom: 30, left: 40};
            width = containerWidth - margin.left - margin.right,
            height = containerHeight - margin.top - margin.bottom;

            var parseDate = d3.time.format("%Y").parse;
            var xScale = d3.time.scale().range([0,width]);
            var yScale = d3.scale.linear().range([height,0]);
            var xAxis = d3.svg.axis()
                          .scale(xScale)
                          .orient("bottom");
            var yAxis = d3.svg.axis().scale(yScale).orient("left");

    svg2=d3.select("#LineChart")
                        .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 + ")");



     yScale.domain([0,d3.max(datiInternet,function(d){
                    return +d["Totale"];
            })]);

            xScale.domain(d3.extent(data,function(d){
                return +d["Anno"];
            }));


    svg2.selectAll("circle")
                    .data(datiInternet)
                    .enter()
                    .append("circle")
                    .attr("cx",function(d){
                        return xScale(d["Anno"]);
            })
                    .attr("cy",function(d){
                        return yScale(d["Totale"]);
            })
                    .attr("r", function(d) {
                        return Math.sqrt(d["Totale"]);
                    });
 });

The two graph are made by two different csv file,what i would like to do is to pass the mouse over a point in the line chart,and have this point displayed on the second chart which is a scatter plot.How can I implement such a "mouseover" function? Thanks in advance,hope that now is more completed and clear.

Working JSFiddle: http://jsfiddle.net/mirko89/ahrdormr/5/

Ethan Jewett
  • 6,002
  • 16
  • 25
Mirko
  • 137
  • 1
  • 2
  • 14
  • This is a very general question. You may want to look at a library that specializes in this, like dc.js. – Ethan Jewett Nov 09 '15 at 23:51
  • Suppose I have one line chart and one scatter plot,how I can interact with one of them and make this interaction work on the other graph,this is the point and I can't figure out a way of do it. @EthanJewett – Mirko Nov 10 '15 at 12:05
  • You need to be more specific. Please read http://stackoverflow.com/help/how-to-ask and post a working example. There are tons of examples and libraries and lots of different ways to do this. – Ethan Jewett Nov 10 '15 at 12:39
  • @EthanJewett I've pasted my code,hope now is useful,thanks. – Mirko Nov 10 '15 at 21:31
  • Ok. For starters, you'll want to add an on('click', ...) event handler to the element you are clicking on. Within that handler you will do whatever you need to do to highlight elements in the other visualization. Have you given that a shot? – Ethan Jewett Nov 11 '15 at 01:25
  • That's my point,if I add an .on('click',...),how can I modify the second visualization?I can't figure out a way of doing that,I hope in a help.Thanks. @EthanJewett – Mirko Nov 11 '15 at 13:19
  • Generally speaking, you would use d3 methods inside the event handler much like you already have. `svg2.selectAll('circle').filter(function(d) { return d.thingIWant === true;}).attr('fill', 'red')` should turn circles red. – Ethan Jewett Nov 11 '15 at 16:23
  • Ok,but I know how to turn red a circle on the current chart,I don't know how to call the second chart,what reference I've to consider.For example if in my handler I create a new chart,it will be displayed above the one I already have? @EthanJewett – Mirko Nov 11 '15 at 20:26
  • You don't want to create a new chart in your handler. You want to select the other (existing) chart and modify it. If you create a working example using jsFiddle or something similar it will be very easy to show. – Ethan Jewett Nov 11 '15 at 22:05
  • I'm not practice with jsFiddle,I think that I cannot pass my input file there.However the other existing chart is created by "svg2" using the div "LineChart",how can i refer to it?@EthanJewett – Mirko Nov 11 '15 at 22:35
  • I've put the code here https://gist.github.com/mirko441989/ and here http://bl.ocks.org/mirko441989 there is an execution,but that code works on my machine while on bl.ocks it looks very different.Anyway now the code is linked there.Hope it can be helpful.@EthanJewett – Mirko Nov 11 '15 at 23:51
  • svg2 is still accessible in your on-click handler and *is* a reference to the 2nd chart. So you would start from there and use d3's select/selectAll/filter methods to select the actual elements you want to change. Blocks/gists aren't a great option here because they are not very easy to change. To get help on SO, it's best if you make it as easy as possible for people to provide an answer to your question. You can create these charts on jsFiddle, CodePen.io, etc for best ease of answering. – Ethan Jewett Nov 12 '15 at 19:49
  • http://jsfiddle.net/jvaorxdj/ Here is the jsFiddle,but as I said,I can't load the csv file from there,so the charts are empty.How can I link jsFiddle to my csv files?It's all set,the only missing things are the external file to link. @EthanJewett – Mirko Nov 13 '15 at 21:45
  • Thanks for starting this. One approach that should work for CSV files with limited length like your is discussed here: http://stackoverflow.com/questions/22890836/loading-external-csv-file-in-jsfiddle – Ethan Jewett Nov 13 '15 at 22:49
  • Thanks,I've just done in another way,I've created the file as arrays since they are not so big.Now the jsFiddle is ready,but on the website I can't display anything and on my local machine it works.Hope now I can understand how to do the interaction I want.Here is the page http://jsfiddle.net/mirko89/ahrdormr/ thanks a lot.@EthanJewett – Mirko Nov 14 '15 at 16:27
  • it didn't have d3 or d3.tip included. I've added those - here is a working version: http://jsfiddle.net/ahrdormr/1/ But I don't see the 2nd visualization or the code for it. Could you add that? – Ethan Jewett Nov 14 '15 at 23:52
  • http://jsfiddle.net/mirko89/ahrdormr/4/ here you are! Now there is the second chart;but I don't know why here I can't see the line between points in the first graph it's strange. Thanks a lot.. @EthanJewett – Mirko Nov 15 '15 at 13:34
  • I've corrected it,this is the final version http://jsfiddle.net/mirko89/ahrdormr/5/ now I'm ready to learn from you how to do the interaction between the first and the second graph. Thanks,really!@EthanJewett – Mirko Nov 15 '15 at 14:03
  • Thanks for setting up the example. I answered below. – Ethan Jewett Nov 15 '15 at 17:34

1 Answers1

1

So, now that we've got a working example to start from, this is pretty easy to explain/demonstrate: You've got svg1 and svg2 as variables on your global scope. You can use those within event handlers to change other charts when something happens. For example if you want to highlight the matching circle in svg1 when someone clicks a circle in svg2, you would add a handler for that event:

svg2.selectAll("circle")
      .data(datiInternet)
      .enter()
      .append("circle")
[...]
    .on('click', function(d) {
      svg1.selectAll('circle')
          .filter(function(f) {
                return f.Anno.getFullYear() === d.Anno.getFullYear();
            })
          .attr('fill', 'red');
    });

Here's a working example: http://jsfiddle.net/sc4cf2Le/ (Click a circle on the 2nd chart and the corresponding circle on the 1st chart will turn red.)

You can modify your mouseover handler similarly. And note that this only turns the circle red. It doesn't switch it back when you click again, so if you are doing mouseover you'll probably want to switch the color back in the mouseout handler.

Ethan Jewett
  • 6,002
  • 16
  • 25
  • Ok thanks a lot,but the two graphs are made by two different datasets,so the circle that turns red in the first graph is not the same of the second(the year is the same so you have just highlighted this thing).What i wanted to obtain is to make the clicked circle of the second chart appearing on the first one.How can I do that? Thanks. – Mirko Nov 15 '15 at 17:44
  • You would use d3 methods to draw the point on the chart wherever you want. But probably more important to ask some questions: What would that mean? Are the years always the same in your data sets? Are you sure that the y-axis range of the 1st chart will always cover the same range as the 2nd chart (I wouldn't be). Why can't you solve the problem by plotting them on a single chart? – Ethan Jewett Nov 15 '15 at 21:29
  • Because I have to do an interaction between two charts as a specific of a work,even if it has not much sense,I need that.Anyway if I want to draw the point,I've always use selectAll(..).data(..).enter().append(..),in this case I have the coordinate of the point and I don't need to call .data(..) to retrieve a value,so how can I do such a thing? – Mirko Nov 16 '15 at 09:40
  • Just because something is a requirement doesn't mean it is right. If you're doing this professionally, I think you should push back on the requirement until you get a good answer to the questions I asked above. – Ethan Jewett Nov 16 '15 at 15:06
  • I know,but since it is for the university,I can't change the requirements,and the only thing I need is to click on a point of a chart and having that point displayed in the other chart,but i I don't know how.Thanks a lot. – Mirko Nov 17 '15 at 00:42
  • I've done the mouse out function on svg1,now if I want to even display the tip on the first graph while changing the circle color?In svg2 on click action we filter the circle of the first graph and turn them red,how can I display the tip too? I've tried to do .call(tip.show) after the .attr(..) but it does not work. Thanks in advance . – Mirko Nov 18 '15 at 18:57
  • Please post a link to the example. – Ethan Jewett Nov 18 '15 at 19:23
  • http://jsfiddle.net/mirko89/sc4cf2Le/1/ line 218 is the mouseover function on svg1 elements (I reset the color and hide the tip) now I would have that when I click on svg2,svg1 circles become red and display the tip.So by clicking on an svg2 circle I highlight in red and show the tip of svg1 circles. – Mirko Nov 18 '15 at 22:41
  • http://jsfiddle.net/49fqrkw2/ - `.attr('fill', 'red').each(function(d) { tip.show(d, this) })` – Ethan Jewett Nov 18 '15 at 22:45
  • I'd recommend you close this question and open new ones with simplified examples for further questions. :-) – Ethan Jewett Nov 18 '15 at 22:46