D3 Graph scaling task with appropriate scale scaling (Y axis, X axis)

Code Script Example

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

I want to add sliders for scaling along the X axis (time range), along the Y axis (distance range). I tried d3 scaling options that work great. But the scales (x axis, y axis) do not scale proportionally to the rectangles of the graph. As if the rectangle was within 10.20 miles along the Y axis. It goes more than 20 miles when scaling.

Then I tried viewbox on svg. It works. The scale is kept proportional to the schedule.

I want to keep the proportions of the scales and the graph when scaling, but I do not want to increase the size of the weight labels, as this makes the graph ugly.

Here is a code snippet for how I initially create my schedule

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 ) {


                    });
        });
+4
source share
2 answers

Just change the domain yAxisScalewhen the scaling event occurs.

Here the violin is updated.

First remove the method yin zoom. This helps to scale the axis automatically, but this is not your case. I will give an explanation at last.

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

Then change the domain yAxisScalewhen the scale value is changed.

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

? , , .

zoom y, yAxisScale . , , .

+1

, , , , . . .

1) :

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

2) zoomIn:

function zoomIn(){
var t = d3.event.translate,
s = d3.event.scale;
left_color_chart.attr("transform","translate("+t+")scale("+s+")")
}
+2

Source: https://habr.com/ru/post/1648705/


All Articles