1 /** 2 * Abstract; see the various scale implementations. 3 * 4 * @class Represents a scale; a function that performs a transformation from 5 * data domain to visual range. For quantitative and quantile scales, the domain 6 * is expressed as numbers; for ordinal scales, the domain is expressed as 7 * strings (or equivalently objects with unique string representations). The 8 * "visual range" may correspond to pixel space, colors, font sizes, and the 9 * like. 10 * 11 * <p>Note that scales are functions, and thus can be used as properties 12 * directly, assuming that the data associated with a mark is a number. While 13 * this is convenient for single-use scales, frequently it is desirable to 14 * define scales globally: 15 * 16 * <pre>var y = pv.Scale.linear(0, 100).range(0, 640);</pre> 17 * 18 * The <tt>y</tt> scale can now be equivalently referenced within a property: 19 * 20 * <pre> .height(function(d) y(d))</pre> 21 * 22 * Alternatively, if the data are not simple numbers, the appropriate value can 23 * be passed to the <tt>y</tt> scale (e.g., <tt>d.foo</tt>). The {@link #by} 24 * method similarly allows the data to be mapped to a numeric value before 25 * performing the linear transformation. 26 * 27 * @see pv.Scale.quantitative 28 * @see pv.Scale.quantile 29 * @see pv.Scale.ordinal 30 * @extends function 31 */ 32 pv.Scale = function() {}; 33 34 /** 35 * @private Returns a function that interpolators from the start value to the 36 * end value, given a parameter <i>t</i> in [0, 1]. 37 * 38 * @param start the start value. 39 * @param end the end value. 40 */ 41 pv.Scale.interpolator = function(start, end) { 42 if (typeof start == "number") { 43 return function(t) { 44 return t * (end - start) + start; 45 }; 46 } 47 48 /* For now, assume color. */ 49 start = pv.color(start).rgb(); 50 end = pv.color(end).rgb(); 51 return function(t) { 52 var a = start.a * (1 - t) + end.a * t; 53 if (a < 1e-5) a = 0; // avoid scientific notation 54 return (start.a == 0) ? pv.rgb(end.r, end.g, end.b, a) 55 : ((end.a == 0) ? pv.rgb(start.r, start.g, start.b, a) 56 : pv.rgb( 57 Math.round(start.r * (1 - t) + end.r * t), 58 Math.round(start.g * (1 - t) + end.g * t), 59 Math.round(start.b * (1 - t) + end.b * t), a)); 60 }; 61 }; 62 63 /** 64 * Returns a view of this scale by the specified accessor function <tt>f</tt>. 65 * Given a scale <tt>y</tt>, <tt>y.by(function(d) d.foo)</tt> is equivalent to 66 * <tt>function(d) y(d.foo)</tt>. 67 * 68 * <p>This method is provided for convenience, such that scales can be 69 * succinctly defined inline. For example, given an array of data elements that 70 * have a <tt>score</tt> attribute with the domain [0, 1], the height property 71 * could be specified as: 72 * 73 * <pre> .height(pv.Scale.linear().range(0, 480).by(function(d) d.score))</pre> 74 * 75 * This is equivalent to: 76 * 77 * <pre> .height(function(d) d.score * 480)</pre> 78 * 79 * This method should be used judiciously; it is typically more clear to invoke 80 * the scale directly, passing in the value to be scaled. 81 * 82 * @function 83 * @name pv.Scale.prototype.by 84 * @param {function} f an accessor function. 85 * @returns {pv.Scale} a view of this scale by the specified accessor function. 86 */ 87