Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

D3 Scaling issue of Graph with appropriate scaling of Scales(Y-axis,X-axis)

Tags:

Example Code Fiddle

I am working on a heatmap. In which I make the rectangles of heat map (width,height) programmatically depending upon data.

I want to add sliders for zooming on X-axis(time range) , Y-axis(distance range). I tried d3 scaling options which works fine. But the scales(x-axis, y-axis) don't scale in proportion to rectangles of graph. Like if a rectangle was between 10,20 miles y-axis scale. it goes further than 20 miles on scaling.

Then I tried viewbox on svg. It works . Scales are kept in proportion to graph exactly.

I want to keep the proportion of scales and graph on scaling but not want to increase the size of scales labels as it makes the graph ugly.

Here is code snippet for how I am making my graph initially

d3.json('dateWiseNewDataRight.json',function(err,right_dat){
            // console.log(right_dat);
            var dateGroups=_.groupBy(right_dat, "DATE");
            var data = [];
            var x= 0,y=0;
            var tlength=0;
            var totalDates=Object.keys(dateGroups);
            var graphWidth=(total_width/totalDates.length)-6;

            for(var key in dateGroups){
                tlength=0;
                data = [];
                y=0;
                var segmentMiles=0;
                var currentGraphData=dateGroups[key];
                var road=currentGraphData[0]['ROAD'];
                for(var i = 0; i < currentGraphData.length-1; i++) {
                    tlength+=currentGraphData[i].MILES;
                }
                for (var i = 0; i < currentGraphData.length-1; i++) {
                    var height=0;
                    segmentMiles=segmentMiles+currentGraphData[i].MILES;
                    for(var j in times){
                        if(road!=currentGraphData[i]['ROAD']){
                            road=currentGraphData[i]['ROAD'];
                            height=1;
                            for(var k=0;k<times.length;k++){
                                data.push({value:20000,x:x,y:y, height:height ,width:col_width,name:"",tmc:"", length:"",road:""});
                                x=x+col_width;
                            }
                            break;
                        }
                        else{

                            col_width=graphWidth/24;
                            var Congestion= currentGraphData[i][times[j]];
                            height=(currentGraphData[i].MILES/tlength)*total_height;
                            //road=leftDat[i]['ROAD'];
                            data.push({value:Congestion,x:x,y:y, height:height ,width:col_width,name:currentGraphData[i]['NAME'],tmc:currentGraphData[i]['TMC CODE'], length:currentGraphData[i]['MILES'],road:currentGraphData[i]['ROAD'],miles:segmentMiles});
                            // x=x+col_width;
                        }
                        x=x+col_width;
                    }
                    y=y+height;
                    x=0;
                }

                plotSegmentNames(panelData);

                var margin = { top: 50, right: 0, bottom: 10, left: 10 };

                $('.heat-map-2').append('<div class="chart-right-'+key+' " style="width: '+graphWidth+'px;float:left;margin:3px;;overflow:hidden"></div>');
                var graphDiv='.chart-right-'+key;
                var right_Svg = d3.select(graphDiv)
                        .append("svg")
                        .attr("class", "chart")
                        .attr("width",graphWidth)
                        .attr("height", total_height )
                        .attr("transform", "translate(" + margin.left + "," + margin.top + ")");
                var right_color_chart = right_Svg.append("g")
                        .attr("class", "rightHeatMap");
                right_color_chart.call(tip);

                var color = d3.scale.linear()
                        .domain([d3.min(data), 1])
                        .range(["blue", "green"]);
                right_color_chart.selectAll("rect")
                        .data(data)
                        .enter()
                        .append("rect")
                        .attr("x", function(d,i) {return d.x; })
                        .attr("y", function(d,i) { return d.y; })
                        .attr("width", col_width)
                        .attr("height",  function(d) { return d.height; })
                        .attr("road",function(d){
                            return d.road;
                        })
                        .attr("miles",  function(d) { return d.miles; })
                        .style("fill", function(d) {return chooseColor(d.value);})
                        .on('mouseover', tip.show)
                        .on('mouseout', tip.hide);
                var   right_xAxisScale = d3.time.scale(),
                        right_xAxis = d3.svg.axis()
                                .orient('bottom')
                                .ticks(d3.time.hour,1)
                                .tickFormat(d3.time.format('%I %p'))
                                .tickSubdivide(6);

                right_xAxis.scale(right_xAxisScale.range([0,graphWidth]).domain([timeFormat.parse(times[0]),timeFormat.parse(times[times.length-1])]));
                right_Svg.append('g')
                        .attr('class','x axis')
                        .call(right_xAxis)
                        .append('text')
                        .attr('transform','translate('+total_width+',0)');

                var    yAxisScale = d3.scale.linear()
                                .range([0,xAxisHeight])
                                .domain([0,tlength]),
                        yAxis = d3.svg.axis()
                                .orient('right')
                                .ticks(5)
                                .scale(yAxisScale);
                right_Svg.append('g')
                        .attr('transform','translate('+1+','+0+')')
                        .attr('class','y axis')
                        .call(yAxis)
//                        .append('text')
//                        .text('Length')
//                        .attr('transform','translate(100,'+total_height+') rotate(-90)');
            }



            var   testTimes =times;
            var distanceRange=[0,60];
            $("#scale-slider")
                    .slider({

                        animate:true,
                        range: true,
                        min: 0,
                        max: 1440,
                        step: 24,
                        values: [0, 1440],
                        slide: function (e, ui) {
                            var sliderTime= calculateSiderTime(e,ui);
                            testTimes=[sliderTime.nob1Time,sliderTime.nob2Time];
                            $('.x.axis').remove();
                            $('.y.axis').remove();
                          /*  redrawHeatMaps('left',left_color_chart,'leftHeatMap',leftDat,testTimes,tlength);
                            redrawHeatMaps('right',right_color_chart,'rightHeatMap',right_dat,testTimes,tlength);*/

                            redrawYHeatMaps('left',left_color_chart,'leftHeatMap',leftDat,testTimes,tlength,distanceRange);
                            redrawYHeatMaps('right',right_color_chart,'rightHeatMap',right_dat,testTimes,tlength,distanceRange);

                        }
                    })
                    .on("slidechange", function( e, ui ) {


                    });

            $("#distance-slider")
                    .slider({

                        animate:true,
                        range: true,
                        min: 0,
                        max: 60,
                        step: 5,
                        values: [0, 60],
                        slide: function (e, ui) {
                            distanceRange=ui.values;
                            $('.x.axis').remove();
                            $('.y.axis').remove();
                         //   left_color_chart.attr("transform", "translate("+ d3.event.translate + ")scale(" + d3.event.scale + ")");
                            redrawYHeatMaps('left',left_color_chart,'leftHeatMap',leftDat,testTimes,tlength,distanceRange);
                            redrawYHeatMaps('right',right_color_chart,'rightHeatMap',right_dat,testTimes,tlength,distanceRange);
                            $('.slider-distance1').html(ui.values[0]);
                            $('.slider-distance2').html( ui.values[1]);
                        }
                    })
                    .on("slidechange", function( e, ui ) {


                    });
        });
like image 660
Achilles Avatar asked Jul 21 '16 20:07

Achilles


People also ask

Can you scale the X and Y axis differently?

YES, you can take different scales on the x and y axis of a graph. For example, you can take scale values on x axis in he form of multiples of 2 i.e., 2.

How do you scale a graph axis?

Changing Axis Scale Settings Select the axis. Choose Format Axis from the context menu and click the Scale tab, shown below. Click OK or Apply to see your changes.


1 Answers

Just only edit yAxisScale's domain when scale event is occurred.

Here is updated fiddle.

First, remove y method in zoom. It helps auto-scaling for an axis but, it is not your case. I'll give an explanation at last.

zoom = d3.behavior.zoom()
  .scaleExtent([0, 5])
  .scale(1)
  .on("zoom", zoomed);

After, adjust yAxisScale domain when scale value is changed.

function zoomed() {
  yAxisScale.domain([0, tlength / d3.event.scale]); // added
  leftSvg.select(".y.axis").call(yAxis);
  zoomIn();
}

Why use division not multiplication? Because if you scale twice, axis values only shown up a half in comparison with its original values.

If you use zoom's y method, it is going to auto-scale yAxisScale using multiplication. So, I said it is not your case above.

like image 139
Jinyoung Kim Avatar answered Sep 28 '22 04:09

Jinyoung Kim