Update and rescale Line chart with async received data

44 views
Skip to first unread message

Stefan Schneider

unread,
Nov 26, 2015, 3:00:37 AM11/26/15
to d3-js
Hello everyone,

I have the following problem. I have an oData Rest endpoint and a limitation per request of batches of 50 records. Now I want to draw a line chart with nested user information like the users name and under that the work day and the working time. So I iterate over all the users and try to find the min max for the working day and working time and draw the initial svg.
Now when I get the next 50 records I want to rescale x and y axis to a new min max and I also need to rescale the old 50 records to the new scale, and there is my main problem. I don't have the data of the data of the 50 former records but I have the path drawn by those data.
How can I rescale the old paths to the new domain before I fill in the new data? And how do I add the information of the same user to the path of the user. Each user should have only one path in the line chart.
Also, how do I keep a legend for each line in the chart for each user?
I'm getting my data from a MS Dynamics CRM oData Rest endpoint and I'm substituting a webresource via fiddler in a given MS Dynamics CRM environment if anyone is wondering where I get my data from
My current version looks like this:

<!DOCTYPE html>
<html lang='en'>
<head>
 
<meta charset='utf-8'>


 
<title>dc.js Experiment</title>

 
<script src='https://cdnjs.cloudflare.com/ajax/libs/jquery/3.0.0-alpha1/jquery.min.js' type='text/javascript'></script>
 
<script src='https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.8/d3.js' type='text/javascript'></script>
 
<script src='https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.10.1/lodash.min.js' type='text/javascript'></script>
 
<script src="/WebResources/con_XrmServiceToolkit_2.1.js"></script>


</head>
<body>

   
<style>

   
.legend {
        font
-size: 14px;
        font
-weight: bold;
   
}


   
.xaxis path,
   
.xaxis line,
   
.yaxis path,
   
.yaxis line {
        fill
: none;
        stroke
: black;
        shape
-rendering: crispEdges;
   
}


   
.yaxis text,
   
.xaxis text {
        font
-family: sans-serif;
        font
-size: 11px;
   
}
   
</style>
   
<script type="text/javascript">


       
var margin = {
                top
: 20,
                right
: 100,
                bottom
: 70,
                left
: 50
           
},
            width
= 960 - margin.left - margin.right,
            height
= 500 - margin.top - margin.bottom;


       
var color = d3.scale.category20();


       
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" );


       
var svg = d3.select( "body" ).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 + ")" );


       
var lineGen = d3.svg.line().interpolate("monotone")
           
.x( function ( d ) {
               
return xScale(new Date(d.key + " 00:00:00"));
           
} )
           
.y( function ( d ) {
               
return yScale(d.values);
           
} );


       
(function executeQueryRest (){
           
var returnResults = [];
           
XrmServiceToolkit.Rest.RetrieveMultiple(
               
"con_workrecordSet",
               
"$select=&$filter=&$top=100&$orderby=CreatedOn",
               
function (results) {
                    render
(results);
               
},
               
function (error) {
               
},
               
function onComplete() {
               
},
               
true
           
);
       
})();


       
function render(data){
           
var dataGroup  = d3.nest()
               
.key(function(d){
                   
return d.OwnerId.Name;
               
})
               
.key(function(d){
                   
var format = d3.time.format("%Y-%m-%d");
                   
return format(d.CreatedOn);
               
})
               
.rollup(function( workingtime ){
                   
return d3.sum( workingtime, function ( d ) {
                       
return d.con_workingtime;
                   
} );
               
})
               
.entries(data);


           
var xMin = d3.min( dataGroup  ,
               
function ( d ) {
                   
return d3.min( _.map(d.values, function(value){return new Date(value.key + " 00:00:00");}));
               
}
           
);


           
var xMax = d3.max( dataGroup  ,
               
function ( d ) {
                   
return d3.max( _.map(d.values, function(value){return new Date(value.key + " 00:00:00");}));
               
}
           
);


           
var yMin = d3.min( dataGroup  ,
               
function ( d ) {
                   
return d3.min( _.map(d.values, function(value){return value.values;}));
               
}
           
);


           
var yMax = d3.max( dataGroup  ,
               
function ( d ) {
                   
return d3.max( _.map(d.values, function(value){return value.values;}));
               
}
           
);


           
if ( $(".yaxis").length > 0 || $(".xaxis").length > 0){
               
var newXMin = d3.min([xMin, xScale.domain()[0] ]);
               
var newXMax = d3.max([xMax, xScale.domain()[1] ]);


               
var newYMin = d3.min([yMin, yScale.domain()[0] ]);
               
var newYMax = d3.max([yMax, yScale.domain()[1] ]);


                xScale
.domain([newXMin, newXMax]);
                yScale
.domain([0, newYMax]);
           
} else {
                xScale
.domain([xMin, xMax]);
                yScale
.domain([0, yMax]);
           
}


           
if ( $(".yaxis").length > 0 || $(".xaxis").length > 0){
               
// d3.selectAll(".yaxis").remove();
               
// d3.selectAll(".xaxis").remove();
                svg
.select(".yaxis")
                   
.transition().duration(1500).ease("sin-in-out")
                   
.call(yAxis);


                svg
.select(".xaxis")
                   
.transition().duration(1500).ease("sin-in-out")
                   
.call(xAxis);
           
} else {
                svg
.append( "g" )
                   
.attr( "class", "xaxis" )
                   
// .style({ 'stroke': 'Black', 'fill': 'none', 'stroke-width': '2px'})
                   
.attr( "transform", "translate(0," + height + ")" )
                   
.call( xAxis )
                   
.append("text")
                       
.attr("transform", "translate(" + (width / 2) + " ," + (height + margin.bottom) + ")")
                       
.style("text-anchor", "middle")
                       
.text("Date");


                svg
.append( "g" )
                   
.attr( "class", "yaxis" )
                   
// .style({ 'stroke': 'Black', 'fill': 'none', 'stroke-width': '2px'})
                   
.call( yAxis )
                   
.append( "text" )
                       
.attr( "transform", "rotate(-90)" )
                       
.attr( "y", 6 )
                       
.attr( "dy", ".71em" )
                       
.style( "text-anchor", "end" )
                       
.text( "Workingtime" );
           
}


            _
.forEach(dataGroup, function(d, i){
               
// if ( $("#line_" + d.key.replace(/\s|\,/g,"")).length > 0){
               
//     var path = svg.select("#line_" + d.key.replace(/\s|\,/g,""))
               
//         .data(d.values);
               
//     path.enter().append("path")
               
//             .attr("d", lineGen(d.values, xScale, yScale))
               
//             .attr("stroke", function(){
               
//                 return color( d.key.length );
               
//             })
               
//             .attr("stroke-width", 2)
               
//             .attr('id', 'line_' + d.key.replace(/\s|\,/g,""))
               
//             .attr("fill", "none");
               
// } else {
                   
var path = svg.selectAll("#line_" + d.key.replace(/\s|\,/g,""))
                       
.data(d.values);
                    path
.enter().append("path")
                       
.transition()
                       
.duration(300)
                       
.attr("d", lineGen(d.values, xScale, yScale))
                       
.attr("stroke", function(){
                           
return color( d.key.length );
                       
})
                       
.attr("stroke-width", 2)
                       
.attr('id', 'line_' + d.key.replace(/\s|\,/g,""))
                       
.attr("fill", "none");


                    path
.exit()
                       
.transition()
                       
.duration(300)
                       
.ease("exp")
                           
.attr("width", 0)
                           
.remove();
               
// }


               
var point = svg.append("g")
                       
.attr("class", "line-point");


                point
.selectAll( 'circle' )
                   
.data( d.values )
                   
.enter().append( 'circle' )
                       
.transition()
                       
.duration(300)
                       
.attr( "cx", function ( d ) {
                           
return xScale( new Date( d.key ) );
                       
} )
                       
.attr( "cy", function ( d ) {
                           
return yScale( d.values );
                       
} )
                       
.attr( "r", 3.5 )
                       
.style( "fill", function () { // dynamic colours
                           
return color( d.key.length );
                       
} )


           
var lSpace = width/dataGroup.length;


           
var legend = svg.append("text")
                   
.attr("x", (lSpace / 2) + i * lSpace)
                   
.attr("y", height + 45)
                   
.style("fill", function(){return color( d.key.length );})
                   
.attr("class", "legend")
                   
.on('click', function() {
                       
var active = d.active ? false : true;
                       
var opacity = active ? 0 : 1;


                        d3
.select("#line_" + d.key.replace(/\s|\,/g,""))
                           
.transition()
                           
.duration(200)
                           
.style("opacity", opacity);


                        d
.active = active;
                   
})
                   
.text(d.key);
           
});
       
}
   
</script>
</body>
</html>


Reply all
Reply to author
Forward
0 new messages