Last active
November 23, 2020 11:58
-
-
Save henryjameslau/345113789b65f8806f0b53497d67d7dd to your computer and use it in GitHub Desktop.
A colour palette based off ONS
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
.DS_Store |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<head> | |
<meta charset="utf-8"> | |
<script src="https://d3js.org/d3.v4.min.js"></script> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.15.0/lodash.min.js"></script> | |
<script src="https://npmcdn.com/[email protected]/browser.min.js"></script> | |
<script type="text/javascript" src="https://cdn.rawgit.com/gka/chroma.js/master/chroma.min.js"></script> | |
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/[email protected]/lodash.min.js"></script> | |
<link href="https://fonts.googleapis.com/css?family=Open+Sans:400,700" rel="stylesheet"> | |
<style> | |
body { | |
font-family: 'Open Sans', sans-serif; | |
} | |
p { | |
max-width: 600px; | |
} | |
svg#sex { | |
width: 800px; | |
height: 210px; | |
} | |
svg#five { | |
width: 800px; | |
height: 210px; | |
} | |
svg#nine { | |
width: 1000px; | |
height: 160px; | |
} | |
td { | |
text-align: center; | |
} | |
table { | |
border-collapse: collapse; | |
} | |
table, | |
th, | |
td { | |
border: 1px solid black; | |
} | |
</style> | |
<link rel="stylesheet" type="text/css" href="bootstrap-grid.css"> | |
</head> | |
<body> | |
<h1>New ONS colours</h1> | |
<h2>Male/Female</h2> | |
<svg id="sex"></svg> | |
<code>["#234d70","#00a5a1"]</code> | |
<h2>5 colour palette</h2> | |
<svg id="five"></svg> | |
<code>["#053D58","#24A79B","#3A7899","#ABC149","#005D60"]</code> | |
<h2>9 colours</h2> | |
<svg id="nine"></svg> | |
<code>["#053D58","#24A79B","#3A7899","#ABC149","#005D60","#3383EF","#493C7F","#7EC8FA","#2A5FB8"]</code> | |
<h2>Sequential palette</h2> | |
<select id="seqNum"> | |
<option value=3>Three</option> | |
<option value=4>Four</option> | |
<option value=5>Five</option> | |
<option value=6>Six</option> | |
<option value=7>Seven</option> | |
</select> colours from | |
<select id="seqCol"> | |
<option value="#053D58">Midnight</option> | |
<option value="#24A79B">Aquamarine</option> | |
<option value="#3A7899">Denim</option> | |
<option value="#ABC149">Straw</option> | |
<option value="#005D60">Forest</option> | |
<option value="#3383EF">Cobalt</option> | |
<option value="#493C7F">Navy</option> | |
<option value="#7EC8FA">Sky</option> | |
<option value="#2A5FB8">Admiral</option> | |
</select> | |
<button onclick='seqPal()'>Create palette</button> | |
<div id="sequential"></div> | |
<code id="seqPalCode"></code> | |
<h2>Diverging palette</h2> | |
<select id="divNum"> | |
<option value=3>Three</option> | |
<option value=4>Four</option> | |
<option value=5>Five</option> | |
<option value=6>Six</option> | |
<option value=7>Seven</option> | |
</select> colours based on | |
<select id="divCol"> | |
<option value="#053D58">Midnight</option> | |
<option value="#24A79B">Aquamarine</option> | |
<option value="#3A7899">Denim</option> | |
<option value="#ABC149">Straw</option> | |
<option value="#005D60">Forest</option> | |
<option value="#3383EF">Cobalt</option> | |
<option value="#493C7F">Navy</option> | |
<option value="#7EC8FA">Sky</option> | |
<option value="#2A5FB8">Admiral</option> | |
</select> | |
<button onclick='divPal()'>Create palette</button> | |
<div id="divergent"></div> | |
<code id="divPalCode"></code> | |
<script> | |
var sex = ["#234d70","#00a5a1"] | |
d3.select('#sex') | |
.selectAll('circle') | |
.data(sex) | |
.enter() | |
.append('circle') | |
.attr("fill", function(d) { | |
return d | |
}) | |
.attr("cx", function(d, i) { | |
return 150 * (i + 0.5) | |
}) | |
.attr("cy", 100) | |
.attr("r", 50) | |
d3.select('#sex') | |
.selectAll('text') | |
.data(["Male","Female"]) | |
.enter() | |
.append('text') | |
.text(function(d) { | |
return d | |
}) | |
.attr("x", function(d, i) { | |
return 150 * (i + 0.5) | |
}) | |
.attr("y", 180) | |
.attr("text-anchor", "middle") | |
var colours = ["#053D58", "#24A79B", "#3A7899", "#ABC149", "#005D60", "#3383EF", "#493C7F", "#7EC8FA", "#2A5FB8"] | |
var names = ["Midnight", "Aquamarine", "Denim", "Straw", "Forest", "Cobalt", "Navy", "Sky", "Admiral"] | |
d3.select('#five') | |
.selectAll('circle') | |
.data(colours.slice(0, 5)) | |
.enter() | |
.append('circle') | |
.attr("fill", function(d) { | |
return d | |
}) | |
.attr("cx", function(d, i) { | |
return 150 * (i + 0.5) | |
}) | |
.attr("cy", 100) | |
.attr("r", 50) | |
d3.select('#five') | |
.selectAll('text') | |
.data(names.slice(0, 5)) | |
.enter() | |
.append('text') | |
.text(function(d) { | |
return d | |
}) | |
.attr("x", function(d, i) { | |
return 150 * (i + 0.5) | |
}) | |
.attr("y", 180) | |
.attr("text-anchor", "middle") | |
d3.select("#nine") | |
.selectAll('circle') | |
.data(colours) | |
.enter() | |
.append('circle') | |
.attr("fill", function(d) { | |
return d | |
}) | |
.attr("cx", function(d, i) { | |
return 85 * (i + 0.5) | |
}) | |
.attr("cy", 50) | |
.attr("r", 30) | |
d3.select('#nine') | |
.selectAll('text') | |
.data(names) | |
.enter() | |
.append('text') | |
.text(function(d) { | |
return d | |
}) | |
.attr("x", function(d, i) { | |
return 85 * (i + 0.5) | |
}) | |
.attr("y", 130) | |
.attr("text-anchor", "middle") | |
//sequential palettes | |
function seqPal() { | |
var sequential = d3.select("#sequential") | |
var seqNum = +document.getElementById('seqNum').value | |
var i = d3.interpolate(1.5, 2.2) | |
var seqColour = document.getElementById('seqCol').value | |
var seqColInd = colours[colours.indexOf(seqColour)] | |
sequential.selectAll("*").remove() | |
sequential.append('svg') | |
.attr("width", "800px") | |
.attr("height", "160px") | |
sequential.select('svg') | |
.selectAll('circle') | |
.data(chroma.scale([chroma(seqColInd), chroma(seqColInd).brighten(i((seqNum - 3) / 4))]) | |
.mode('lch') | |
.colors(seqNum)) | |
.enter() | |
.append('circle') | |
.attr("fill", function(d) { | |
return d | |
}) | |
.attr("cx", function(d, i) { | |
return 800 / seqNum * (i + 0.5) | |
}) | |
.attr("cy", 50) | |
.attr("r", 40) | |
sequential.select('svg') | |
.selectAll('text') | |
.data(chroma.scale([chroma(seqColInd), chroma(seqColInd).brighten(i((seqNum - 3) / 4))]) | |
.mode('lch') | |
.colors(seqNum)) | |
.enter() | |
.append('text') | |
.text(function(d) { | |
return d | |
}) | |
.attr("x", function(d, i) { | |
return 800 / seqNum * (i + 0.5) | |
}) | |
.attr("y", 130) | |
.attr("text-anchor", "middle") | |
d3.select("#seqPalCode").text("[" + chroma.scale([chroma(seqColInd), chroma(seqColInd).brighten(i((seqNum - 3) / 4))]) | |
.mode('lch') | |
.colors(seqNum) + | |
"]") | |
} //end seqPal function | |
function divPal() { | |
var divergent = d3.select("#divergent") | |
var divNum = +document.getElementById('divNum').value | |
var divColour = document.getElementById('divCol').value | |
divergent.selectAll("*").remove() | |
divergent.append('svg') | |
.attr("width", "800px") | |
.attr("height", "160px") | |
divergent.select('svg') | |
.selectAll('circle') | |
.data(chroma.scale([chroma(divColour), "#ccc", chroma(divColour).set('hsl.h', chroma(divColour).get('hsl.h') - 180)]) | |
.mode('lch') | |
.colors(divNum)) | |
.enter() | |
.append('circle') | |
.attr("fill", function(d) { | |
return d | |
}) | |
.attr("cx", function(d, i) { | |
return 800 / divNum * (i + 0.5) | |
}) | |
.attr("cy", 50) | |
.attr("r", 40) | |
d3.select("#divPalCode").text("[" | |
+ chroma.scale([chroma(divColour), "#ccc", chroma(divColour).set('hsl.h', chroma(divColour).get('hsl.h') - 180)]) | |
.mode('lch') | |
.colors(divNum) + | |
"]") | |
} //end divPal function | |
</script> | |
</body> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<head> | |
<meta charset="utf-8"> | |
<script src="https://d3js.org/d3.v4.min.js"></script> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.15.0/lodash.min.js"></script> | |
<script src="https://npmcdn.com/[email protected]/browser.min.js"></script> | |
<script type="text/javascript" src="https://cdn.rawgit.com/gka/chroma.js/master/chroma.min.js"></script> | |
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/[email protected]/lodash.min.js"></script> | |
<link href="https://fonts.googleapis.com/css?family=Open+Sans:400,700" rel="stylesheet"> | |
<style> | |
body{ | |
font-family: 'Open Sans', sans-serif; | |
} | |
p{ | |
max-width: 600px; | |
} | |
svg#matisse { | |
width: 800px; | |
height: 620px; | |
} | |
svg#categorical { | |
width: 1000px; | |
height: 820px; | |
} | |
svg#sequential{ | |
width: 800px; | |
height: 600px; | |
} | |
svg#divergent{ | |
width: 1000px; | |
height: 750px; | |
} | |
td{ | |
text-align:center; | |
} | |
table { | |
border-collapse: collapse; | |
} | |
table, th, td { | |
border: 1px solid black; | |
} | |
</style> | |
<link rel="stylesheet" type="text/css" href="bootstrap-grid.css"> | |
</head> | |
<body> | |
<h1>Instructions and colours to use in charts</h1> | |
<h2>Single hue categorical palette</h2> | |
<p>2-5 colours in a single hue with a hue twist for bars for categorical data. The order of the colours are a certain order to maximise the distance between colours.</p> | |
<div style="width:100%"> | |
<button type="button" value="#206095" onclick="palette1(this.value)">matisse</button> | |
<button type="button" value="#0F8243" onclick="palette1(this.value)">salem</button> | |
<button type="button" value="#6E2585" onclick="palette1(this.value)">prince</button> | |
<button type="button" value="#D32F2F" onclick="palette1(this.value)">poppy</button> | |
<button type="button" value="#B8860B" onclick="palette1(this.value)">gold</button> | |
<button type="button" value="#008080" onclick="palette1(this.value)">teal</button> | |
<button type="button" value="#FF9933" onclick="palette1(this.value)">orange</button> | |
</div> | |
<svg id="matisse"></svg> | |
<table> | |
<tbody> | |
<tr> | |
<td >Number of classes</td> | |
<td >Large areas (e.g. bar chart)</td> | |
<td >Small areas (lines and dots) </td> | |
</tr> | |
<tr> | |
<td >2</td> | |
<td >👍</td> | |
<td >👍</td> | |
</tr> | |
<tr> | |
<td >3</td> | |
<td >👍</td> | |
<td >👍</td> | |
</tr> | |
<tr> | |
<td >4</td> | |
<td >👍</td> | |
<td >❌</td> | |
</tr> | |
<tr> | |
<td >5</td> | |
<td >👍</td> | |
<td >❌</td> | |
</tr> | |
</tbody> | |
</table> | |
<h2>Multihued colours categorical palette</h2> | |
<p>Categorical colours chosen with <a href="http://vrl.cs.brown.edu/color">colorgorical</a>. Starting colours are based around blue where the eye has greatest acuity in determining different colours. </p> | |
<p>The first three colours are similar in lightness and saturation to try to make them even in attention, but there is a slight difference in lightness to help with colour-blindness and printing in black and white.</p> | |
<p>The next three colours are light, dark, light as we are forced to widen the range of lightness to get perceivable colour differences. These colours can be used as highlight colours when used with the first three. Avoid using light colours for charts with small areas such as lines and dots as the constrast is not strong enough to stand out against white backgrounds.</p> | |
<p>The last two colours are very saturated to achieve colour differences. </p> | |
<svg id="categorical"></svg> | |
<table> | |
<tbody> | |
<tr> | |
<td>Number of classes</td> | |
<td>Blocks</td> | |
<td>Lines</td> | |
<td>Dots</td> | |
<td>Colourblind safe</td> | |
</tr> | |
<tr> | |
<td>2</td> | |
<td>👍</td> | |
<td>👍</td> | |
<td>👍</td> | |
<td>👍</td> | |
</tr> | |
<tr> | |
<td>3</td> | |
<td>👍</td> | |
<td>👍</td> | |
<td>👍</td> | |
<td>👍</td> | |
</tr> | |
<tr> | |
<td>4</td> | |
<td>👍</td> | |
<td>👍</td> | |
<td>👍</td> | |
<td>👍</td> | |
</tr> | |
<tr> | |
<td>5</td> | |
<td>👍</td> | |
<td>👍</td> | |
<td>❌</td> | |
<td>👍</td> | |
</tr> | |
<tr> | |
<td>6</td> | |
<td>👍</td> | |
<td>❌</td> | |
<td>❌</td> | |
<td>❌</td> | |
</tr> | |
<tr> | |
<td>7</td> | |
<td>👍</td> | |
<td>❌</td> | |
<td>❌</td> | |
<td>❌</td> | |
</tr> | |
<tr> | |
<td>8</td> | |
<td>👍</td> | |
<td>❌</td> | |
<td>❌</td> | |
<td>❌</td> | |
</tr> | |
</tbody> | |
</table> | |
<h2>Sequential palettes</h2> | |
<p>Sequential palettes are based around a certain hue with a slight hue twist to help with contrast. The ends are made lighter/darker as the number of classes increases to make enough differences betweens colours.</p> | |
<div> | |
<button type="button" value="#206095" onclick="palette2(this.value)">matisse</button> | |
<button type="button" value="#0F8243" onclick="palette2(this.value)">salem</button> | |
<button type="button" value="#D32F2F" onclick="palette2(this.value)">poppy</button> | |
<button type="button" value="#6E2585" onclick="palette2(this.value)">prince</button> | |
</div> | |
<svg id="sequential"></svg> | |
<h2>Diverging palette</h2> | |
<p>Two sequential palettes stuck back to back with a middle colour for odd number of classes. Again the ends are made darker as the number of classes increases to ensure enough colour differences between individual colours.</p> | |
<div style="width:100%"> | |
<button type="button" value="#206095,#0F8243" onclick="palette3(this.value)">matisse-salem</button> | |
<button type="button" value="#B8860B,#0F8243" onclick="palette3(this.value)">gold-salem</button> | |
<button type="button" value="#B8860B,#008080" onclick="palette3(this.value)">gold-teal</button> | |
<button type="button" value="#206095,#D32F2F" onclick="palette3(this.value)">matisse-poppy</button> | |
<button type="button" value="#008080,#D32F2F" onclick="palette3(this.value)">teal-poppy</button> | |
<button type="button" value="#008080,#FF9933" onclick="palette3(this.value)">orange-teal</button> | |
</div> | |
<!-- Start colour | |
<input type="radio" name="start" value="#206095">matisse<br> | |
<input type="radio" name="start" value="#B8860B">salem</button> | |
</div> | |
<div style="width:100%"> | |
Mid colour | |
<input type="radio" name="mid" value="#f7f7f7">grey<br> | |
<input type="radio" name="mid" value="#ffffbf">cream</button> | |
</div> | |
<div style="width:100%"> | |
End colour | |
<input type="radio" name="end" value="#008080">teal</button> | |
<input type="radio" name="end" value="#0F8243">salem</button> | |
</div> | |
<div> | |
<button type="button" onclick="palette3()">Generate</button> | |
</div> --> | |
<svg id="divergent"></svg> | |
<script> | |
function palette1(value){ | |
var matisse={} | |
var startcolour=value | |
var helix=chroma.cubehelix() | |
.start(Math.round(chroma(startcolour).get('hcl.h'))) | |
.rotations(-0.25) | |
.lightness([0.4,0.8]) | |
.scale() | |
.correctLightness() | |
.colors(2); | |
var endcolour=helix.slice(1)[0] | |
matisse["5"]=maxColourDistance(permutator(chroma.scale([chroma(startcolour).darken().hex(),endcolour]).correctLightness().colors(5))) | |
matisse["4"]=maxColourDistance(permutator(chroma.scale([startcolour,endcolour]).correctLightness().colors(4))) | |
matisse["3"]=maxColourDistance(permutator(chroma.scale([chroma(startcolour).brighten(0.5),endcolour]).correctLightness().colors(3))) | |
matisse["2"]=chroma.scale([chroma(startcolour).brighten(0.5),endcolour]).correctLightness().colors(3) | |
matisse["2"].pop() | |
matisse["2"].reverse() | |
var svg = d3.select('#matisse'); | |
svg.selectAll("*").remove() | |
var size = 150; | |
var keys = Object.keys(matisse) | |
for(i=0;i<keys.length;i++){ | |
for(j=0;j<matisse[keys[i]].length;j++){ | |
svg.append("circle").attr("fill",matisse[keys[i]][j]) | |
.attr("cx",size*(j+0.5)) | |
.attr("cy",size*(i+0.5)) | |
.attr("r",size/3) | |
svg.append("text").text(matisse[keys[i]][j]) | |
.attr("x",size*(j+0.5)) | |
.attr("y",size*(i+0.5)+size/2) | |
.attr("text-anchor","middle") | |
} | |
} | |
} | |
// start of categorical colours | |
var categorical={} | |
var size2=100; | |
// categorical["2"]=["#3e76ad","#339a59"] | |
// categorical["3"]=["#3e76ad","#339a59","#74abc5"] | |
// categorical["4"]=["#3e76ad","#339a59","#74abc5","#e2bc22"] | |
// categorical["5"]=["#3e76ad","#339a59","#74abc5","#e2bc22","#601552"] | |
// categorical["6"]=["#3e76ad","#339a59","#74abc5","#e2bc22","#601552","#dc98ff"] | |
// categorical["7"]=["#3e76ad","#339a59","#74abc5","#e2bc22","#601552","#dc98ff","#ed4b04"] | |
// categorical["8"]=["#3e76ad","#339a59","#74abc5","#e2bc22","#601552","#dc98ff","#ed4b04","#6c41cb"] | |
// palette = ["#1E5C92", "#CD842F", "#5B0F44", "#039E82", "#B1295E","#5999D1", "#3A1E82","#BE3E24","#1E4943"] | |
palette =["#055477" | |
, "#1FA494" | |
, "#023446" | |
, "#9FB34A" | |
, "#1289B4" | |
, "#4A356E" | |
, "#157E64" | |
, "#7EC8FA" | |
, "#5D48C1"] | |
categorical["2"]=findBestCombination(choosePermutations(palette,2)) | |
categorical["3"]=findBestCombination(choosePermutations(palette,3)) | |
categorical["4"]=findBestCombination(choosePermutations(palette,4)) | |
categorical["5"]=findBestCombination(choosePermutations(palette,5)) | |
categorical["6"]=findBestCombination(choosePermutations(palette,6)) | |
categorical["7"]=findBestCombination(choosePermutations(palette,7)) | |
categorical["8"]=findBestCombination(choosePermutations(palette,8)) | |
categorical["9"]=findBestCombination(choosePermutations(palette,9)) | |
var svg2 = d3.select('#categorical'); | |
var keys2 = Object.keys(categorical) | |
for(i=0;i<keys2.length;i++){ | |
for(j=0;j<categorical[keys2[i]].length;j++){ | |
svg2.append("circle").attr("fill",categorical[keys2[i]][j]) | |
.attr("cx",size2*(j+0.5)) | |
.attr("cy",size2*(i+0.5)) | |
.attr("r",size2/3) | |
svg2.append("text").text(categorical[keys2[i]][j]) | |
.attr("x",size2*(j+0.5)) | |
.attr("y",size2*(i+0.5)+size2/2) | |
.attr("text-anchor","middle") | |
} | |
} | |
//Sequential | |
function palette2(value){ | |
var sequential={} | |
var size3=80; | |
var startSeqentialColour=value | |
var helix2=chroma.cubehelix() | |
.start(Math.round(chroma(startSeqentialColour).get('hcl.h'))) | |
.rotations(-0.1) | |
.lightness([0.4,0.8]) | |
.scale() // convert to chroma.scale | |
.correctLightness() | |
.colors(2); | |
var endcolour2=helix2.slice(1)[0] | |
sequential["3"]=chroma.scale([chroma(startSeqentialColour).brighten(),chroma(endcolour2)]).correctLightness().colors(3) | |
sequential["4"]=chroma.scale([chroma(startSeqentialColour),chroma(endcolour2).brighten(0.5)]).correctLightness().colors(4) | |
sequential["5"]=chroma.scale([chroma(startSeqentialColour).darken(0.5),chroma(endcolour2).brighten(0.5)]).correctLightness().colors(5) | |
sequential["6"]=chroma.scale([chroma(startSeqentialColour).darken(0.5),chroma(endcolour2).brighten(0.5)]).correctLightness().colors(6) | |
sequential["7"]=chroma.scale([chroma(startSeqentialColour).darken(),chroma(endcolour2).brighten(0.5)]).correctLightness().colors(7) | |
sequential["8"]=chroma.scale([chroma(startSeqentialColour).darken(),chroma(endcolour2).brighten(1)]).correctLightness().colors(8) | |
sequential["9"]=chroma.scale([chroma(startSeqentialColour).darken(1.5),chroma(endcolour2).brighten(1)]).correctLightness().colors(9) | |
var svg3 = d3.select('#sequential'); | |
svg3.selectAll("*").remove() | |
var keys3 = Object.keys(sequential) | |
for(i=0;i<keys3.length;i++){ | |
for(j=0;j<sequential[keys3[i]].length;j++){ | |
svg3.append("circle").attr("fill",sequential[keys3[i]][j]) | |
.attr("cx",size3*(j+0.5)) | |
.attr("cy",size3*(i+0.5)) | |
.attr("r",size3/3) | |
svg3.append("text").text(sequential[keys3[i]][j]) | |
.attr("x",size3*(j+0.5)) | |
.attr("y",size3*(i+0.5)+size3/2) | |
.attr("text-anchor","middle") | |
} | |
} | |
} | |
function palette3(value){ | |
//divergent palettes | |
var divergent={} | |
var size4=80; | |
var startDivergentColour=value.split(",")[0] | |
var midDivergentColour="#f7f7f7"; | |
var endDivergentColour=value.split(",")[1] | |
divergent["3"]=[chroma(startDivergentColour).brighten(),midDivergentColour,chroma(endDivergentColour).brighten()] | |
var divergent4part1 = chroma.scale([startDivergentColour,midDivergentColour]).correctLightness().colors(3) | |
var divergent4part2 = chroma.scale([midDivergentColour,endDivergentColour]).correctLightness().colors(3) | |
divergent4part1.pop() | |
divergent4part2.shift() | |
divergent["4"]=divergent4part1.concat(divergent4part2) | |
divergent["5"]=divergent4part1.concat(chroma.scale([midDivergentColour,endDivergentColour]).correctLightness().colors(3)) | |
var divergent6part1 = chroma.scale([chroma(startDivergentColour).darken(0.5),midDivergentColour]).correctLightness().colors(4) | |
var divergent6part2 = chroma.scale([midDivergentColour,chroma(endDivergentColour).darken(0.5)]).correctLightness().colors(4) | |
divergent6part1.pop() | |
divergent6part2.shift() | |
divergent["6"]=divergent6part1.concat(divergent6part2) | |
divergent["7"]=divergent6part1.concat(chroma.scale([midDivergentColour,chroma(endDivergentColour).darken(0.5)]).correctLightness().colors(4)) | |
var divergent8part1 = chroma.scale([chroma(startDivergentColour).darken(0.5),midDivergentColour]).correctLightness().colors(5) | |
var divergent8part2 = chroma.scale([midDivergentColour,chroma(endDivergentColour).darken(0.5)]).correctLightness().colors(5) | |
divergent8part1.pop() | |
divergent8part2.shift() | |
divergent["8"]=divergent8part1.concat(divergent8part2) | |
divergent["9"]=divergent8part1.concat(chroma.scale([midDivergentColour,chroma(endDivergentColour).darken(0.5)]).correctLightness().colors(5)) | |
var divergent10part1 = chroma.scale([chroma(startDivergentColour).darken(1),midDivergentColour]).correctLightness().colors(6) | |
var divergent10part2 = chroma.scale([midDivergentColour,chroma(endDivergentColour).darken(1)]).correctLightness().colors(6) | |
divergent10part1.pop() | |
divergent10part2.shift() | |
divergent["10"]=divergent10part1.concat(divergent10part2) | |
divergent["11"]=divergent10part1.concat(chroma.scale([midDivergentColour,chroma(endDivergentColour).darken(1)]).correctLightness().colors(6)) | |
var svg4 = d3.select('#divergent'); | |
svg4.selectAll("*").remove(); | |
var keys4 = Object.keys(divergent) | |
for(i=0;i<keys4.length;i++){ | |
for(j=0;j<divergent[keys4[i]].length;j++){ | |
svg4.append("circle").attr("fill",divergent[keys4[i]][j]) | |
.attr("cx",size4*(j+0.5)) | |
.attr("cy",size4*(i+0.5)) | |
.attr("r",size4/3) | |
svg4.append("text").text(divergent[keys4[i]][j]) | |
.attr("x",size4*(j+0.5)) | |
.attr("y",size4*(keys4[i]-2.5)+size4/2) | |
.attr("text-anchor","middle") | |
} | |
} | |
} | |
function choosePermutations(array,choice){ | |
//function that takes an array of colours and a number of colours selected and returns the combination of colours that give the biggest difference. | |
if (choice === 1) { | |
return array.map(array => [array]); | |
} | |
// Init combinations array. | |
var combos = []; | |
// Extract characters one by one and concatenate them to combinations of smaller lengths. | |
// We need to extract them because we don't want to have repetitions after concatenation. | |
array.forEach(function(currentOption, optionIndex){ | |
// Generate combinations of smaller size. | |
var smallerCombos = choosePermutations( | |
array.slice(optionIndex + 1), | |
choice - 1, | |
); | |
// Concatenate currentOption with all combinations of smaller size. | |
smallerCombos.forEach((smallerCombo) => { | |
combos.push([currentOption].concat(smallerCombo)); | |
}); | |
}); | |
return combos; | |
} | |
// var test = choosePermutations(['#7b3294','#c2a5cf','#f7f7f7','#a6dba0','#008837'],3) | |
// console.log(findBestCombination(test)) | |
function findBestCombination(array){ | |
results = array.map(function(d){ | |
var maxArray = maxColourDistance(permutator(d)) | |
var colourDistance = [] | |
for(var i = 1; i<maxArray.length;i++){ colourDistance.push(chroma.deltaE(maxArray[i],maxArray[i-1]))} | |
return {colours:maxArray,colourDistance:colourDistance.reduce(function(a,b){return a+b},0)}; | |
}) | |
results.sort(function(a,b){return b.colourDistance-a.colourDistance}) | |
var bestCombo=results.shift(); | |
return(bestCombo.colours) | |
} | |
function permutator(inputArr) { | |
//from https://stackoverflow.com/questions/9960908/permutations-in-javascript | |
var results = []; | |
function permute(arr, memo) { | |
var cur, memo = memo || []; | |
for (var i = 0; i < arr.length; i++) { | |
cur = arr.splice(i, 1); | |
if (arr.length === 0) { | |
results.push(memo.concat(cur)); | |
} | |
permute(arr.slice(), memo.concat(cur)); | |
arr.splice(i, 0, cur[0]); | |
} | |
return results; | |
} | |
return permute(inputArr); | |
} | |
function maxColourDistance(arr){ | |
maxArray=[] | |
alldistances={} | |
sumdistances={} | |
for(i=0;i<arr.length;i++){ | |
alldistances[i]=[] | |
for(j=0;j<arr[i].length-1;j++){ | |
alldistances[i].push(chroma.deltaE(arr[i][j],arr[i][j+1])) | |
} | |
sumdistances[i]=alldistances[i].reduce(function(a,b){return a+b},0) | |
maxArray.push({"index":i,"distance":sumdistances[i]}) | |
} | |
maxArray.sort(function(a,b){ | |
var x = a.distance; var y = b.distance; | |
return ((x < y) ? -1 : ((x > y) ? 1 : 0)); | |
}) | |
maxDistance=maxArray.pop() | |
return arr[maxDistance.index] | |
} | |
</script> | |
</body> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<head> | |
<meta charset="utf-8"> | |
<script src="https://d3js.org/d3.v4.min.js"></script> | |
<script type="text/javascript" src="https://cdn.rawgit.com/gka/chroma.js/master/chroma.min.js"></script> | |
<link href="https://fonts.googleapis.com/css?family=Open+Sans:400,700" rel="stylesheet"> | |
<style> | |
</style> | |
</head> | |
<body> | |
<div id="sequential"></div> | |
<button>Download all as json</button> | |
<div id="bivariate"></div> | |
<script> | |
chart_width=400 | |
var OceanBlue = "#206095" | |
var SkyBlue = "#27a0cc" | |
var NightBlue = "#003c57" | |
var EmeraldGreen = "118C7B" | |
var SpringGreen = "a8bd3a" | |
var BeetrootPurple = "#871a5b" | |
var CoralPink = "#f66068" | |
var LavenderPurple = "#746cb1" | |
var MintGreen = "#22d0b6" | |
var RubyRed = "#D0021B" | |
var JaffaOrange = "#FE781F" | |
var SunYellow = "#FBC900" | |
var colorbrewer = ["#ffffd9","#ffffcc","#edf8b1","#c7e9b4","#a1dab4","#7fcdbb","#41b6c4","#1d91c0","#2c7fb8","#225ea8","#253494","#0c2c84","#081d58"] | |
ONSYlGnBu = chroma.scale([SpringGreen, EmeraldGreen,SkyBlue,OceanBlue]).mode('lab').colors(13) | |
//['#a8bd3a', '#82b14a', '#5da55b', '#37986b', '#118c7b', '#158182', '#197688', '#1c6b8f', '#206095', '#185786', '#104e76', '#084567', '#003c57'] | |
ONSblues = chroma.scale([SkyBlue,OceanBlue,NightBlue]).mode('lab').colors(13) | |
//['#27a0cc', '#2397c2', '#208eb7', '#1c85ad', '#197da3', '#157499', '#126c8f', '#0e6486', '#0b5b7c', '#075373', '#044b69', '#024460', '#003c57'] | |
ONSBuGn = chroma.scale([SkyBlue,EmeraldGreen]).mode('lab').colors(13) | |
//['#206095', '#226493', '#236791', '#236b8f', '#246f8d', '#23728b', '#237688', '#227a86', '#207d84', '#1e8182', '#1b8580', '#17887d', '#118c7b'] | |
ONSBuPu = chroma.scale([SkyBlue,LavenderPurple]).mode('lab').colors(13) | |
//['#206095', '#2b6197', '#34629a', '#3c639c', '#43649e', '#4a65a1', '#5166a3', '#5767a5', '#5d68a8', '#6369aa', '#696aac', '#6e6baf', '#746cb1'] | |
ONSGnBu = chroma.scale([MintGreen,OceanBlue]).mode('lab').colors(13) | |
//['#118c7b', '#17887d', '#1b8580', '#1e8182', '#207d84', '#227a86', '#237688', '#23728b', '#246f8d', '#236b8f', '#236791', '#226493', '#206095'] | |
ONSOrRd = chroma.scale([JaffaOrange,RubyRed]).mode('lab').colors(13) | |
//['#fe781f', '#fa711f', '#f76a1f', '#f3631e', '#ef5c1e', '#eb551e', '#e74d1d', '#e4451d', '#e03c1d', '#dc331c', '#d8281c', '#d41a1b', '#d0021b'] | |
ONSRdPu = chroma.scale([RubyRed,LavenderPurple]).mode('lab').colors(13) | |
//['#d0021b', '#cc1c28', '#c82a35', '#c33541', '#be3d4d', '#b84559', '#b24b65', '#ab5272', '#a3577e', '#9a5d8b', '#8f6297', '#8367a4', '#746cb1'] | |
ONSYlGn = chroma.scale([SunYellow,EmeraldGreen]).mode('lab').colors(13) | |
//['#fbc900', '#edc421', '#debf30', '#d0ba3c', '#c1b546', '#b2b04e', '#a2ab56', '#92a65d', '#81a164', '#6e9c6a', '#5a9670', '#409176', '#118c7b'] | |
ONSYlOrBr = chroma.scale([SunYellow, JaffaOrange,BeetrootPurple]).mode('lab').colors(13) | |
//['#fbc900', '#fbb711', '#f8a61e', '#f29628', '#eb8630', '#e17737', '#d7693e', '#cc5b43', '#c04e48', '#b3414d', '#a53452', '#962757', '#871a5b'] | |
ONSYlOrRd = chroma.scale([SunYellow,JaffaOrange,RubyRed]).mode('lab').colors(13) | |
//['#fbc900', '#fcbb0a', '#fcad11', '#fb9f16', '#f99218', '#f6841a', '#f2761c', '#ee681c', '#e9591d', '#e44a1d', '#dd3a1c', '#d7261c', '#d0021b'] | |
var CbL = colorbrewer.map(function(d){return chroma(d).get('hcl.l')}) | |
palettes = [ONSYlGnBu,ONSblues,ONSBuGn,ONSBuPu, ONSGnBu, ONSOrRd, ONSRdPu, ONSYlGn, ONSYlOrBr, ONSYlOrRd] | |
paletteNames = ["ONSYlGnBu","ONSblues","ONSBuGn","ONSBuPu", "ONSGnBu", "ONSOrRd", "ONSRdPu", "ONSYlGn", "ONSYlOrBr", "ONSYlOrRd"] | |
ONSpalettes={} | |
palettes.forEach((item, i) => { | |
lighted=changeLightness(item) | |
ONSpalettes[paletteNames[i]]={} | |
thispalettes = generateSeqBreaks(lighted) | |
thispalettes.forEach((d, j) => { | |
generateSeq(d) | |
console.log( | |
'"'+d.join('","')+'"' | |
) | |
console.log(d.join(",")) | |
ONSpalettes[paletteNames[i]][d.length]=d | |
}); | |
}); | |
d3.select('button').on('click',function(){download(JSON.stringify(ONSpalettes), 'ONSpalettes.json', 'text/plain'); | |
}) | |
function download(content, fileName, contentType) { | |
var a = document.createElement("a"); | |
var file = new Blob([content], {type: contentType}); | |
a.href = URL.createObjectURL(file); | |
a.download = fileName; | |
a.click(); | |
} | |
function changeLightness(colours){ | |
return colours.map(function(d,i){ | |
return chroma(d).set('hcl.l',CbL[0]-(CbL[0]-CbL[CbL.length-1])/CbL.length*(i)).hex() | |
}) | |
} | |
function generateSeqBreaks(array){ | |
var threeCols = [array[2],array[5],array[8]] | |
var fourCols = [array[1],array[4],array[6],array[9]] | |
var fiveCols = [array[1],array[4],array[6],array[8],array[10]] | |
var sixCols = [array[1],array[3],array[5],array[6],array[8],array[10]] | |
var sevenCols = [array[1],array[3],array[5],array[6],array[7],array[9],array[11]] | |
var eightCols = [array[0],array[2],array[3],array[5],array[6],array[7],array[9],array[11]] | |
var nineCols = [array[0],array[2],array[3],array[5],array[6],array[7],array[9],array[10],array[12]] | |
return [threeCols,fourCols,fiveCols,sixCols,sevenCols,eightCols,nineCols] | |
} | |
function generateSeq(colours){ | |
sequential=d3.select('#sequential') | |
.append('svg') | |
.attr('height',50) | |
.attr('width',chart_width) | |
sequential.selectAll('rect') | |
.data(colours) | |
.enter().append('rect') | |
.attr('x',function(d,i){return i*chart_width/colours.length}) | |
.attr('y',function(d,i){return 0}) | |
.attr('width',chart_width/colours.length) | |
.attr('height',50) | |
.attr('fill',function(d){return d}) | |
} | |
//bivariate | |
colour1="#206095", | |
colour2="#F66068" | |
bivariate=[] | |
bivariate.push(colour1) | |
bivariate.push(chroma.blend(colour1, colour2, 'multiply').hex()) | |
bivariate.push(chroma.blend(colour1, colour2, 'screen').hex()) | |
bivariate.push(colour2) | |
square=d3.select('#bivariate') | |
.append('svg') | |
.attr('height',chart_width) | |
.attr('width',chart_width) | |
square.selectAll('rect') | |
.data(bivariate) | |
.enter().append('rect') | |
.attr('x',function(d,i){return (i%2)*chart_width/2}) | |
.attr('y',function(d,i){return Math.floor(i/2)*chart_width/2}) | |
.attr('width',chart_width/2) | |
.attr('height',chart_width/2) | |
.attr('fill',function(d){return d}) | |
</script> | |
</body> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment