// Creates a texture scale that combines pattern, color, and size. function createTextureScale(){ var patternScale, colorScale, sizeScale, patternAccessor, colorAccessor, sizeAccessor, texturesCache = {}; function my(d){ // Extract data values using accessors. var patternValue = patternAccessor(d), colorValue = colorAccessor(d), sizeValue = sizeAccessor(d), // Use data values to look up the texture. key = [patternValue, colorValue, sizeValue].join(","), texture = texturesCache[key], pattern, color, size; // Create a new texture the first time each unique // (texture, color, size) combination is encountered. if(!texture){ // Evaluate scaled values for pattern, color, and size. pattern = patternScale(patternValue); color = colorScale(colorValue); size = sizeScale(sizeValue); // Create the base texture with the pattern generator. texture = pattern(); // Apply color. texture = colorizeTexture(texture, color); // Apply size. texture = texture.size(size); // Initialize the texture. svg.call(texture); // Store the texture for future reuse. texturesCache[key] = texture; } // Return the url so this function can be passed directly into the fill attribute. return texture.url(); } // Makes the given texture appear as the given color. function colorizeTexture(texture, color){ // Use stroke, present on all patterns. var texture = texture.stroke(color); // Use fill, present only on some textures (e.g. "circles", not "lines"). if(texture.fill){ texture.fill(color); } return texture; } // API design inspired by http://bost.ocks.org/mike/chart/ my.patternScale = function(value){ if (!arguments.length) return patternScale; patternScale = value; return my; }; my.colorScale = function(value){ if (!arguments.length) return colorScale; colorScale = value; return my; }; my.sizeScale = function(value){ if (!arguments.length) return sizeScale; sizeScale = value; return my; }; my.patternAccessor = function(value){ if (!arguments.length) return patternAccessor; patternAccessor = value; return my; }; my.colorAccessor = function(value){ if (!arguments.length) return colorAccessor; colorAccessor = value; return my; }; my.sizeAccessor = function(value){ if (!arguments.length) return sizeAccessor; sizeAccessor = value; return my; }; return my; }