|
(function (global, factory) { |
|
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : |
|
typeof define === 'function' && define.amd ? define(['exports'], factory) : |
|
(factory((global.ln = global.ln || {}))); |
|
}(this, (function (exports) { 'use strict'; |
|
|
|
|
|
////////////////////////////////////////////////////////////////////// |
|
// Master Pattern |
|
function pt(S,I) { |
|
var p = {}; |
|
// basic set up: |
|
p.sel = S || d3.select("svg"); // attempt to select SVG by default |
|
if(p.sel.node() && p.sel.node().nodeName != "svg") console.log("no svg found"); |
|
|
|
if(I) p.id = I; |
|
else p.id = patternGetNextClass(p.sel); |
|
|
|
// basic pattern info: |
|
p.bg = "none"; |
|
p.sw = 0; |
|
p.s = "#000"; |
|
p.o = 1; |
|
p.a = 0; |
|
|
|
p.background = function(_) { if(!arguments.length) return p.bg; p.bg = _; return p; } |
|
p.strokeWidth = function(_) { if(!arguments.length) return p.sw; p.sw = _; return p; } |
|
p.stroke = function(_) { if(!arguments.length) return p.s; p.s = _; return p; } |
|
p.opacity = function(_) { if(!arguments.length) return p.o; p.o = _; return p; } |
|
p.angle = function(_) { if(!arguments.length) return p.a; p.a = _; return p; } |
|
|
|
p.use = function() { |
|
p.add(); |
|
return "url(#"+p.id+")"; |
|
} |
|
|
|
return p; |
|
} |
|
////////////////////////////////////////////////////////////////////// |
|
// Master Pattern for Centered Shape |
|
function ptCentered(S,I) { |
|
var p = pt(S,I); |
|
|
|
p.f = "steelblue"; |
|
p.hx = true; |
|
p.sp = 2; |
|
|
|
p.fill = function(_) { if(!arguments.length) return p.f; p.f = _; return p; } |
|
p.hex = function(_) { if(!arguments.length) return p.hx; p.hx = _; return p; } |
|
p.spacing = function(_) { if(!arguments.length) return p.sp; p.sp = _; return p; } |
|
|
|
return p; |
|
} |
|
////////////////////////////////////////////////////////////////////// |
|
// Single Square Pattern |
|
function ptSquare(S,I) { |
|
var p = ptCentered(S,I); |
|
|
|
p.l = 10; |
|
p.length = function(_) { if(!arguments.length) return p.l; p.l = _; return p; } |
|
|
|
p._sq = function(pt) { |
|
wh(pt,p.l + p.sp, p.l + p.sp); |
|
applyBG(pt,p.bg,p.l + p.sp, p.l + p.sp); |
|
var d = [[p.sp/2,p.sp/2]]; |
|
var r = pt.selectAll(".rect") |
|
.data(d); |
|
|
|
r.exit().remove(); |
|
r.enter().append("rect").attr("class","rect"); |
|
} |
|
|
|
p._hx = function(pt) { |
|
var d = hxCentroids(p.sp + p.l); |
|
wh(pt,d.w,d.h); |
|
applyBG(pt,p.bg,d.w,d.h); |
|
|
|
pt.selectAll(".rect") |
|
.data(d.c) |
|
.enter() |
|
.append("rect") |
|
.attr("class","rect"); |
|
} |
|
|
|
p._style = function(pt) { |
|
pt.selectAll(".rect") |
|
.attr("x", function(d) { return d[0] }) |
|
.attr("y", function(d) { return d[1] }) |
|
.attr("width", p.l) |
|
.attr("height",p.l) |
|
.attr("fill", p.f) |
|
.attr("stroke",p.s) |
|
.attr("stroke-width",p.sw); |
|
} |
|
p.add = function() { |
|
var defs = checkDefs(p.sel); |
|
var pt = checkPattern(p.sel,defs,p.id); |
|
ptProps(pt,p.a,p.id); |
|
|
|
if (p.hx) p._hx(pt); |
|
else p._sq(pt); |
|
|
|
p._style(pt); |
|
return p; |
|
} |
|
p.add(); |
|
return p; |
|
} |
|
////////////////////////////////////////////////////////////////////// |
|
// Single Circle Pattern |
|
function ptCircle(S,I) { |
|
var p = ptCentered(S,I); |
|
|
|
p.r = 10; |
|
p.radius = function(_) { if(!arguments.length) return p.r; p.r = _; return p; } |
|
|
|
p._sq = function(pt) { |
|
wh(pt,p.r*2+p.sp,p.r*2+p.sp); |
|
applyBG(pt,p.bg,p.r*2+p.sp,p.r*2+p.sp); |
|
var d = [[p.sp/2+p.r,p.sp/2+p.r]]; |
|
var c = pt.selectAll("circle") |
|
.data(d); |
|
|
|
c.exit().remove(); |
|
c.enter().append("circle"); |
|
} |
|
p._hx = function(pt) { |
|
var d = hxCentroids((p.sp/2 + p.r)/0.866); |
|
wh(pt,d.w,d.h); |
|
applyBG(pt,p.bg,d.w,d.h); |
|
|
|
pt.selectAll("circle") |
|
.data(d.c) |
|
.enter() |
|
.append("circle"); |
|
} |
|
p._style = function(pt) { |
|
pt.selectAll("circle") |
|
.attr("cx", function(d) { return d[0] }) |
|
.attr("cy", function(d) { return d[1] }) |
|
.attr("r", p.r) |
|
.attr("fill", p.f) |
|
.attr("stroke",p.s) |
|
.attr("stroke-width",p.sw); |
|
} |
|
|
|
p.add = function() { |
|
var defs = checkDefs(p.sel); |
|
var pt = checkPattern(p.sel,defs,p.id); |
|
ptProps(pt,p.a,p.id); |
|
|
|
if (p.hx) p._hx(pt); |
|
else p._sq(pt); |
|
|
|
p._style(pt); |
|
return p; |
|
} |
|
p.add(); |
|
return p; |
|
} |
|
////////////////////////////////////////////////////////////////////// |
|
// Single Hexagon Pattern |
|
function ptHexagon(S,I) { |
|
var p = ptCentered(S,I); |
|
|
|
p.r = 10; |
|
p.radius = function(_) { if(!arguments.length) return p.r; p.r = _; return p; } |
|
|
|
p._sq = function(pt) { |
|
wh(pt,p.r*2+p.sp,p.r*2+p.sp); |
|
applyBG(pt,p.bg,p.r*2+p.sp,p.r*2+p.sp); |
|
var d = [[p.sp/2+p.r,p.sp/2+p.r]]; |
|
var c = pt.selectAll("path") |
|
.data(d); |
|
|
|
c.exit().remove(); |
|
c.enter().append("path"); |
|
} |
|
p._hx = function(pt) { |
|
var d = hxCentroids((p.sp/2 + p.r)); |
|
wh(pt,d.w,d.h); |
|
applyBG(pt,p.bg,d.w,d.h); |
|
|
|
pt.selectAll("path") |
|
.data(d.c) |
|
.enter() |
|
.append("path"); |
|
} |
|
p._style = function(pt) { |
|
pt.selectAll("path") |
|
.attr("d", function(d) { return hexPath(d[0],d[1],p.r); }) |
|
.attr("fill", p.f) |
|
.attr("stroke",p.s) |
|
.attr("stroke-width",p.sw); |
|
} |
|
|
|
p.add = function() { |
|
var defs = checkDefs(p.sel); |
|
var pt = checkPattern(p.sel,defs,p.id); |
|
ptProps(pt,p.a,p.id); |
|
|
|
if (p.hx) p._hx(pt); |
|
else p._sq(pt); |
|
|
|
p._style(pt); |
|
return p; |
|
} |
|
p.add(); |
|
return p; |
|
} |
|
////////////////////////////////////////////////////////////////////// |
|
// Single Letter Pattern |
|
function ptLetter(S,I) { |
|
var p = ptCentered(S,I); |
|
|
|
p.t = "\u03B1"; |
|
p.dy = 5; |
|
p.k = 14; |
|
|
|
p.offsetY = function(_) { if(!arguments.length) return p.dy; p.dy = _; return p; } |
|
p.text = function(_) { if(!arguments.length) return p.t; p.t = _; return p; } |
|
p.fontSize = function(_){ if(!arguments.length) return p.k; p.k = _; return p; } |
|
p.sp = 20; |
|
|
|
p._sq = function(pt) { |
|
wh(pt,p.sp,p.sp); // set width/height |
|
applyBG(pt,p.bg,p.sp,p.sp); // set background rect |
|
var d = [[p.sp/2,p.sp/2]]; // middle of each path. |
|
var c = pt.selectAll("text") |
|
.data(d); |
|
|
|
c.exit().remove(); |
|
c.enter().append("text"); |
|
} |
|
p._hx = function(pt) { |
|
var d = hxCentroids((p.sp/2 )); // get hex info, |
|
wh(pt,d.w,d.h); // set width/height |
|
applyBG(pt,p.bg,d.w,d.h); // set background rect |
|
|
|
pt.selectAll("text") |
|
.data(d.c) |
|
.enter() |
|
.append("text"); |
|
} |
|
p._style = function(pt) { |
|
pt.selectAll("text") |
|
.text(p.t) |
|
.style("text-anchor","middle") |
|
.attr("fill", p.f) |
|
.attr("stroke",p.s) |
|
.attr("stroke-width",p.sw) |
|
.attr("x", function(d) { return d[0]; }) |
|
.attr("y", function(d) { return d[1]; }) |
|
.style("font-size",p.k) |
|
.attr("dy",p.dy); |
|
} |
|
|
|
p.add = function() { |
|
var defs = checkDefs(p.sel); |
|
var pt = checkPattern(p.sel,defs,p.id); |
|
ptProps(pt,p.a,p.id); |
|
|
|
if (p.hx) p._hx(pt); |
|
else p._sq(pt); |
|
|
|
p._style(pt); |
|
return p; |
|
} |
|
p.add(); |
|
return p; |
|
} |
|
////////////////////////////////////////////////////////////////////// |
|
// Single Symbol Pattern |
|
function ptSymbol(S,I) { |
|
var p = ptCentered(S,I); |
|
|
|
p.sym = d3.symbol().type(d3.symbolWye).size(100); |
|
p.r = 14; |
|
p.symbol = function(_) { if(!arguments.length) return p.sym; p.sym = _; return p; } |
|
|
|
p.dx = 0; p.dy = 0; |
|
p.center = function(_) { if(!arguments.length) return [p.dx,p.dy]; p.dx = _[0]; p.dy = _[1]; return p; } |
|
|
|
p.sc = 1; |
|
p.scale = function(_) { if(!arguments.length) return p.sc; p.sc = _; return p; } |
|
|
|
p.sp = 16; |
|
|
|
p._sq = function(pt) { |
|
wh(pt,p.sp,p.sp); |
|
applyBG(pt,p.bg,p.sp,p.sp); |
|
var d = [[p.sp/2,p.sp/2]]; |
|
var c = pt.selectAll("path") |
|
.data(d); |
|
|
|
c.exit().remove(); |
|
c.enter().append("path"); |
|
} |
|
p._hx = function(pt) { |
|
var d = hxCentroids(p.sp/2*1.414); |
|
wh(pt,d.w,d.h); |
|
applyBG(pt,p.bg,d.w,d.h); |
|
|
|
pt.selectAll("path") |
|
.data(d.c) |
|
.enter() |
|
.append("path"); |
|
} |
|
p._style = function(pt) { |
|
pt.selectAll("path") |
|
.attr("d", p.sym) |
|
.attr("transform",function(d) { return "translate("+([d[0]-(p.dx*p.sc),d[1]-(p.dy*p.sc)])+ ")scale("+p.sc+")" }) |
|
.attr("r", p.r) |
|
.attr("fill", p.f) |
|
.attr("stroke",p.s) |
|
.attr("stroke-width",p.sw); |
|
} |
|
|
|
p.add = function() { |
|
var defs = checkDefs(p.sel); |
|
var pt = checkPattern(p.sel,defs,p.id); |
|
ptProps(pt,p.a,p.id); |
|
|
|
if (p.hx) p._hx(pt); |
|
else p._sq(pt); |
|
|
|
p._style(pt); |
|
return p; |
|
} |
|
p.add(); |
|
return p; |
|
} |
|
////////////////////////////////////////////////////////////////////// |
|
// Common Symbols |
|
// Symbols from Maki: https://www.mapbox.com/maki-icons/ |
|
var ptWetland = function(S,I) { |
|
var pt = ptSymbol(S,I); |
|
pt.background("lightblue").fill("darkgreen").stroke("black").scale(0.8).strokeWidth(0).spacing(30).center([12,12]) |
|
.symbol("M 2.6181942,7.0403716 C 3.2611586,6.454134 4.0830945,6.157614 4.9177382,6.2107118 6.7744687,6.0665089 8.4206096,7.5109538 8.699883,9.5293512 L 9.8799123,17.294968 C 8.912591,16.814927 7.7983711,16.845458 6.8541964,17.377933 L 5.64391,9.5293512 C 5.2012477,8.0935415 3.9988281,7.1045871 2.6181942,7.0403716 Z M 11.695343,18.224187 c 0.577305,-0.510407 1.248106,-0.878278 1.966714,-1.078557 L 15.507745,4.5513921 C 15.950405,3.1155825 17.152827,2.126628 18.53346,2.0624123 17.898363,1.4841395 17.088681,1.1881167 16.264172,1.2327526 14.407443,1.0885575 12.761302,2.532995 12.482028,4.5513921 L 10.515313,17.477493 c 0.421482,0.191155 0.818154,0.442211 1.18003,0.746694 z m 6.535546,-0.82966 0,0 c 0.236762,-0.211896 0.489864,-0.400559 0.756429,-0.56417 l 1.059,-7.3010058 C 20.488982,8.0935415 21.691399,7.1045871 23.072034,7.0403716 22.436936,6.462098 21.627254,6.1660758 20.802747,6.2107118 18.946017,6.0665089 17.299875,7.5109538 17.020603,9.5293512 l -1.013615,6.6372778 c 0.821632,0.204099 1.585173,0.625564 2.223901,1.227898 z m 3.328289,2.090743 0,0 c -0.657491,-0.0166 -1.297883,0.231308 -1.800303,0.696914 l -0.711042,0.68032 c -0.430713,0.422465 -1.082149,0.422465 -1.512861,0 -0.226928,-0.199119 -0.438726,-0.431422 -0.665655,-0.647135 -1.070499,-0.990281 -2.636005,-0.990281 -3.706504,0 -0.242056,0.215713 -0.468985,0.464611 -0.711042,0.680322 -0.43071,0.422464 -1.082147,0.422464 -1.512859,0 -0.242056,-0.215711 -0.468985,-0.464609 -0.711042,-0.680322 -1.0679267,-0.980989 -2.6234473,-0.980989 -3.6913739,0 C 6.3095677,20.431082 6.0977674,20.663385 5.8708388,20.862504 5.735892,20.981147 5.5820341,21.071246 5.4169813,21.127998 4.974924,21.236186 4.5139564,21.078058 4.206695,20.713167 3.8322624,20.358071 3.4325654,20.036328 3.0115371,19.750761 2.6992833,19.555125 2.3419462,19.462869 1.9827937,19.48527 l -0.090771,0 c -0.4177004,0 -0.7564291,0.371522 -0.7564291,0.829659 0,0.45814 0.3387287,0.82966 0.7564289,0.82966 l 0,0 c 0.3721631,0.02406 0.7204229,0.209075 0.9682291,0.514388 l 0.5446289,0.431425 c 1.0161869,0.912624 2.4671689,0.95361 3.524959,0.09956 0.2874433,-0.232304 0.5446289,-0.530982 0.8320721,-0.779879 0.4307105,-0.422462 1.0821469,-0.422462 1.5128579,0 l 0.5900146,0.580762 c 1.0494699,1.026953 2.6205729,1.075904 3.7216299,0.11614 0.226929,-0.182526 0.408472,-0.414832 0.635402,-0.61395 0.450227,-0.5041 1.187744,-0.512231 1.64735,-0.0184 0.0055,0.0061 0.01112,0.01222 0.0168,0.0184 l 0.590014,0.580763 c 0.736158,0.684303 1.737519,0.915281 2.662632,0.613948 0.578668,-0.171904 1.102269,-0.516545 1.512857,-0.995593 0.234342,-0.29403 0.555823,-0.48784 0.907718,-0.547574 l 0,0 c 0.417697,0 0.756426,-0.371521 0.756426,-0.82966 0,-0.458138 -0.338729,-0.829658 -0.756426,-0.829658 z"); |
|
return pt; |
|
} |
|
|
|
var ptFish = function(S,I) { |
|
var pt = ptSymbol(S,I); |
|
pt.background("#0077BE").fill("orange").stroke("black").strokeWidth(1).scale(0.8).spacing(30).center([12,12]) |
|
.symbol("m 17.055085,18.852887 c -0.444915,-0.983199 -0.444915,-3.768927 0,-4.588259 0.593221,-0.983198 5.042373,2.294129 5.042373,2.294129 1.334746,0.655466 1.334746,-9.9958486 0,-9.3403831 0,0 -4.597458,3.4411941 -5.042373,2.2941292 -0.444915,-1.1470646 -0.444915,-3.4411939 0,-4.5882585 C 17.5,3.9410464 23.135594,3.77718 23.135594,3.77718 c 0,-1.1470646 -4.300848,-2.2941292 -6.080509,-2.2941292 -1.779661,0 -3.707627,0.1638664 -6.080508,1.310931 C 8.6016949,3.77718 6.6737288,5.4158438 4.8940678,7.3822402 3.1144068,9.3486367 0.88983051,13.28143 0.88983051,14.428495 c 0,1.147064 2.22457629,4.588258 5.48728809,6.063055 3.2627119,1.474798 4.8940684,1.80253 6.6737294,2.130263 1.631356,0.163866 3.855932,0 5.783898,-0.491599 1.483051,-0.327733 4.300848,-1.147065 4.300848,-1.80253 0,-0.327733 -5.635594,-0.491599 -6.080509,-1.474797 z M 7.5635593,15.08396 c -1.1864407,0 -2.2245763,-1.147065 -2.2245763,-2.457996 0,-1.310931 1.0381356,-2.457995 2.2245763,-2.457995 1.1864407,0 2.2245763,1.147064 2.2245763,2.457995 0,1.310931 -1.0381356,2.457996 -2.2245763,2.457996 z"); |
|
return pt; |
|
} |
|
var ptFire = function(S,I) { |
|
var fire = ptSymbol(S,I); |
|
fire.background("yellow").fill("orange").stroke("black").scale(0.6).spacing(30).center([12,12]) |
|
.symbol("M 12.108051,0.7923729 7.9588913,7.0366745 5.4693956,3.9145237 C 4.5486141,5.4370405 0.99427797,9.0542083 0.99427797,12.974381 c 0,5.773481 4.97583813,10.453585 11.11377303,10.453585 6.137935,0 11.113773,-4.680104 11.113773,-10.453585 0,-3.9201727 -3.554336,-7.5373405 -4.475118,-9.0598573 L 16.25721,7.0366745 12.108051,0.7923729 Z m 0,10.1469901 c 0,0 4.149159,3.999163 4.149159,7.024839 0,1.306776 -1.370716,3.122151 -4.149159,3.122151 -2.7784433,0 -4.1491597,-1.815375 -4.1491597,-3.122151 0,-2.921865 4.1491597,-7.024839 4.1491597,-7.024839 z"); |
|
return fire; |
|
} |
|
var ptDanger = function(S,I) { |
|
var danger = ptSymbol(S,I); |
|
danger.background("darkorange").fill("black").stroke("black").strokeWidth(0).scale(0.8).spacing(40).center([12,12]) |
|
.symbol("m 22.723729,22.613369 c -0.126052,0.290777 -0.44093,0.481882 -0.790981,0.479633 -0.100135,0.01604 -0.202793,0.01604 -0.302928,0 l -9.744214,-3.657207 -9.7610432,3.657207 c -0.4328517,0.150636 -0.9209039,-0.03987 -1.0898709,-0.425375 -0.00135,-0.0032 -0.00269,-0.0062 -0.00404,-0.0093 -0.2172674,-0.365871 -0.060249,-0.819425 0.3507243,-1.012776 0.043925,-0.02068 0.089868,-0.03792 0.1373278,-0.05141 L 9.6809563,18.596436 1.518705,15.598725 C 1.0740726,15.478367 0.82314655,15.059736 0.95828658,14.663738 1.0934264,14.267742 1.5634712,14.044262 2.0081035,14.16462 c 0.039885,0.01079 0.078762,0.02428 0.1164593,0.04017 l 9.7610432,3.612242 9.761043,-3.612242 c 0.419724,-0.177614 0.921745,-0.01858 1.121173,0.355229 0.199428,0.373815 0.02087,0.820924 -0.398856,0.998538 -0.0377,0.01604 -0.07658,0.02938 -0.116459,0.04017 l -8.179081,2.997711 8.162251,2.997711 c 0.438742,0.136395 0.670315,0.563719 0.517335,0.95447 -0.0086,0.02203 -0.01835,0.04361 -0.02928,0.06475 z m -3.2649,-15.6630409 0,0.6744849 c -0.0035,0.3191064 -0.121508,0.6289199 -0.336588,0.8843248 -0.940089,0.9267424 -1.952377,1.7932322 -3.029289,2.5930212 l 0,1.738672 c 0.0025,0.311761 -0.21205,0.592198 -0.53854,0.704462 l -3.635147,1.304004 -0.117806,0 -3.6519766,-1.304004 c -0.3002362,-0.1307 -0.4851911,-0.40709 -0.4712228,-0.704462 l 0,-1.738672 C 6.5890619,10.304018 5.5654987,9.4373789 4.6153117,8.5091378 4.4121811,8.2501355 4.3061559,7.9406219 4.3123827,7.624813 l 0,-0.6744849 C 4.5932652,3.625417 7.5055902,0.95595549 11.22926,0.61016949 l 0.605858,0 0,0 0.656346,0 c 3.746557,0.31940607 6.689344,2.99726121 6.967365,6.34015861 z M 9.361198,6.6055913 c 0,-0.8278179 -0.7534515,-1.4988554 -1.6829384,-1.4988554 -0.9294868,0 -1.6829384,0.6710375 -1.6829384,1.4988554 0,0.8278179 0.7534516,1.4988555 1.6829384,1.4988555 0.9294869,0 1.6829384,-0.6710376 1.6829384,-1.4988555 z m 1.682938,4.4965677 c 0,-0.413835 -0.376809,-0.749428 -0.841469,-0.749428 -0.4646591,0 -0.841469,0.335593 -0.841469,0.749428 l 0,0.749427 c 0,0.413834 0.3768099,0.749427 0.841469,0.749427 0.46466,0 0.841469,-0.335593 0.841469,-0.749427 l 0,-0.749427 z m 3.365878,0 c 0,-0.413835 -0.376811,-0.749428 -0.84147,-0.749428 -0.464659,0 -0.841469,0.335593 -0.841469,0.749428 l 0,0.749427 c 0,0.413834 0.37681,0.749427 0.841469,0.749427 0.464659,0 0.84147,-0.335593 0.84147,-0.749427 l 0,-0.749427 z m 3.365877,-4.4965677 c 0,-0.8278179 -0.753452,-1.4988554 -1.682939,-1.4988554 -0.929487,0 -1.682938,0.6710375 -1.682938,1.4988554 0,0.8278179 0.753451,1.4988555 1.682938,1.4988555 0.929487,0 1.682939,-0.6710376 1.682939,-1.4988555 z"); |
|
return danger; |
|
} |
|
////////////////////////////////////////////////////////////////////// |
|
// Checker |
|
function ptChecker(S,I) { |
|
var p = pt(S,I); |
|
|
|
p.w = 10; |
|
p.f = ["steelblue","white"]; |
|
p.width = function(_) { if(!arguments.length) return p.w; p.w = _; return p; } |
|
p.fill = function(_) { if(!arguments.length) return p.f; p.f = arr(_); return p; } |
|
p.a = 45; |
|
|
|
// go about drawing: |
|
p.add = function() { |
|
var defs = checkDefs(p.sel); |
|
var pt = checkPattern(p.sel,defs,p.id); |
|
ptProps(pt,p.a,p.id); |
|
|
|
p.o = arr(p.o); |
|
|
|
if (p.f.length == 1) p.f.push("white"); |
|
|
|
var totalWidth = p.w * 2; |
|
|
|
pt.attr("width", totalWidth) |
|
.attr("height", totalWidth) |
|
.attr("patternUnits","userSpaceOnUse") |
|
.attr("patternTransform","rotate("+p.a+")") |
|
.attr("id",p.id); |
|
|
|
var rects = pt.selectAll("rect") |
|
.data([[0,0],[0,p.w],[p.w,p.w],[p.w,0]]); |
|
|
|
rects.exit().remove(); |
|
|
|
var enter = rects.enter() |
|
.append("rect") |
|
|
|
enter.merge(rects) |
|
.attr("width", p.w) |
|
.attr("height", p.w) |
|
.attr("x", function(d,i) { return d[0]; }) |
|
.attr("y", function(d,i) { return d[1]; }) |
|
.attr("fill",function(d,i) { return p.f[i%2]; }) |
|
.attr("opacity",function(d,i) { return p.o[i%p.o.length]; }) |
|
|
|
|
|
return p; |
|
} |
|
p.add(); |
|
return p; |
|
} |
|
////////////////////////////////////////////////////////////////////// |
|
// Stripe |
|
function ptStripe(S,I) { |
|
var p = pt(S,I); |
|
|
|
p.w = [10]; |
|
p.f = ["steelblue","white"]; |
|
p.width = function(_) { if(!arguments.length) return p.w; p.w = arr(_); return p; } |
|
p.fill = function(_) { if(!arguments.length) return p.f; p.f = arr(_); return p; } |
|
p.a = 45; |
|
|
|
// go about drawing: |
|
p.add = function() { |
|
var defs = checkDefs(p.sel); |
|
var pt = checkPattern(p.sel,defs,p.id); |
|
ptProps(pt,p.a,p.id); |
|
|
|
p.o = arr(p.o); |
|
|
|
if (p.f.length == 1) p.f.push("white"); |
|
|
|
var totalWidth = 0; |
|
var currentX = 0; |
|
|
|
p.f.forEach(function(d,i) { |
|
totalWidth += p.w[i%p.w.length]; |
|
}) |
|
|
|
pt.attr("width", totalWidth) |
|
.attr("height", 20) |
|
.attr("patternUnits","userSpaceOnUse") |
|
.attr("patternTransform","rotate("+p.a+")") |
|
.attr("id",p.id); |
|
|
|
var rects = pt.selectAll("rect") |
|
.data(p.f); |
|
|
|
rects.exit().remove(); |
|
|
|
var enter = rects.enter() |
|
.append("rect"); |
|
|
|
enter.merge(rects) |
|
.attr("width", function(d,i) { return p.w[i%p.w.length]; }) |
|
.attr("height", 20) |
|
.attr("x", function(d,i) { currentX += p.w[i%p.w.length]; return currentX - p.w[i%p.w.length]; }) |
|
.attr("y",0) |
|
.attr("fill",function(d,i) { return p.f[i]; }) |
|
.attr("opacity",function(d,i) { return p.o[i%p.o.length]; }) |
|
|
|
return p; |
|
} |
|
p.add(); |
|
return p; |
|
} |
|
////////////////////////////////////////////////////////////////////// |
|
// Plaid |
|
function ptPlaid(S,I) { |
|
var p = pt(S,I); |
|
|
|
p.w = [[10,5],[12,6]]; |
|
p.f = [["crimson","red"],["steelblue","white"]]; |
|
p.o = [[0.5,0.8],[0.6,0.4]]; |
|
|
|
p.width = function(_) { if(!arguments.length) return p.w; p.w = _; return p; } |
|
p.fill = function(_) { if(!arguments.length) return p.f; p.f = _; return p; } |
|
p.a = 45; |
|
|
|
// go about drawing: |
|
p.add = function() { |
|
var defs = checkDefs(p.sel); |
|
var pt = checkPattern(p.sel,defs,p.id); |
|
ptProps(pt,p.a,p.id); |
|
|
|
p.o = arr(p.o); |
|
p.w = arr(p.w); |
|
|
|
if (Array.isArray(p.w[0]) && p.w.length == 1) p.w.push(p.w[0]); else if(!Array.isArray(p.w[0])) { p.w = [p.w,p.w]; } |
|
if (Array.isArray(p.o[0]) && p.o.length == 1) p.o.push(p.o[0]); else if(!Array.isArray(p.o[0])) { p.o = [p.o,p.o]; } |
|
if (Array.isArray(p.f[0]) && p.f.length == 1) p.f.push(p.f[0]); else if(!Array.isArray(p.f[0])) { p.f = [p.f,p.f]; } |
|
|
|
var totalWidth = 0; |
|
var totalHeight = 0; |
|
var currentX = 0; |
|
var currentY = 0; |
|
|
|
p.f[0].forEach(function(d,i) { |
|
totalWidth += p.w[0][i%p.w[0].length]; |
|
}) |
|
p.f[1].forEach(function(d,i) { |
|
totalHeight += p.w[1][i%p.w[1].length]; |
|
}) |
|
|
|
pt.attr("width", totalWidth) |
|
.attr("height", totalHeight) |
|
.attr("patternUnits","userSpaceOnUse") |
|
.attr("patternTransform","rotate("+p.a+")") |
|
.attr("id",p.id); |
|
|
|
var r0 = pt.selectAll(".x") |
|
.data(p.f[0]); |
|
|
|
var r1 = pt.selectAll(".y") |
|
.data(p.f[1]); |
|
|
|
r0.exit().remove(); |
|
r1.exit().remove(); |
|
|
|
var e0 = r0.enter().append("rect").attr("class","x"); |
|
var e1 = r1.enter().append("rect").attr("class","y"); |
|
|
|
e0.merge(r0) |
|
.attr("width", function(d,i) { return p.w[0][i%p.w[0].length]; }) |
|
.attr("height", totalHeight) |
|
.attr("x", function(d,i) { currentX += p.w[0][i%p.w[0].length]; return currentX - p.w[0][i%p.w[0].length]; }) |
|
.attr("y",0) |
|
.attr("fill",function(d,i) { return p.f[0][i]; }) |
|
.attr("opacity",function(d,i) { return p.o[0][i%p.o.length]; }) |
|
e1.merge(r1) |
|
.attr("height", function(d,i) { return p.w[1][i%p.w[1].length]; }) |
|
.attr("width", totalWidth) |
|
.attr("y", function(d,i) { currentY += p.w[1][i%p.w[1].length]; return currentY - p.w[1][i%p.w[1].length]; }) |
|
.attr("x",0) |
|
.attr("fill",function(d,i) { return p.f[1][i]; }) |
|
.attr("opacity",function(d,i) { return p.o[1][i%p.o.length]; }) |
|
|
|
return p; |
|
} |
|
p.add(); |
|
return p; |
|
} |
|
////////////////////////////////////////////////////////////////////// |
|
// Cairo Pentagonal |
|
function ptCairo(S,I) { |
|
var p = pt(S,I); |
|
|
|
p.base = [[[0.7071067811865476,1.224744871391589],[0.2981726899245648,2.750907676928317],[1.1165716605051963,3.560304443015607],[2.641768897701186,3.161464390300587],[2.2332695867232757,1.6336789626535717]],[[0.7071067811865476,1.224744871391589],[1.1160408724485302,-0.30141793414513884],[0.29764190186789885,-1.1108147002324285],[-1.4190814287039564,0.0028104639365018613],[-0.8190560243501803,0.8158107801296063]],[[3.0426663528105653,0.8152799920729403],[2.6438263000955455,-0.7099172451230495],[4.159364279028645,-1.1113454882890943],[4.977763249609277,-0.3019487222018049],[4.5688291583472935,1.224214083334923]],[[2.641768897701186,3.161464390300587],[4.15989506708531,2.750376888871651],[4.978294037665942,3.5597736549589403],[4.56935994640396,5.0859364604956685],[3.043197140867232,4.677002369233686]],[[-1.2296127377224502,3.1594069879062276],[0.2981726899245648,2.750907676928317],[1.1165716605051963,3.560304443015607],[0.7076375692432135,5.086467248552335],[-0.8185252362935145,4.677533157290352]],[[1.1160408724485302,-0.30141793414513884],[2.6438263000955455,-0.7099172451230495],[3.0426663528105653,0.8152799920729403],[2.2332695867232757,1.6336789626535717],[0.7071067811865476,1.224744871391589]],[[1.1165716605051963,3.560304443015607],[2.641768897701186,3.161464390300587],[3.043197140867232,4.677002369233686],[2.2338003747799418,5.495401339814318],[0.7076375692432135,5.086467248552335]],[[-0.8190560243501803,0.8158107801296063],[0.7071067811865476,1.224744871391589],[0.2981726899245648,2.750907676928317],[-1.2296127377224502,3.1594069879062276],[-1.62845279043747,1.6342097507102378]],[[3.0426663528105653,0.8152799920729403],[4.5688291583472935,1.224214083334923],[4.15989506708531,2.750376888871651],[2.641768897701186,3.161464390300587],[2.2332695867232757,1.6336789626535717]]]; |
|
|
|
p.l = 20; |
|
p.f = ["#2b8cbe","#a8ddb5","#7bccc4","#ccebc5"]; |
|
p.a = 15; |
|
p.sw = 1; |
|
|
|
p.length = function(_) { if(!arguments.length) return p.l; p.l = _; return p; } |
|
p.fill = function(_) { if(!arguments.length) return p.f; p.f = _; return p; } |
|
p.a = 45; |
|
|
|
// go about drawing: |
|
p.add = function() { |
|
var defs = checkDefs(p.sel); |
|
var pt = checkPattern(p.sel,defs,p.id); |
|
ptProps(pt,p.a,p.id); |
|
|
|
var k = p.l/2; |
|
var w = k * 3.864; |
|
var c = [0,1,1,1,1,2,2,3,3]; |
|
|
|
var l = d3.line() |
|
.x(function(d) { return d[0]*k; }) |
|
.y(function(d) { return d[1]*k; }) |
|
|
|
pt.attr("width", w) |
|
.attr("height", w) |
|
.attr("patternUnits","userSpaceOnUse") |
|
.attr("patternTransform","rotate("+p.a+")") |
|
.attr("id",p.id); |
|
|
|
pt.selectAll("path") |
|
.data(p.base) |
|
.enter() |
|
.append("path") |
|
|
|
pt.selectAll("path") |
|
.attr("d",l) |
|
.attr("fill",function(d,i) { return p.f[c[i]]; }) |
|
.attr("stroke", p.s) |
|
.attr("stroke-width", p.sw) |
|
.attr("opacity",p.o) |
|
|
|
return p; |
|
} |
|
p.add(); |
|
return p; |
|
} |
|
|
|
////////////////////////////////////////////////////////////////////// |
|
// Octagon + Square |
|
function ptOctagon(S,I) { |
|
var p = pt(S,I); |
|
|
|
p.base = [[[0.707,0],[0,-0.707],[-0.707,0],[0,0.707]],[[0.707,2.41],[0,1.717],[-0.707,2.41],[0,3.12]],[[3.12,2.41],[2.41,1.71],[1.71,2.41],[2.41,3.12]],[[3.12,0],[2.41,-0.707],[1.71,0],[2.41,0.707]],[[0,0.707],[0,1.717],[0.71,2.41],[1.71,2.41],[2.41,1.71],[2.41,0.71],[1.71,0],[0.707,0],[0,0.707]]] |
|
|
|
p.l = 32; |
|
p.f = ["steelblue","white"] |
|
p.a = 15; |
|
p.sw = 1; |
|
|
|
p.length = function(_) { if(!arguments.length) return p.l; p.l = _; return p; } |
|
p.fill = function(_) { if(!arguments.length) return p.f; p.f = _; return p; } |
|
p.a =0; |
|
|
|
p.add = function() { |
|
var defs = checkDefs(p.sel); |
|
var pt = checkPattern(p.sel,defs,p.id); |
|
ptProps(pt,p.a,p.id); |
|
|
|
var k = p.l/2.41; |
|
var w = k * 2.41 + p.sw/2; |
|
var c = [1,1,1,1,0]; |
|
|
|
var l = d3.line() |
|
.x(function(d) { return d[0]*k; }) |
|
.y(function(d) { return d[1]*k; }) |
|
|
|
pt.attr("width", w) |
|
.attr("height", w) |
|
.attr("patternUnits","userSpaceOnUse") |
|
.attr("patternTransform","rotate("+p.a+")") |
|
.attr("id",p.id); |
|
|
|
pt.selectAll("path") |
|
.data(p.base) |
|
.enter() |
|
.append("path") |
|
|
|
pt.selectAll("path") |
|
.attr("d",l) |
|
.attr("fill",function(d,i) { return p.f[c[i]]; }) |
|
.attr("stroke", p.s) |
|
.attr("stroke-width", p.sw) |
|
.attr("opacity",p.o) |
|
|
|
return p; |
|
} |
|
p.add(); |
|
return p; |
|
} |
|
////////////////////////////////////////////////////////////////////// |
|
// Sine |
|
function ptSine(S,I) { |
|
var p = pt(S,I); |
|
|
|
p.amp = 10; |
|
p.sam = 1; |
|
p.per = 100; |
|
p.sw = 10; |
|
p.s = "steelblue"; |
|
p.f = "none"; |
|
p.sp = 4; |
|
|
|
p.amplitude = function(_) { if(!arguments.length) return p.amp; p.amp = _; return p; } |
|
p.period = function(_) { if(!arguments.length) return p.per; p.per = _; return p; } |
|
p.sampling = function(_) { if(!arguments.length) return p.sam; p.sam = _; return p; } |
|
p.spacing = function(_) { if(!arguments.length) return p.sp; p.sp = _; return p; } |
|
|
|
p.add = function() { |
|
var defs = checkDefs(p.sel); |
|
var pt = checkPattern(p.sel,defs,p.id); |
|
ptProps(pt,p.a,p.id); |
|
|
|
|
|
var points=[]; |
|
var x,y; |
|
var width = p.per; |
|
var samples = width/p.sam; |
|
|
|
for (var i =0; i < (samples+20); i++) { |
|
x= (i-10) * p.sam; |
|
y= Math.sin(i/samples*Math.PI*8) * p.amp; |
|
if(i==0) points.push("M"+x+" "+y); |
|
else points.push(" L"+x+" "+y); |
|
} |
|
|
|
var path = points.join(" "); |
|
|
|
pt.attr("width", width) |
|
.attr("height", (p.amp+p.sw/4+p.sp)*2) |
|
.attr("patternUnits","userSpaceOnUse") |
|
.attr("patternTransform","rotate("+p.a+")") |
|
.attr("stroke-width",p.sw) |
|
.attr("stroke",p.s) |
|
.attr("id",p.id) |
|
.attr("fill",p.f) |
|
|
|
var paths = pt.selectAll("path") |
|
.data([path]); |
|
|
|
paths.exit().remove(); |
|
|
|
var enter = paths.enter() |
|
.append("path"); |
|
|
|
enter.merge(paths) |
|
.attr("transform","translate(0,"+(p.amp+p.sw/4+p.sp)+")") |
|
.attr("d", path) |
|
|
|
return p; |
|
} |
|
p.add(); |
|
return p; |
|
} |
|
|
|
////////////////////////////////////////////////////////////////////// |
|
// Scheme |
|
var ptSchemeCategory10 = function(S) { |
|
var sel = S || d3.select("svg"); // attempt to select SVG by default |
|
if(sel.node() && sel.node().nodeName != "svg") console.log("no svg found"); |
|
|
|
return [ |
|
ptCircle(sel).radius(2).spacing(2).fill("black"), |
|
ptCircle(sel).radius(6).fill("none").strokeWidth(1).spacing(2), |
|
ptCircle(sel).radius(5).spacing(4).fill("black"), |
|
ptCircle(sel).radius(1).spacing(1).fill("black"), |
|
ptCircle(sel).radius(3).fill("none").strokeWidth(1).spacing(2), |
|
ptCircle(sel).radius(2).spacing(5).hex(false).fill("black"), |
|
ptCircle(sel).radius(10).spacing(1).fill("black"), |
|
ptCircle(sel).radius(10).spacing(1).fill("none").strokeWidth(2), |
|
ptCircle(sel).radius(7).spacing(4).fill("none").strokeWidth(5), |
|
ptCircle(sel).radius(6).hex(false).spacing(5).fill("black") |
|
] |
|
} |
|
|
|
////////////////////////////////////////////////////////////////////// |
|
// Scheme Generator |
|
var ptCircles = function(S) { |
|
var c = {}; |
|
c.bg = ["none"]; |
|
c.f = ["black"]; |
|
c.r = [1]; |
|
c.s = [16,8,4,2]; |
|
|
|
c.spacings = function(_) { if(!arguments.length) return c.s; c.s = arr(_); return c; } |
|
c.fills = function(_) { if(!arguments.length) return c.f; c.f = arr(_); return c; } |
|
c.radii = function(_) { if(!arguments.length) return c.r; c.r = arr(_); return c; } |
|
c.backgrounds = function(_) { if(!arguments.length) return c.bg; c.bg = arr(_); return c; } |
|
|
|
c.get = function() { |
|
console.log(c); |
|
var max = Math.max(c.s.length,c.f.length,c.r.length,c.bg.length); |
|
var a = []; |
|
|
|
for(var i = 0; i < max; i++) { |
|
var p = ptCircle(S); |
|
if (c.s) p.spacing(c.s[i%c.s.length]); |
|
if (c.f) p.fill(c.f[i%c.f.length]); |
|
if (c.r) p.radius(c.r[i%c.r.length]); |
|
if (c.bg) p.background(c.bg[i%c.bg.length]); |
|
p.add(); |
|
a.push(p); |
|
} |
|
return a; |
|
} |
|
return c; |
|
} |
|
|
|
////////////////////////////////////////////////////////////////////// |
|
// Stripes Manager |
|
var ptManager = function(S) { |
|
var m = {}; |
|
|
|
m.keys = []; |
|
m.f = d3.schemeCategory20; |
|
m.combos = []; |
|
m.comboIds = []; |
|
m.totalWidth = 12; |
|
m.a = 45; |
|
m.sel = S; |
|
|
|
m.values = function() { |
|
var values = []; |
|
m.keys.forEach(function(d,i) { |
|
values.push({key:d,color:m.f[i]}) |
|
}) |
|
return values; |
|
} |
|
|
|
m.fills = function(_) { if(!_) return m.f; m.f = _; return m; } |
|
m.width = function(_) { if(!_) return m.totalWidth; m.totalWidth = _; return m; } |
|
|
|
m.datum = function(d) { |
|
var bStriped = false; |
|
|
|
// add new keys to key array: |
|
if (Array.isArray(d)) { |
|
d.forEach(function(e) { |
|
if (m.keys.indexOf(e) < 0) m.keys.push(e); |
|
}) |
|
|
|
if (d.length > 1) bStriped = true; |
|
} |
|
else { |
|
if (m.keys.indexOf(d) < 0) m.keys.push(d); |
|
} |
|
|
|
// Return a fill - solid or stripe pattern: |
|
if (!bStriped) { |
|
if (Array.isArray(d)) return m.f[m.keys.indexOf(d[0])]; |
|
else return m.f[m.keys.indexOf(d)]; |
|
} |
|
// requires stripes: |
|
else { |
|
// ensure same order for areas with same stripes: |
|
d.sort(); |
|
|
|
// don't create duplicate patterns |
|
var existing = null; |
|
m.combos.forEach(function(c,i) { |
|
if (c.length==d.length && c.every(function(e,j) { return d[j] === e})) existing = i; |
|
}) |
|
if (existing != null) { return m.comboIds[existing]; } |
|
|
|
// create a new pattern: |
|
else { |
|
m.combos.push(d); |
|
var stripeColors = []; |
|
d.forEach(function(e) { |
|
stripeColors.push(m.f[m.keys.indexOf(e)]); |
|
}) |
|
|
|
var w = m.totalWidth / stripeColors.length; |
|
var str = ptStripe(m.sel).fill(stripeColors).angle(m.a).width(w); |
|
m.comboIds.push(str.use()); |
|
return str.use(); |
|
} |
|
} |
|
|
|
return m; |
|
} |
|
return m; |
|
} |
|
|
|
////////////////////////////////////////////////////////////////////// |
|
// Pattern Helper Functions: |
|
|
|
// width and height: |
|
function wh(e,w,h) { |
|
e.attr("width",w) |
|
e.attr("height",h) |
|
} |
|
|
|
function checkDefs(s) { |
|
var defs = s.select("defs"); |
|
if(defs.empty()) defs = s.append("defs"); |
|
|
|
return defs; |
|
} |
|
|
|
function checkPattern(s,d,id) { |
|
var pt = s.select("#"+id); |
|
if (pt.empty()) pt = d.append("pattern"); |
|
return pt; |
|
} |
|
|
|
function ptProps(p,a,id) { |
|
p.attr("patternUnits","userSpaceOnUse") |
|
.attr("patternTransform","rotate("+a+")") |
|
.attr("id", id); |
|
} |
|
|
|
|
|
// takes radius, stroke width, and spacing additional spacing to return length,width of pattern and pattern object centroids. |
|
function hxCentroids(r) { |
|
// units: |
|
var h = r*2; |
|
var w = Math.sqrt(3)/2 * h; |
|
|
|
// dimensions: |
|
var dy = h*1.5; |
|
var dx = w; |
|
|
|
return {"h":dy,"w":dx,"c":[[w/2,0],[w/2,dy],[0,h*3/4],[dx,h*3/4]]}; |
|
} |
|
// draws background for pattern (p) with fill (f) and dimensions x,y |
|
function applyBG(p,f,x,y) { |
|
var r = p.select(".ptBackground") |
|
r.remove(); |
|
r = p.append("rect"); |
|
r.attr("width", x) |
|
.attr("height",y) |
|
.attr("fill",f) |
|
.attr("x",0) |
|
.attr("y",0) |
|
.lower() |
|
.attr("class","ptBackground"); |
|
} |
|
// draws background color for canvas patterns, c is context, f is fill, and dimensions are x,y |
|
function patternApplyCanvasBackground(c,f,x,y) { |
|
c.beginPath() |
|
c.fillStyle = f; |
|
c.fillRect(0,0,x,y); |
|
} |
|
// returns a hexagon path centered at [x,y] with r |
|
function hexPath(x,y,r) { |
|
var x1 = x; |
|
var y1 = y-r; |
|
var x2 = x+(Math.cos(Math.PI/6)*r); |
|
var y2 = y-(Math.sin(Math.PI/6)*r); |
|
var x3 = x+(Math.cos(Math.PI/6)*r); |
|
var y3 = y+(Math.sin(Math.PI/6)*r); |
|
var x4 = x; |
|
var y4 = y+r; |
|
var x5 = x-(Math.cos(Math.PI/6)*r); |
|
var y5 = y+(Math.sin(Math.PI/6)*r); |
|
var x6 = x-(Math.cos(Math.PI/6)*r); |
|
var y6 = y-(Math.sin(Math.PI/6)*r); |
|
|
|
var path = "M"+x1+" "+y1+" L"+x2+" "+y2+" L"+x3+" "+y3+" L"+x4+" "+y4+" L"+x5+" "+y5+" L"+x6+" "+y6+"z"; |
|
return path; |
|
} |
|
// ensure a is an array. |
|
function arr(a) { |
|
if(Array.isArray(a)) return a; |
|
else return [a]; |
|
} |
|
|
|
// Get the next free class for a pattern: |
|
function patternGetNextClass(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; |
|
} |
|
|
|
|
|
exports.circle = ptCircle; |
|
exports.square = ptSquare; |
|
exports.hexagon = ptHexagon; |
|
exports.text = ptLetter; |
|
exports.symbol = ptSymbol; |
|
exports.wetland = ptWetland; |
|
exports.fish = ptFish; |
|
exports.fire = ptFire; |
|
exports.danger = ptDanger; |
|
exports.checker = ptChecker; |
|
exports.stripe = ptStripe; |
|
exports.plaid = ptPlaid; |
|
exports.cairo = ptCairo; |
|
exports.octagon = ptOctagon; |
|
exports.sine = ptSine; |
|
|
|
exports.circles = ptCircles; |
|
exports.stripeManager = ptManager; |
|
exports.circleSchemeCategory10 = ptSchemeCategory10; |
|
}))); |