I am experimenting with different styles for charts – and I am wondering how to create these kind of pattern textures charts for the different segments.
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;
1