In some cases, you might need to interpolate numbers embedded in a string; perhaps a CSS style for font.
In this recipe, we will examine how you can do that using D3 scale and interpolation. However, before we jump right into string interpolation, a bit of background research on interpolator is due and the following section will cover what interpolation is and how D3 implements interpolator functions.
In the first three recipes, we have gone over three different D3 scale implementations, now it is time to delve a little deeper into D3 scales. You are probably already asking the question, "How different scale knows what value to use for different inputs?" In fact this question can be generalized to:
We are given the values of a function f(x) at different points x0, x1, … ,xn. We want to find approximate values of the function f(x) for "new" x's that lie between these points . This process is called interpolation.
Kreyszig E & Kreyszig H & Norminton E. J. (2010)
Interpolation is not only important in scale implementation but also essential to many other core D3 capabilities, for example, animation and layout management. It is because of this essential role, D3 has designed a separate and re-usable construct called interpolator so that this common cross-functional concern can be addressed in a centralized and consistent fashion. Let's take a simple interpolator as an example:
var interpolate = d3.interpolateNumber(0, 100); interpolate(0.1); // => 10 interpolate(0.99); //=> 99
In this simple example, we created a D3 number interpolator with a range of [0, 100]
. The d3.interpolateNumber
function returns an interpolate
function which we can use to perform number-based interpolations. The interpolate
function is an equivalent to the following code:
function interpolate(t) { return a * (1 - t) + b * t; }
In this function, a
represents the start of the range and b
represents the end of the range. The parameter t
passed into the interpolate()
function, is a float-point number ranging from 0 to 1, and it signifies how far the return value is from a
.
D3 provides a number of built-in interpolators. Due to limited scope in this book, we will focus on some of the more interesting interpolators for the next few recipes; we are ending our discussion on simple number interpolation here. Nevertheless, the fundamental approach and mechanism remains the same whether it is a number or an RGB color code interpolator.
For more details on number and round interpolation, please refer to the D3 reference documents at https://github.com/mbostock/d3/wiki/Transitions#wiki-d3_interpolateNumber
Now with general interpolation concepts behind, let's take a look at how string interpolator works in D3.
Open your local copy of the following file in your web browser:
https://github.com/NickQiZhu/d3-cookbook/blob/master/src/chapter4/string-interpolation.html
String interpolator finds the numbers embedded in the string, then performs interpolation using D3 number interpolator:
<div id="font" class="clear"> <span>Font Interpolation<br></span> </div> <script type="text/javascript"> var max = 11, data = []; var sizeScale = d3.scale.linear() // <-A .domain([0, max]) .range([ // <-B "italic bold 12px/30px Georgia, serif", "italic bold 120px/180px Georgia, serif" ]); for (var i = 0; i < max; ++i){ data.push(i); } function render(data, scale, selector) { // <-C d3.select(selector).selectAll("div.cell") .data(data) .enter().append("div").classed("cell", true) .append("span"); d3.select(selector).selectAll("div.cell") .data(data) .exit().remove(); d3.select(selector).selectAll("div.cell") .data(data) .style("display", "inline-block") .select("span") .style("font", function(d,i){ return scale(d); // <-D }) .text(function(d,i){return i;}); // <-E } render(data, sizeScale, "#font"); </script>
The preceding code produces the following output:
In this example, we created a linear scale on line A
with range specified between two strings representing start and end font
styles:
var sizeScale = d3.scale.linear() // <-A .domain([0, max]) .range([ // <-B "italic bold 12px/30px Georgia, serif", "italic bold 120px/180px Georgia, serif" ]);
As you can see in the code of the string-interpolation.html
file, the font
style strings contain font-size
numbers 12px/30px
and 120px/180px
, which we want to interpolate in this recipe.
On line C
, the render()
function simply creates 10 cells containing each one's index numbers (line E
) styled using interpolated font
style string calculated on line D
.
.style("font", function(d,i){ return scale(d); // <-D }) .text(function(d,i){return i;}); // <-E
Though we demonstrated string interpolation in D3 using a CSS font style as an example, D3 string interpolator is not only limited handling CSS styles. It can basically handle any string, and interpolates the embedded number as long as the number matches the following Regex pattern:
/[-+]?(?:d+.?d*|.?d+)(?:[eE][-+]?d+)?/g