I am experimenting with different styles for charts – and I am wondering how to create these exact kind of pattern textures charts for the different segments.
How do you start creating some of these specific patterns if its something less traditional like a big/small dot tessellation.
Or if there is a gradient instead of a pattern
and in this case there appears to be a slight rounding at the edges of the pie as if it were stacked on top of each other and overlayed more.
d3js pie chart with different patterns for the segments
demo reference with a legend on the left – and pie/half pie on the right
https://codesandbox.io/p/sandbox/magical-wiles-forked-fvj79p
my current build — regular pie
import React from 'react';
import * as d3 from 'd3';
import './PieChart1.scss';
class PieChart extends React.Component {
constructor(props) {
super(props);
this.myRef = React.createRef();
this.state = {
data: [],
theme: this.props.theme ? this.props.theme : ['#bde0fe', '#2698f9', '#71bcfd', '#f1f8fe']
};
}
componentDidMount() {
var $this = this.myRef.current;
d3.select($this)
.selectAll('svg')
.remove();
const data = this.props.data;
const width = parseInt(this.props.width, 10),
height = parseInt(this.props.height, 10),
radius = parseInt(this.props.r, 10),
innerradius = parseInt(this.props.ir, 10);
var color = d3.scaleOrdinal().range(this.state.theme);
var arc = d3
.arc()
.outerRadius(radius)
.innerRadius(innerradius);
data.forEach(function(d) {
d.total = +d.value;
});
var pie = d3
.pie()
.sort(null)
.value(function(d) {
return d.total;
});
var svg = d3
.select($this)
.append('svg')
.attr('width', width)
.attr('height', height)
.append('g')
.attr('class', 'piechart')
.attr('transform', 'translate(' + width / 2 + ',' + height / 2 + ')');
var segments = svg.append('g').attr('class', 'segments');
var slices = segments
.selectAll('.arc')
.data(pie(data))
.enter()
.append('g')
.attr('class', 'arc');
slices
.append('path')
.attr('d', arc)
.attr('fill', function(d, i) {
return color(i);
})
.transition()
.attrTween('d', function(d) {
var i = d3.interpolate(d.startAngle+0.1, d.endAngle);
return function(t) {
d.endAngle = i(t);
return arc(d);
}
});
}
render() {
return <div ref={this.myRef} className="PieChart" />;
}
}
export default PieChart;
I’ve seen this example in making a pattern – how would you make these 4 pattern types — one appears to be just a gradient
<!DOCTYPE html>
<html>
<head>
<style>
</style>
</head>
<body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<div id="hook"></div>
<script type="text/javascript">
// SVG injection:
var svg = d3.select("#hook").append("svg").attr("id", "d3svg")
.attr("width", 120)
.attr("height", 120);
//Pattern injection
var defs = svg.append("defs")
var pattern = defs.append("pattern")
.attr({ id:"hash4_4", width:"8", height:"8", patternUnits:"userSpaceOnUse", patternTransform:"rotate(-45)"})
.append("rect")
.attr({ width:"4", height:"8", transform:"translate(0,0)", fill:"#88AAEE" });
//Shape design
svg.append("g").attr("id","shape")
.append("circle")
.attr({cx:"60",cy:"60",r:"50", fill:"url(#hash4_4)" })
</script>
</body>
</html>
Found this as a reference — but not sure how to make those exact patterns in the demo
How to make the patterns of a pie chart parallel to the center line of sectors in d3.js?
<script src="https://unpkg.com/[email protected]/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>
19th Sep – latest version – with general patterns – but not the ones we need or legend in the right place.
https://codesandbox.io/p/sandbox/magical-wiles-forked-pmdgrs
import React from "react";
import * as d3 from "d3";
import "./PieChart1.scss";
class PieChart extends React.Component {
constructor(props) {
super(props);
this.myRef = React.createRef();
this.state = {
data: [],
theme: this.props.theme
? this.props.theme
: ["#bde0fe", "#2698f9", "#71bcfd", "#f1f8fe"],
};
}
componentDidMount() {
var $this = this.myRef.current;
d3.select($this).selectAll("svg").remove();
const data = this.props.data;
const width = parseInt(this.props.width, 10),
height = parseInt(this.props.height, 10),
radius = parseInt(this.props.r, 10),
innerradius = parseInt(this.props.ir, 10);
var color = d3.scaleOrdinal().range(this.state.theme);
var arc = d3.arc().outerRadius(radius).innerRadius(innerradius);
data.forEach(function (d) {
d.total = +d.value;
});
var pie = d3
.pie()
.sort(null)
.value(function (d) {
return d.total;
});
var svg = d3
.select($this)
.append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("class", "piechart")
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
// Generate the patterns
var legend = d3.select("svg#legend"),
defs = legend.append("defs");
defs
.selectAll("pattern")
.data(pie(data))
.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);
var segments = svg.append("g").attr("class", "segments");
var slices = segments
.selectAll(".arc")
.data(pie(data))
.enter()
.append("g")
.attr("class", "arc");
slices
.append("path")
.attr("d", arc)
//.attr("fill", function (d, i) {
// return color(i);
//})
.attr("stroke", "black")
.attr("stroke-width", "1")
.attr("fill", function (d, i) {
return "url(#pattern" + i + ")";
})
.transition()
.attrTween("d", function (d) {
var i = d3.interpolate(d.startAngle + 0.1, d.endAngle);
return function (t) {
d.endAngle = i(t);
return arc(d);
};
});
}
render() {
return (
<>
<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>
<div ref={this.myRef} className="PieChart" />
</>
);
}
}
export default PieChart;