d3.js 如何让饼图的图案平行于扇区的中心线?
How to make the patterns of a pie chart parallel to the center line of sectors in d3.js?
我创建了一个充满模式的饼图。我想让图案平行于它所在扇区的中心线。我试图改变 patternTransform
参数来旋转图案,但我不知道如何获得正确的度数。
我怎样才能做到这一点?
我当前的代码:
<script src="https://unpkg.com/d3@5.15.1/dist/d3.min.js"></script>
<script src="https://d3js.org/d3.v4.js"></script>
<svg width="300" height="200"> </svg>
<svg>
<defs>
<pattern id="pattern0"
x="0" y="0" width="20" height="20"
patternUnits="userSpaceOnUse" patternTransform="rotate(0)">
<rect id="rotateRect" x="5" y = "5" width = "10" height = "10" fill = " #87CEFA "/>
</pattern>
</defs>
<defs>
<pattern id="pattern1"
x="0" y="0" width="20" height="20"
patternUnits="userSpaceOnUse" patternTransform="rotate(0)">
<rect id="rotateRect" x="5" y = "5" width = "10" height = "10" fill = " #4169E1 "/>
</pattern>
</defs>
<defs>
<pattern id="pattern2"
x="0" y="0" width="20" height="20"
patternUnits="userSpaceOnUse" patternTransform="rotate(0)">
<rect id="rotateRect" x="5" y = "5" width = "10" height = "10" fill = " #000080 "/>
</pattern>
</defs>
<rect x="0" y="0" width="100" height="100"
style="stroke: #000000; fill: url(#pattern0);" />
<rect x="100" y="0" width="100" height="100"
style="stroke: #000000; fill: url(#pattern1);" />
<rect x="200" y="0" width="100" height="100"
style="stroke: #000000; fill: url(#pattern2);" />
</svg>
<script>
var data = [{ year: '2001', value:10 },
{ year: '2002', value:30 },
{ year: '2003', value:60 },
]
var svg = d3.select("svg"),
width = svg.attr("width"),
height = svg.attr("height"),
radius = Math.min(width, height) / 2,
g = svg.append("g").attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
var color = d3.scaleOrdinal(['#4daf4a','#377eb8','#ff7f00','#984ea3','#e41a1c']);
// Generate the pie
var pie = d3.pie().value(function(d) {
return d.value;});
// Generate the arcs
var arc = d3.arc()
.innerRadius(0)
.outerRadius(radius);
//Generate groups
var arcs = g.selectAll("arc")
.data(pie(data))
.enter()
.append("g")
.attr("class", "arc")
//Draw arc paths
arcs.append("path")
.attr("d", arc)
.attr('stroke', "black")
.attr('stroke-width', '1')
.attr("fill", function(d,i) { return "url(#pattern" + i +")"});
</script>
</script>
提前致谢。
由于 patternTransform
属性是在模式上定义的,因此您需要在运行时动态创建 <pattern>
元素。
d3.pie(data)
returns 具有 startAngle
和 endAngle
属性的对象数组。您可以使用它们来计算所需的旋转:
averageAngle = (d.startAngle + d.endAngle) * 90 / Math.PI
我本来希望只定义一次图案几何,然后re-use那个as a template,但不幸的是至少Firefox没有通过影子树模型实现样式继承。因此,如果我做这样的事情...
<pattern id="patternTemplate"
x="0" y="0" width="20" height="20"
patternUnits="userSpaceOnUse" patternTransform="rotate(0)">
<rect id="rotateRect" x="5" y = "5" width = "10" height = "10" />
</pattern>
<pattern id="pattern0" href="#patternTemplate" fill="#4daf4a" />
...图案中使用的填充颜色保持黑色。
<script src="https://unpkg.com/d3@5.15.1/dist/d3.min.js"></script>
<script src="https://d3js.org/d3.v4.js"></script>
<svg id="pie" width="300" height="200"> </svg>
<svg id="legend">
<rect x="0" y="0" width="100" height="100"
style="stroke: #000000; fill: url(#pattern0);" />
<rect x="100" y="0" width="100" height="100"
style="stroke: #000000; fill: url(#pattern1);" />
<rect x="200" y="0" width="100" height="100"
style="stroke: #000000; fill: url(#pattern2);" />
</svg>
<script>
var data = [{ year: '2001', value:10 },
{ year: '2002', value:30 },
{ year: '2003', value:60 },
]
var svg = d3.select("svg#pie"),
width = svg.attr("width"),
height = svg.attr("height"),
radius = Math.min(width, height) / 2,
g = svg.append("g").attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
var color = d3.scaleOrdinal(['#4daf4a','#377eb8','#ff7f00','#984ea3','#e41a1c']);
// Generate the pie
var pie = d3.pie().value(function(d) {
return d.value;})(data);
// Generate the patterns
var legend = d3.select("svg#legend"),
defs = legend.append("defs");
defs.selectAll("pattern")
.data(pie)
.enter()
.append("pattern")
.attr("id", (d, i) => "pattern" + i)
.attr("patternUnits", "userSpaceOnUse")
.attr("width", 20)
.attr("height", 20)
.attr("patternTransform", (d) => `rotate(${(d.startAngle + d.endAngle) * 90 / Math.PI})`)
.style("fill", (d, i) => color(i))
.append("rect")
.attr("x", 5)
.attr("y", 5)
.attr("width", 10)
.attr("height", 10)
// Generate the arcs
var arc = d3.arc()
.innerRadius(0)
.outerRadius(radius);
//Generate groups
var arcs = g.selectAll("arc")
.data(pie)
.enter()
.append("g")
.attr("class", "arc")
//Draw arc paths
arcs.append("path")
.attr("d", arc)
.attr('stroke', "black")
.attr('stroke-width', '1')
.attr("fill", function(d,i) { return "url(#pattern" + i +")"});
</script>
</script>
我创建了一个充满模式的饼图。我想让图案平行于它所在扇区的中心线。我试图改变 patternTransform
参数来旋转图案,但我不知道如何获得正确的度数。
我怎样才能做到这一点?
我当前的代码:
<script src="https://unpkg.com/d3@5.15.1/dist/d3.min.js"></script>
<script src="https://d3js.org/d3.v4.js"></script>
<svg width="300" height="200"> </svg>
<svg>
<defs>
<pattern id="pattern0"
x="0" y="0" width="20" height="20"
patternUnits="userSpaceOnUse" patternTransform="rotate(0)">
<rect id="rotateRect" x="5" y = "5" width = "10" height = "10" fill = " #87CEFA "/>
</pattern>
</defs>
<defs>
<pattern id="pattern1"
x="0" y="0" width="20" height="20"
patternUnits="userSpaceOnUse" patternTransform="rotate(0)">
<rect id="rotateRect" x="5" y = "5" width = "10" height = "10" fill = " #4169E1 "/>
</pattern>
</defs>
<defs>
<pattern id="pattern2"
x="0" y="0" width="20" height="20"
patternUnits="userSpaceOnUse" patternTransform="rotate(0)">
<rect id="rotateRect" x="5" y = "5" width = "10" height = "10" fill = " #000080 "/>
</pattern>
</defs>
<rect x="0" y="0" width="100" height="100"
style="stroke: #000000; fill: url(#pattern0);" />
<rect x="100" y="0" width="100" height="100"
style="stroke: #000000; fill: url(#pattern1);" />
<rect x="200" y="0" width="100" height="100"
style="stroke: #000000; fill: url(#pattern2);" />
</svg>
<script>
var data = [{ year: '2001', value:10 },
{ year: '2002', value:30 },
{ year: '2003', value:60 },
]
var svg = d3.select("svg"),
width = svg.attr("width"),
height = svg.attr("height"),
radius = Math.min(width, height) / 2,
g = svg.append("g").attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
var color = d3.scaleOrdinal(['#4daf4a','#377eb8','#ff7f00','#984ea3','#e41a1c']);
// Generate the pie
var pie = d3.pie().value(function(d) {
return d.value;});
// Generate the arcs
var arc = d3.arc()
.innerRadius(0)
.outerRadius(radius);
//Generate groups
var arcs = g.selectAll("arc")
.data(pie(data))
.enter()
.append("g")
.attr("class", "arc")
//Draw arc paths
arcs.append("path")
.attr("d", arc)
.attr('stroke', "black")
.attr('stroke-width', '1')
.attr("fill", function(d,i) { return "url(#pattern" + i +")"});
</script>
</script>
提前致谢。
由于 patternTransform
属性是在模式上定义的,因此您需要在运行时动态创建 <pattern>
元素。
d3.pie(data)
returns 具有 startAngle
和 endAngle
属性的对象数组。您可以使用它们来计算所需的旋转:
averageAngle = (d.startAngle + d.endAngle) * 90 / Math.PI
我本来希望只定义一次图案几何,然后re-use那个as a template,但不幸的是至少Firefox没有通过影子树模型实现样式继承。因此,如果我做这样的事情...
<pattern id="patternTemplate"
x="0" y="0" width="20" height="20"
patternUnits="userSpaceOnUse" patternTransform="rotate(0)">
<rect id="rotateRect" x="5" y = "5" width = "10" height = "10" />
</pattern>
<pattern id="pattern0" href="#patternTemplate" fill="#4daf4a" />
...图案中使用的填充颜色保持黑色。
<script src="https://unpkg.com/d3@5.15.1/dist/d3.min.js"></script>
<script src="https://d3js.org/d3.v4.js"></script>
<svg id="pie" width="300" height="200"> </svg>
<svg id="legend">
<rect x="0" y="0" width="100" height="100"
style="stroke: #000000; fill: url(#pattern0);" />
<rect x="100" y="0" width="100" height="100"
style="stroke: #000000; fill: url(#pattern1);" />
<rect x="200" y="0" width="100" height="100"
style="stroke: #000000; fill: url(#pattern2);" />
</svg>
<script>
var data = [{ year: '2001', value:10 },
{ year: '2002', value:30 },
{ year: '2003', value:60 },
]
var svg = d3.select("svg#pie"),
width = svg.attr("width"),
height = svg.attr("height"),
radius = Math.min(width, height) / 2,
g = svg.append("g").attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
var color = d3.scaleOrdinal(['#4daf4a','#377eb8','#ff7f00','#984ea3','#e41a1c']);
// Generate the pie
var pie = d3.pie().value(function(d) {
return d.value;})(data);
// Generate the patterns
var legend = d3.select("svg#legend"),
defs = legend.append("defs");
defs.selectAll("pattern")
.data(pie)
.enter()
.append("pattern")
.attr("id", (d, i) => "pattern" + i)
.attr("patternUnits", "userSpaceOnUse")
.attr("width", 20)
.attr("height", 20)
.attr("patternTransform", (d) => `rotate(${(d.startAngle + d.endAngle) * 90 / Math.PI})`)
.style("fill", (d, i) => color(i))
.append("rect")
.attr("x", 5)
.attr("y", 5)
.attr("width", 10)
.attr("height", 10)
// Generate the arcs
var arc = d3.arc()
.innerRadius(0)
.outerRadius(radius);
//Generate groups
var arcs = g.selectAll("arc")
.data(pie)
.enter()
.append("g")
.attr("class", "arc")
//Draw arc paths
arcs.append("path")
.attr("d", arc)
.attr('stroke', "black")
.attr('stroke-width', '1')
.attr("fill", function(d,i) { return "url(#pattern" + i +")"});
</script>
</script>