Public
Edited
Sep 4, 2024
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
chartMatrix = {
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 colorSourceGroups= g.selectAll('.color-by-source-group')
.data(colorArray_Scale_bySource_bySerise)
.join('g')
.attr('class','color-by-source-group')
.attr('transform', (d,i)=>{
// 这里比较复杂,用于计算色彩系列分组的高度,用到了 lengthMirrorArray 数组
let verticalNum = 0
for (let index = 0; index < i; ++index) {
verticalNum += Math.ceil(lengthMirrorArray[index]/horizontalNumber)
}

let height = verticalNum * (frameHeight + groupGutter) + verticalNum * innerGutter
return `translate(0,${height})`
})

const colorSeriseGroups = colorSourceGroups.selectAll('.color-by-serise-group')
.data(d=>d[1])
.join('g')
.attr('class','color-by-serise-group')
.attr('transform', (d,i)=>{
let x = Math.ceil(i%horizontalNumber)*(layout.frameWidth+innerGutter),
y = Math.floor(i/horizontalNumber)*(frameHeight+innerGutter)
return `translate(${x},${y})`
})
.call(g=>{
//frame setting
g.append('rect')
.attr('class', 'frame')
.attr('fill', 'none')
.attr('stroke', 'rgba(0,0,0,.5)')
.attr('width',layout.frameWidth)
.attr('height',frameHeight)
})

const colorDots = colorSeriseGroups
.append('g')
.selectAll('circle')
.data(d=>d[1])
.join('circle')
.attr("r", r)
.attr("fill", d => d['Hex'])
.attr('cx', d =>scaleX(chroma_okhcl(d['Hex'])[xFeild]))
.attr('cy', d =>scaleY(chroma_okhcl(d['Hex'])[yFeild]))
// // .selectAll('circle')
// // .join('circle')
// // .attr("r", r)
// // .attr("fill", d => d['Hex'])
// // .attr('cx', d =>{
// // console.log(d)
// // // return scaleChromaX(chroma_okhcl(d['Hex'])['chroma']
// // })
// // .attr('cy', d =>scaleLightnessY(chroma_okhcl(d['Hex'])['lightness']))
// })
colorSeriseGroups.append('g')
.attr('transform',`translate(0,${frameHeight})`)
.attr('class', 'x-axis')
.call(xAxis)
.call(g=>{
g.select('.domain')
.remove()
})
.call(g=>{
g.selectAll('.tick line')
.clone()
.attr('y2', -frameHeight)
.attr('opacity', .1)
})
colorSeriseGroups.append('g')
.attr('class', 'y-axis')
.call(yAxis)
.call(g=>{
g.select('.domain')
.remove()
})
.call(g=>{
g.selectAll('.tick line')
.clone()
.attr('x2', layout.frameWidth)
.attr('opacity', .1)
})


colorSourceGroups.append('g')
.append('text')
.text(d=>d[0])
.style("font", "12px sans-serif")
.style("font-weight", '500')
.style("text-anchor","middle")
.attr('transform',(d,i)=>{
let verticalNum = Math.ceil(d[1].length/horizontalNumber),
height = verticalNum * (frameHeight + innerGutter) - innerGutter
return `translate(-50,${height/2}) rotate(-90)`
})

g.append('g')
.append('text')
.text(`↑${yFeild.charAt(0).toUpperCase() + yFeild.slice(1)}`)
.style("font", "12px sans-serif")
.style("font-weight", '500')
.attr('transform', 'translate(-8, -20)')

g.append('g')
.append('text')
.text(`${xFeild.charAt(0).toUpperCase() + xFeild.slice(1)} →`)
.style("font", "12px sans-serif")
.style("font-weight", '500')
.attr('transform', `translate(-8, ${frameHeight + 40})`)

return svg.node()
}
Insert cell
lengthMirrorArray = colorArray_Scale_bySource_bySerise.map(e=>e[1].length)
Insert cell
Insert cell
layout = ({
width: width,
height: 3800,
margin: {
top: 50,
bottom: 10,
left: 80,
right: 50,
},
get innerWidth(){
return this.width - this.margin.left - this.margin.right
},
get innerHeight(){
return this.height - this.margin.top - this.margin.bottom
},
horizontalNumber: horizontalNumber,
get frameWidth(){
return (this.width - this.margin.left - this.margin.right + innerGutter)/this.horizontalNumber - innerGutter
}
})
Insert cell
Insert cell
Insert cell
scaleLightness = d3.scaleLinear()
.domain([0, 1])
// .range([0, frameHeight]);
Insert cell
scaleChroma = d3.scaleLinear()
.domain([0, 0.25])
// .range([0, layout.frameWidth]);
Insert cell
scaleHue = d3.scaleLinear()
.domain([0, 360])
// .range([0, layout.frameWidth]);
Insert cell
scale = ({
lightness: scaleLightness,
chroma: scaleChroma,
hue: scaleHue
})
Insert cell
scaleX = scale[xFeild].copy().range([0, layout.frameWidth])
Insert cell
scaleY = scale[yFeild].copy().range([frameHeight, 0])
Insert cell
Insert cell
xAxis = d3.axisBottom().scale(scaleX).ticks(6)
Insert cell
yAxis = d3.axisLeft().scale(scaleY).ticks(4)
Insert cell
Insert cell
colorData_Scale = colorData.filter(e=>!!e['Serise'])
Insert cell
colorArray_Scale_bySource_bySerise = d3.groups(colorData_Scale, e=>e['Source'], e=>e['Serise'])
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
colorData = d3.csv(getCsvUrl(url), (e)=>{
if(e['Hex'].trim().charAt(0)==='#'){
return {
Source: e['Source'],
Type: e['Type'],
Serise: e['Serise'],
Hex: e['Hex'],
}
}else{
return {
Source: e['Source'],
Type: e['Type'],
Serise: e['Serise'],
Hex: '#'+e['Hex'],
}
}
})
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