问题描述
请查看 Observablehq notebook 中的代码:https://observablehq.com/@erayalan/radial-scatter-plot
我想了解如何更改此作品中每个项目的大小和颜色:
data = [{ name : "foo",r: 40,theta: 1.4 },{ name : "bar",r: 30,theta: 4.8 },{ name : "baz",r: 60,theta: 3.05}]
解决方法
要更改圆圈的大小,您可以使用 "r"
属性,类似于使用“cx”和“cy”的方式。我假设您想将“theta”映射到大小。首先,您需要创建 a scale:
const radiusScale = d3.scaleLinear().domain(d3.extent(data,d=> d.theta)).range([10,20])
d3.extent(data,d=> d.theta)
中的函数 extent 返回 theta 属性中数据的最大值和最小值(在本例中为 [1.4,4.8]
)。这意味着这个标度的域为 [1.4,4.8]
,范围为 [10,20]
,所以如果你调用 radiusScale(1.4)
它将输出 10
,而 radiusScale(4.8)
将输出 { {1}}。有了这个,您将 theta 值映射到足够的半径,并且可以在 SVG 圆的 20
属性上使用它:
"r"
类似的逻辑适用于在 .attr("cx",d => d.r * Math.cos(d.theta))
.attr("cy",d => d.r * Math.sin(d.theta))
.attr("r",d => radiusScale(d.theta))
属性中定义的颜色。您想将“foo”、“bar”和“baz”映射到不同的颜色。您可以为此使用 "fill"
和颜色数组:
scaleOrdinal
这个刻度的范围是 const colorScale = d3.scaleOrdinal().range(d3.schemeCategory10)
,它只是一个包含一些常见颜色的数组(你可以使用任何颜色数组)。您不需要此比例的域,因为 d3 可以自动为比例接收的每个唯一值分配不同的颜色。
然后您可以补充映射,将颜色分配给填充属性。
d3.schemeCategory10
这里是 a fork of your notebook 上面的变化:
附注:
在我的回答中,我将 theta 的值直接映射到半径。不建议使用圆的半径来编码一个值,最好的做法是使用它的面积。为简单起见,我不会在这里深入介绍,但您可以查看映射大小 here 的更好方法。
D3 的学习曲线可能有点陡峭。您在此答案中看到了几个用于更改颜色和大小(比例、域、范围、范围等!)的概念。您可能需要检查 the official d3 introduction 以更连续的方式查看这些概念。
,这是一个包含尺寸和颜色的片段:
data = [
{name: "foo",r: 40,theta: 1.4,size: 10,color: 'red'},{name: "bar",r: 30,theta: 4.8,size: 12,color: 'green'},{name: "baz",r: 60,theta: 3.05,size: 14,color: 'blue'}
];
const width = 200;
const height = 200;
const svg = d3.select('svg');
const radius = 100;
const r = d3.scaleLinear()
.domain([0,1])
.range([0,radius]);
svg
.attr("viewBox",`${-width / 2} ${-height / 2} ${width} ${height}`)
.attr('width',width)
.attr('height',height)
.style("font","10px sans-serif");
const gr = svg.append('g')
.attr('class','r axis')
.selectAll('g')
.data(r.ticks(5).slice(1))
.enter()
.append('g');
gr.append('circle')
.attr("fill","none")
.attr("stroke","#ebebeb")
.attr('r',r);
const ga = svg.append('g')
.attr('class','a axis')
.selectAll('g')
.data(d3.range(0,360,30)) // line density
.enter()
.append('g')
.attr('transform',d => 'rotate(' + -d + ')');
ga.append('line')
.attr("fill","none")
.attr("stroke","#aaa")
.attr('x2',radius);
svg.selectAll("point") // No longer "rect"
.data(data)
.enter()
.append("circle")
.attr("cx",d => d.size)
.style('stroke',d => d.color)
.style('fill','white');
svg.selectAll("text") // Note "text",not "circle" or "rect"
.data(data)
.enter()
.append("text")
.text(d => d.name)
.attr("x",d => d.r * Math.cos(d.theta))
.attr("y",d => d.r * Math.sin(d.theta))
.attr('alignment-baseline','middle')
.attr('text-anchor','middle')
.attr("font-family","sans-serif")
.attr("font-size","11px")
.attr("fill",d => d.color);
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<svg/>