Public
Edited
Jul 21, 2023
2 forks
3 stars
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
colorMatrix = {
const svg = d3.create('svg').attr("viewBox", [0, 0, layout.width, layout.height]);
const g = svg.append('g').attr('id', 'global-group')
.attr('transform', `translate(${layout.margin.left},${layout.margin.top})`);;
const frames = g.selectAll('g')
.data(colorArray_Categorical_bySource)
.join('g')
.attr('data-color-type',d=>d[0])
.attr('transform',(d,n) => {
let position = getPosition(n, layout.horizontalNumber)
return `translate(${position[0]*(layout.frameWidth + layout.gutter)},${position[1]*(frameHeight + layout.gutter)})`
})
if(withFrame){
frames.append('rect')
.attr('width',layout.frameWidth)
.attr("height", frameHeight)
.attr("fill", "none")
.attr("stroke", "#E9E9E9")
}



frames.append('text')
.attr('transform',`translate(${layout.frameWidth/2},${-16})`)
.text(d=>d[0])
.style("font", "12px sans-serif")
.style("font-weight", '500')
.style("text-anchor","middle")

let centeredg = frames.append('g').attr('class','plot-g')
.attr('transform', `translate(${radius},${radius})`)
let plotg = centeredg.append('g').attr('class','color-plot-g')
let colorDots = plotg.selectAll('circle')
.data(d=>d[1].slice(0, firstN))
.join('circle')
.attr("r", 5)
.attr("fill", d => d['Hex'])
.attr('cx', d => {
if(RValue=='chroma'){
return scaleChromaR(chroma_okhcl(d['Hex'])[RValue])
}else if(RValue=='lightness'){
return scaleLightnessR(chroma_okhcl(d['Hex'])[RValue])
}
})
.attr('transform', d => {
return `rotate(${scaleHueY(chroma_okhcl(d['Hex'])['hue'])})`
})
centeredg.call(rAxis);
centeredg.call(xAxis);

return svg.node()
}
Insert cell
radius = layout.frameWidth/2
Insert cell
frameHeight = (layout.innerHeight+layout.gutter)/(getPosition(colorArray_Categorical_bySource.length, layout.horizontalNumber)[1] + 1)-layout.gutter
Insert cell
getPosition(colorArray_Categorical_bySource.length, layout.horizontalNumber)
Insert cell
function getPosition(n, horizontalNumber) {
n = n
return [Math.round(n%horizontalNumber), parseInt(n/horizontalNumber)]
}
Insert cell
getPosition(1,10)
Insert cell
Insert cell
Insert cell
scaleHueY = d3.scaleLinear()
.domain([0, 360])
.range([-90, 270])
Insert cell
scaleLightnessR = d3.scaleLinear()
.domain([0, 1])
.range([innerRadius, layout.frameWidth/2])
Insert cell
scaleChromaR = d3.scaleLinear()
.domain([0, 0.3])
.range([innerRadius, layout.frameWidth/2])
Insert cell
Insert cell
YtickArray = {
let interpolator = d3.interpolate(scaleHueY.range()[0],scaleHueY.range()[1])
let array = d3.quantize(interpolator, 13)
array.shift()
return array
}
Insert cell
rAxis = function(node) {
node.append('g')
.attr('class','r-axis')
.call(g=>{
g.selectAll('g')
.data(YtickArray)
.join('g')
.attr('transform', d => {
return `rotate(${scaleHueY(d)})`
})
.append('line')
.attr('x1', radius+10)
.attr('x2', d=>{
if(RValue=='chroma'){
return scaleChromaR(0)-5
}else if(RValue=='lightness'){
return scaleLightnessR(0)-5
}
})
.attr("fill", "none")
.attr("stroke", "#aaa")
.attr("stroke-width", 0.5)
.attr("stroke-dasharray", "2")
})
}
Insert cell
xAxis = function(node) {
node.append('g')
.attr('class','x-axis')
.call(g=>{
g.selectAll('g')
.data(scaleLightnessR.ticks(5))
.join('g')
.append('circle')
.attr('r', d=>scaleLightnessR(d))
.attr("fill", "none")
.attr("stroke", "#aaa")
.attr('opacity', (d,n)=> !n?0:1)
.attr("stroke-width", 0.5)
.attr("stroke-dasharray", "2")
})
.call(g=>{
g.append('circle')
.attr('r', radius)
.attr("fill", "none")
.attr("stroke", "black")
.attr("stroke-width", 0.5)
})
.call(g=>{
g.append('circle')
.attr('r', d=>{
if(RValue=='chroma'){
return scaleChromaR(0)
}else if(RValue=='lightness'){
return scaleLightnessR(0)
}
})
.attr("fill", "none")
.attr("stroke", "#999")
.attr("stroke", "rgba(0,0,0,.5)")//内圈边界
.attr("stroke-width", 0.5)
})
}
Insert cell
Insert cell
layout = ({
width: width,
height: height,
margin: {
top: 50,
bottom: 10,
left: 10,
right: 10,
},
get innerWidth(){
return this.width - this.margin.left - this.margin.right
},
get innerHeight(){
return this.height - this.margin.top - this.margin.bottom
},
gutter: gutter,
horizontalNumber: 5,
get frameWidth(){
return (this.width - this.margin.left - this.margin.right + this.gutter)/this.horizontalNumber - this.gutter
}
})
Insert cell
Insert cell
colorData_Categorical = colorData.filter(d => d['Type'] == 'Categorical')
Insert cell
colorMap_Categorical_bySource = d3.group(colorData_Categorical, d => d['Source'])
Insert cell
colorArray_Categorical_bySource = Array.from(colorMap_Categorical_bySource).sort((a,b)=>{
if(a[0].startsWith('Uni')){
return -1
}else{
return 1
}
})
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
function chroma_okhcl(hex) {
return {
lightness: chroma(hex).oklch()[0],
chroma: chroma(hex).oklch()[1],
hue:chroma(hex).oklch()[2]
}
}
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more