===Writing the Script - Part 5=== That's enough to get a basic Infographic working. But with live data, there's an issue - we keep adding //more// content to the page every time we call **draw**. The simplest way to avoid this is by re-drawing the image every time. We could do this with the line... $('#reportsvg').html(""); This is...OK. But it's not great, either for performance or for your users experience. Let's use some of what makes D3 great, and make it //transition//. This can be done in a couple of steps... 1) Smoothly transitioning our bars when we first create them, \\ 2) Avoid re-creating items that can never update, and \\ 3) Smoothly transitioning our bars when data changes \\ ----- ===Starting Our Bars Out Small=== Our **join** command creates our bars already at their full size. If we want to make a pretty opening transition, it'd be nice to have them animate from 0 up to their final value. We can do this quite simply, by changing the initial width to '0' and using the **transition** and **duration** functions. We can change our 'enter' function to look like this... this.svgbase.selectAll(".bar").data(finaldata) .join( enter => enter.append("rect") .attr("class","bar element") .attr("x",function (d) { return x(0); }) .attr("y",function (d) { return y(d.name); }) .attr("width", 0) .attr("height",y.bandwidth) .attr("fill","cyan") .attr("name",function(d) { return d.name; }) .attr("value",function(d) { return d.value; }) .attr("units"," Deg C") .call(this.tip) .transition() .duration(1000) .attr("width", function(d) { return x(d.value);}) ); They key changes here are.... * The width now starts at 0, * We've told d3 to //transition// our value over //1000ms// (1 second), and * The width we used to have previously is now **after** the transition - the width will animate to this value. ----- ===Only Creating the Axes Once=== We don't want to constantly re-create our report axes every time an update comes in, so let's write a simple condition. When we //initialise// our report, we'll set a flag called 'first'. initialise() { super.initialise(); this.first = true; }; Then, we only draw our X and Y axes //if the value of **first** is **true**//. if (this.first == true) { ....draw x and y axes... } this.first = false; This ensures that the elements that don't **need** to be updated when new live data arrives, don't get updated. ------ ===Animate On Updates=== In our **join** function, we gave a function that is called on //entry// - when the object first appears in the image. Next, we need to define a function that is called on //update// - when there **is** an existing bar to use. We add this after the 'enter' parameter to the **join** function. The code is almost exactly the same as the code we just added to our bars during entry... update => update .attr("value",function(d) { return d.value;}) .transition() .duration(500) .attr("width",function(d) { return x(d.value); }) This tells the system to leave all of the existing properties alone, but immediately set the 'value' attribute (to change the value shown on the tooltips) to it's new value, and animate the //width// of the object to the new value. ===Final Code & Example=== For a version of this graphic with a little bit of extra polish, see the [[code:barchart_of_all_properties|code example]] In addition to the basics we've explored here, this example... * Places the set of axes in a //group// and translates it, creating a top and left margin, * Deals properly with negative values (the simple code shown above will struggle with negatives) * Includes a text value on each of the bars, * Dynamically colours the bars using ARDI colour lookup tables, and * Highlights the minimum and maximum values