d3.patternGetNextClass = function(svg) { function increment() { var selection = svg.select("#d3Pattern-"+i) if (!selection.empty()) { return false; } return true; } var i = 0; while (!increment(i)) { i++; if ( i > 1000) break; // upper limit of patterns } return "d3Pattern-"+i; } d3.patternStripes = function(p,_) { var colors = ["olive","white"]; var stripeWidth = 10; var angle = 45; var opacity = 1; var id = null; var svg = d3.select("svg"); if(p) svg = p; if(_) id = _; else id = d3.patternGetNextClass(svg); function patternStripes() { } patternStripes.width = function(_) { if(!_) return stripeWidth; stripeWidth = _; this.add(); return patternStripes; } patternStripes.colors = function(_) { if(!_) return colors; colors = _; this.add(); return patternStripes; } patternStripes.opacity = function(_) { if(!_) return opacity; opacity = _; this.add(); return patternStripes; } patternStripes.angle = function(_) { if(!_) return angle; angle = _; this.add(); return patternStripes; } patternStripes.svg = function(_) { if(!_) return svg; svg = _; this.add(); return patternStripes; } patternStripes.add = function() { var defs = svg.select("defs"); // add defs if not present if(defs.empty()) defs = svg.append("defs"); // set width to an array if not already: if (!Array.isArray(stripeWidth)) stripeWidth = [stripeWidth]; // set opacity to an array if not already: if (!Array.isArray(opacity)) opacity = [opacity]; var totalWidth = 0; var currentX = 0; colors.forEach(function(d,i) { totalWidth += stripeWidth[i%stripeWidth.length]; }) var pattern = svg.select("#"+id); // append pattern if needed: if (pattern.empty()) pattern = defs.append("pattern") pattern .attr("width", totalWidth) .attr("height", 20) // arbitrary. .attr("patternUnits","userSpaceOnUse") .attr("patternTransform","rotate("+angle+")") .attr("id",id); var rects = pattern.selectAll("rect") .data(colors); rects.exit().remove(); var enter = rects.enter() .append("rect"); enter.merge(rects) .attr("width", function(d,i) { return stripeWidth[i%stripeWidth.length]; }) .attr("height", 20) .attr("x", function(d,i) { currentX += stripeWidth[i%stripeWidth.length]; return currentX - stripeWidth[i%stripeWidth.length]; }) .attr("y",0) .attr("fill",function(d,i) { return colors[i]; }) .attr("opacity",function(d,i) { return opacity[i%opacity.length]; }) return patternStripes; } patternStripes.use = function() { return "url(#"+id+")"; } patternStripes.add(); return patternStripes; } ////////////////////////////////////////////////////////////////////// // Plaid Pattern ///////////////////////////////////////////////////////////////////// d3.patternPlaid = function(p,_) { var colorsX = ["steelblue","white"]; var colorsY = ["darkblue","lightsteelblue"]; var widthX = 10; var widthY = 10; var opacityX = [0.3,0.7]; var opacityY = [0.3,0.7]; var angle = 45; var id = null; var svg = d3.select("svg"); if(p) svg = p; if(_) id = _; else id = d3.patternGetNextClass(svg); function patternPlaid() { } patternPlaid.widthX = function(_) { if(!_) return widthX; widthX = _; this.add(); return patternPlaid; } patternPlaid.widthY = function(_) { if(!_) return widthY; widthY = _; this.add(); return patternPlaid; } patternPlaid.colorsX = function(_) { if(!_) return colorsX; colorsX = _; this.add(); return patternPlaid; } patternPlaid.colorsY = function(_) { if(!_) return colorsY; colorsY = _; this.add(); return patternPlaid; } patternPlaid.opacityX = function(_) { if(!_) return opacityX; opacityX = _; this.add(); return patternPlaid; } patternPlaid.opacityY = function(_) { if(!_) return opacityY; opacityY = _; this.add(); return patternPlaid; } patternPlaid.colorsY = function(_) { if(!_) return colorsY; colorsY = _; this.add(); return patternPlaid; } patternPlaid.angle = function(_) { if(!_) return angle; angle = _; this.add(); return patternPlaid; } patternPlaid.svg = function(_) { if(!_) return svg; svg = _; this.add(); return patternPlaid; } patternPlaid.add = function() { var defs = svg.select("defs"); // add defs if not present if(defs.empty()) defs = svg.append("defs"); // set width to an array if not already: if (!Array.isArray(widthX)) widthX = [widthX]; if (!Array.isArray(widthY)) widthY = [widthY]; // set opacity to an array if not already: if (!Array.isArray(opacityX)) opacityX = [opacityX]; if (!Array.isArray(opacityY)) opacityY = [opacityY]; var totalX = 0; var currentX = 0; var totalY = 0; var currentY = 0; colorsX.forEach(function(d,i) { totalX += widthX[i%widthX.length]; }) colorsY.forEach(function(d,i) { totalY += widthY[i%widthY.length]; }) var pattern = svg.select("#"+id); // append pattern if needed: if (pattern.empty()) pattern = defs.append("pattern") pattern .attr("width", totalX) .attr("height", totalY) .attr("patternUnits","userSpaceOnUse") .attr("patternTransform","rotate("+angle+")") .attr("id",id); /////////// X var rectsX = pattern.selectAll("rectX") .data(colorsX); rectsX.exit().remove(); var enter = rectsX.enter() .append("rect") .attr("class","rectX"); enter.merge(rectsX) .attr("width", function(d,i) { return widthX[i%widthX.length]; }) .attr("height", 20) .attr("x", function(d,i) { currentX += widthX[i%widthX.length]; return currentX - widthX[i%widthX.length]; }) .attr("y",0) .attr("fill",function(d,i) { return colorsX[i]; }) .attr("opacity",function(d,i) { return opacityX[i%opacityX.length]; }) //////// Y var rectsY = pattern.selectAll("rectY") .data(colorsY); rectsY.exit().remove(); var enter = rectsY.enter() .append("rect") .attr("class","rectY"); enter.merge(rectsY) .attr("height", function(d,i) { return widthY[i%widthY.length]; }) .attr("width", 20) .attr("y", function(d,i) { currentY += widthY[i%widthY.length]; return currentY - widthY[i%widthY.length]; }) .attr("x",0) .attr("fill",function(d,i) { return colorsY[i]; }) .attr("opacity",function(d,i) { return opacityY[i%opacityY.length]; }) return patternPlaid; } patternPlaid.use = function() { return "url(#"+id+")"; } patternPlaid.add(); return patternPlaid; } ////////////////////////////////////////////////////////////////////// // Checker Pattern ///////////////////////////////////////////////////////////////////// d3.patternCheckers = function(p,_) { var colors = ["orange","white"] var width = 10; var angle = 0; var opacity = 1; var id = null; var svg = d3.select("svg"); if(p) svg = p; if(_) id = _; else id = d3.patternGetNextClass(svg); function patternCheckers() { } patternCheckers.width = function(_) { if(!_) return width; width = _; this.add(); return patternCheckers; } patternCheckers.colors = function(_) { if(!_) return colors; colors = _; this.add(); return patternCheckers; } patternCheckers.angle = function(_) { if(!_) return angle; angle = _; this.add(); return patternCheckers; } patternCheckers.opacity = function(_) { if(!_) return opacity; opacity = _; this.add(); return patternCheckers; } patternCheckers.svg = function(_) { if(!_) return svg; svg = _; this.add(); return patternCheckers; } patternCheckers.add = function() { var defs = svg.select("defs"); // add defs if not present if(defs.empty()) defs = svg.append("defs"); // set opacity to an array if not already: if (!Array.isArray(opacity)) opacity = [opacity]; var totalWidth = width * 2; var pattern = svg.select("#"+id); // append pattern if needed: if (pattern.empty()) pattern = defs.append("pattern") pattern .attr("width", totalWidth) .attr("height", totalWidth) .attr("patternUnits","userSpaceOnUse") .attr("patternTransform","rotate("+angle+")") .attr("id",id); pattern.selectAll("rect").remove(); var rects = pattern.selectAll("rect") .data(d3.range(4)) .enter() .append("rect") .attr("width", width ) .attr("height", width ) .attr("x", function(d,i) { return i%2 * width; }) .attr("y", function(d,i) { return Math.floor(i/2) * width; }) .attr("fill",function(d,i) { return (i == 0 || i == 3) ? colors[0] : colors[1]; } ) .attr("opacity", function(d,i) { return (i == 0 || i == 3) ? opacity[0] : opacity[1%opacity.length]; } ) return patternCheckers; } patternCheckers.use = function() { return "url(#"+id+")"; } patternCheckers.add(); return patternCheckers; } ////////////////////////////////////////////////////////////////////// // Dots Pattern ///////////////////////////////////////////////////////////////////// d3.patternDots = function(p,_) { var color = "steelblue"; var spacing = 5; var radius = 1; var angle = 0; var opacity = 1; var id = null; var svg = d3.select("svg"); if(p) svg = p; if(_) id = _; else id = d3.patternGetNextClass(svg); function patternDots() { } patternDots.spacing = function(_) { if(!_) return spacing; spacing = _; this.add(); return patternDots; } patternDots.color = function(_) { if(!_) return color; color = _; this.add(); return patternDots; } patternDots.radius = function(_) { if(!_) return radius; radius = _; this.add(); return patternDots; } patternDots.angle = function(_) { if(!_) return angle; angle = _; this.add(); return patternDots; } patternDots.opacity = function(_) { if(!_) return opacity; opacity = _; this.add(); return patternDots; } patternDots.svg = function(_) { if(!_) return svg; svg = _; return patternDots; } patternDots.add = function() { var defs = svg.select("defs"); // add defs if not present if(defs.empty()) defs = svg.append("defs"); var pattern = svg.select("#"+id); // append pattern if needed: if (pattern.empty()) pattern = defs.append("pattern") pattern .attr("width", spacing) .attr("height", spacing) .attr("patternUnits","userSpaceOnUse") .attr("patternTransform","rotate("+angle+")") .attr("id",id); var circle = pattern.select("circle"); if(circle.empty()) circle = pattern.append("circle"); circle .attr("cx", spacing/2 ) .attr("cy", spacing/2 ) .attr("r", radius) .attr("fill", color); return patternDots; } patternDots.use = function() { return "url(#"+id+")"; } patternDots.add(); return patternDots; } ////////////////////////////////////////////////////////////////////// // symbol ///////////////////////////////////////////////////////////////////// d3.patternSymbols = function(p,_) { var color = "crimson"; var stroke = "none"; var spacing = 16; var angle = 0; var path = d3.symbol().type(d3.symbolStar); var id = null; var svg = d3.select("svg"); if(p) svg = p; if(_) id = _; else id = d3.patternGetNextClass(svg); function patternSymbols() { } patternSymbols.spacing = function(_) { if(!_) return spacing; spacing = _; this.add(); return patternSymbols; } patternSymbols.color = function(_) { if(!_) return color; color = _; this.add(); return patternSymbols; } patternSymbols.stroke = function(_) { if(!_) return stroke; stroke = _; this.add(); return patternSymbols; } patternSymbols.symbol = function(_) { if(!_) return path; path = _; this.add(); return patternSymbols; } patternSymbols.angle = function(_) { if(!_) return angle; angle = _; this.add(); return patternSymbols; } patternSymbols.svg = function(_) { if(!_) return svg; svg = _; this.add(); return patternSymbols; } patternSymbols.add = function() { var defs = svg.select("defs"); // add defs if not present if(defs.empty()) defs = svg.append("defs"); var pattern = svg.select("#"+id); // append pattern if needed: if (pattern.empty()) pattern = defs.append("pattern") pattern .attr("width", spacing) .attr("height", spacing) .attr("patternUnits","userSpaceOnUse") .attr("patternTransform","rotate("+angle+")") .attr("id",id); var symbol = pattern.select("path"); if(symbol.empty()) symbol = pattern.append("path"); symbol .attr("transform","translate("+[spacing/2,spacing/2]+ ")") .attr("d", path ) .attr("stroke", stroke) .attr("fill", color); return patternSymbols; } patternSymbols.use = function() { return "url(#"+id+")"; } patternSymbols.add(); return patternSymbols; } ////////////////////////////////////////////////////////////////////// // Squares Pattern ///////////////////////////////////////////////////////////////////// d3.patternSquares = function(p,_) { var color = "steelblue"; var spacing = 10; var length = 5; var angle = 0; var id = null; var svg = d3.select("svg"); if(p) svg = p; if(_) id = _; else id = d3.patternGetNextClass(svg); function patternSquares() { } patternSquares.spacing = function(_) { if(!_) return spacing; spacing = _; this.add(); return patternSquares; } patternSquares.color = function(_) { if(!_) return color; color = _; this.add(); return patternSquares; } patternSquares.edgeLength = function(_) { if(!_) return length; length = _; this.add(); return patternSquares; } patternSquares.angle = function(_) { if(!_) return angle; angle = _; this.add(); return patternSquares; } patternSquares.svg = function(_) { if(!_) return svg; svg = _; this.add(); return patternSquares; } patternSquares.add = function() { var defs = svg.select("defs"); // add defs if not present if(defs.empty()) defs = svg.append("defs"); var pattern = svg.select("#"+id); // append pattern if needed: if (pattern.empty()) pattern = defs.append("pattern") pattern .attr("width", spacing) .attr("height", spacing) .attr("patternUnits","userSpaceOnUse") .attr("patternTransform","rotate("+angle+")") .attr("id",id); var rect = pattern.select("rect"); if(rect.empty()) rect = pattern.append("rect"); rect .attr("x", spacing/2 - length/2) .attr("y", spacing/2 - length/2) .attr("width", length) .attr("height", length) .attr("fill", color); return patternSquares; } patternSquares.use = function() { return "url(#"+id+")"; } patternSquares.add(); return patternSquares; }