Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ the team will have a look.
| Bar chart stacked | [View](https://onsdigital.github.io/Charts/bar-chart-stacked/) | [`</>`](https://github.com/ONSdigital/Charts/tree/main/bar-chart-stacked/) | [README](https://github.com/ONSvisual/Charts/blob/main/bar-chart-stacked/README.md) |
| Bar chart stacked grouped | [View](https://onsdigital.github.io/Charts/bar-chart-stacked-grouped/) | [`</>`](https://github.com/ONSdigital/Charts/tree/main/bar-chart-stacked-grouped/) | [README](https://github.com/ONSvisual/Charts/blob/main/bar-chart-stacked-grouped/README.md) |
| Bar chart stacked sm | [View](https://onsdigital.github.io/Charts/bar-chart-stacked-sm/) | [`</>`](https://github.com/ONSdigital/Charts/tree/main/bar-chart-stacked-sm/) | [README](https://github.com/ONSvisual/Charts/blob/main/bar-chart-stacked-sm/README.md) |
| Bar chart with context bubbles | [View](https://onsdigital.github.io/Charts/bar-chart-with-context-bubbles/) | [`</>`](https://github.com/ONSdigital/Charts/tree/main/bar-chart-with-context-bubbles/) | [README](https://github.com/ONSvisual/Charts/blob/main/bar-chart-with-context-bubbles/README.md) |
| Bar chart with dropdown | [View](https://onsdigital.github.io/Charts/bar-chart-with-dropdown/) | [`</>`](https://github.com/ONSdigital/Charts/tree/main/bar-chart-with-dropdown/) | [README](https://github.com/ONSvisual/Charts/blob/main/bar-chart-with-dropdown/README.md) |
| Beeswarm | [View](https://onsdigital.github.io/Charts/beeswarm/) | [`</>`](https://github.com/ONSdigital/Charts/tree/main/beeswarm/) | [README](https://github.com/ONSvisual/Charts/blob/main/beeswarm/README.md) |
| Column chart | [View](https://onsdigital.github.io/Charts/column-chart/) | [`</>`](https://github.com/ONSdigital/Charts/tree/main/column-chart/) | [README](https://github.com/ONSvisual/Charts/blob/main/column-chart/README.md) |
Expand Down
1 change: 1 addition & 0 deletions bar-chart-with-context-bubbles/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Horizontal bar chart
9 changes: 9 additions & 0 deletions bar-chart-with-context-bubbles/chart.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
.dataLabels{
font-weight: 600;
font-size: 14px;
}

.bubbleLabels{
font-weight: 600;
font-size: 14px;
}
52 changes: 52 additions & 0 deletions bar-chart-with-context-bubbles/config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
config = {
"graphicDataURL": "data.csv",
"colourPalettePositive": ONScolours.emeraldGreen,
"colourPaletteNegative": ONScolours.coralPink,
"colourPaletteBubble": ONScolours.skyBlue,
"sourceText": "Office for National Statistics",
"accessibleSummary": "This chart has been hidden from screen readers. The main message of the chart is summarised in the chart title.",
"dataLabels": {
"show": true,
"numberFormat": ".1%"
},
"dataLabelsBubbleFormat": ".0%",
"xDomain": "auto",
// either "auto" or an array for the x domain e.g. [0,100]
"xAxisLabel": "x axis label",
"xAxisTitle": "x axis title",
"bubbleLabel": "Context bubble label",
"margin": {
"sm": {
"top": 50,
"bubble": 100,
"bottom": 50,
"left": 150,
"right": 10
},
"md": {
"top": 50,
"bubble": 100,
"bottom": 50,
"left": 180,
"right": 10
},
"lg": {
"top": 50,
"bubble": 100,
"bottom": 50,
"left": 200,
"right": 10
}
},
"seriesHeight": {
"sm": 30,
"md": 30,
"lg": 30
},
"xAxisTicks": {
"sm": 4,
"md": 8,
"lg": 10
},
"elements": { "select": 0, "nav": 0, "legend": 0, "titles": 0 }
};
22 changes: 22 additions & 0 deletions bar-chart-with-context-bubbles/data.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
name,value,value1
Total,0.022512891,
Information technology (IT),0.025372118,0.069091985
Professional and technical,0.014008212,0.086069359
Manufacturing,0.010507311,0.110469217
Construction,0.006866247,0.068666705
Administrative services,0.006428236,0.056393075
Transport and storage,0.003780288,0.044110711
"Agriculture, forestry and fishing",0.001529134,0.007096016
Water supply,0.000345815,0.013388421
Public administration and defence,0.000186062,0.053101109
Education,-0.000206951,0.063176273
Recreation and culture,-0.001420556,0.016436356
Other services,-0.001540501,0.021190873
Mining and quarrying,-0.002087217,0.011156108
Hotels and catering,-0.002794911,0.032992818
Wholesale and retail,-0.003061794,0.11328131
Real estate,-0.005436802,0.043964401
Energy,-0.008522412,0.016158477
Health and social care,-0.009248773,0.083735503
Finance and insurance,-0.012151287,0.089521284
Between-industry reallocation,-0.000039328,
Binary file added bar-chart-with-context-bubbles/fallback.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
41 changes: 41 additions & 0 deletions bar-chart-with-context-bubbles/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<!DOCTYPE html>
<html lang="en">
<!-- TEMPLATE https://github.com/ONSdigital/Charts/bar-chart-horizontal -->

<head>
<link href='https://fonts.googleapis.com/css?family=Open+Sans:400,600,700' rel='stylesheet' type='text/css'>
<title>Horizontal Bar Chart Template</title>

<meta name="template" content="bar-chart">
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta charset="utf-8" />
<meta name="robots" content="noindex" />
<meta name="googlebot" content="indexifembedded" />

<link rel="stylesheet" href="../lib/globalStyle.css" />
<link rel="stylesheet" href="./chart.css" />
</head>

<body>

<h5 id="accessibleSummary" class="visuallyhidden"></h5>

<div aria-hidden="true" id="legend"></div>

<div id="graphic" aria-hidden="true">
<!-- <img src="fallback.png" alt="[Chart]" /> -->
</div>


<h5 id="source">
</h5>

<script src="https://cdn.ons.gov.uk/vendor/d3/6.3.0/d3.min.js" type="text/javascript"></script>
<script src="https://cdn.ons.gov.uk/vendor/pym/1.3.2/pym.js" type="text/javascript"></script>
<script src="../lib/colours.js"></script>
<script src="./config.js"></script>
<script src="./script.js" type="module"></script>

</body>

</html>
188 changes: 188 additions & 0 deletions bar-chart-with-context-bubbles/script.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
import { initialise, wrap, addSvg, addDataLabels, addSource, addAxisLabel } from "../lib/helpers.js";

let graphic = d3.select("#graphic");
let pymChild = null;
let graphicData, size, svg;


function drawGraphic() {
// Set up some of the basics and return the size value ('sm', 'md' or 'lg')
// To override breakpoints, pass as: initialise(size, { mediumBreakpoint: 500 })
size = initialise(size);

let margin = config.margin[size];

let chartWidth =
parseInt(graphic.style("width")) - margin.left - margin.bubble - 20;

let height =
config.seriesHeight[size] * graphicData.length +
10 * (graphicData.length - 1) +
12;

//set up scales
const x = d3.scaleLinear().range([0, chartWidth]);

const y = d3
.scaleBand()
.paddingOuter(0.2)
.paddingInner(((graphicData.length - 1) * 10) / (graphicData.length * 30))
.range([0, height])
.round(true);

//use the data to find unique entries in the name column
y.domain([...new Set(graphicData.map((d) => d.name))]);

//set up yAxis generator
let yAxis = d3.axisLeft(y).tickSize(0).tickPadding(10);

//set up xAxis generator
let xAxis = d3
.axisBottom(x)
.tickSize(-height)
.tickFormat(d3.format(config.dataLabels.numberFormat))
.ticks(config.xAxisTicks[size]);

//create svg for chart
svg = addSvg({
svgParent: graphic,
chartWidth: chartWidth,
height: height + margin.top + margin.bottom,
margin: { ...margin, right: margin.bubble + margin.right }
})

if (config.xDomain == "auto") {
if (d3.min(graphicData.map(({ value }) => Number(value))) >= 0) {
x.domain([0, d3.max(graphicData.map(({ value }) => Number(value)))]); //modified so it converts string to number
} else {
x.domain(d3.extent(graphicData.map(({ value }) => Number(value))));
}
} else {
x.domain(config.xDomain);
}

svg
.append("g")
.attr("transform", "translate(0," + height + ")")
.attr("class", "x axis")
.call(xAxis)
.selectAll("line")
.each(function (d) {
if (d == 0) {
d3.select(this).attr("class", "zero-line");
}
});

svg
.append("g")
.attr("class", "y axis")
.call(yAxis)
.selectAll("text")
.call(wrap, margin.left - 20);

svg
.selectAll("rect")
.data(graphicData)
.join("rect")
.attr("x", (d) => (d.value < 0 ? x(d.value) : x(0)))
.attr("y", (d) => y(d.name))
.attr("width", (d) => Math.abs(x(d.value) - x(0)))
.attr("height", y.bandwidth())
.attr("fill", (d) => d.value >= 0 ? config.colourPalettePositive : config.colourPaletteNegative);

// Add context bubbles
const maxRadius = margin.bubble / 1.85;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we have a config parameter to change the relative scaled size of the bubbles?

const maxValueBubble = d3.max(graphicData, d => Math.abs(d.value1));

function calculateRadius(value) {
const areaScaleFactor = Math.pow(maxRadius, 2);
return Math.sqrt((Math.abs(value) / maxValueBubble) * areaScaleFactor / Math.PI);
}

svg
.selectAll("circle")
.data(graphicData)
.join("circle")
.attr("cx", chartWidth + margin.bubble / 2)
.attr("cy", (d) => y(d.name) + y.bandwidth() / 2)
.attr("r", d => calculateRadius(d.value1))
.attr("fill", config.colourPaletteBubble)
.attr("fill-opacity", 0.2)
.attr("stroke", config.colourPaletteBubble)
.attr("stroke-opacity", 0.4);

svg
.selectAll("text.bubbleLabels")
.data(graphicData)
.join("text")
.attr("class", "bubbleLabels")
.attr("x", chartWidth + margin.bubble / 2)
.attr("dx", 0)
.attr("y", (d) => y(d.name) + y.bandwidth() / 2)
.attr("dominant-baseline", "middle")
.attr("text-anchor", "middle")
.attr("fill", "#414042")
.text((d) => {
if (!d.value1 || d.value1 === "" || d.value1 === "0%" || d.value1 === 0) return "";
return isNaN(d.value1) ? "Not applicable" : d3.format(config.dataLabelsBubbleFormat)(d.value1);
});



if (config.dataLabels.show == true) {
addDataLabels({
svgContainer: svg,
data: graphicData,
chartWidth: chartWidth,
labelPositionFactor: 7,
xScaleFunction: x,
yScaleFunction: y
})
} //end if for datalabels

//This does the x-axis title at the top for bars
addAxisLabel({
svgContainer: svg,
xPosition: 0,
yPosition: -10,
text: config.xAxisTitle,
textAnchor: 'start'
})

//This does the x-axis label below the x-axis
addAxisLabel({
svgContainer: svg,
xPosition: chartWidth,
yPosition: height + 35,
text: config.xAxisTitle,
textAnchor: 'end'
})

//This does the bubble label at the top
addAxisLabel({
svgContainer: svg,
xPosition: chartWidth + margin.bubble / 2,
yPosition: -10,
text: config.bubbleLabel,
textAnchor: 'middle',
wrapWidth: margin.bubble
})

//create link to source
addSource('source', config.sourceText);

//use pym to calculate chart dimensions
if (pymChild) {
pymChild.sendHeight();
}
}

d3.csv(config.graphicDataURL).then((data) => {
//load chart data
graphicData = data;

//use pym to create iframed chart dependent on specified variables
pymChild = new pym.Child({
renderCallback: drawGraphic,
});
});
11 changes: 11 additions & 0 deletions chart-menu/chartConfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,17 @@ const chartConfig = [
{ name: "data.csv", path: "data.csv" }
]
},
{
name: "Bar chart with context bubbles",
url: "https://onsdigital.github.io/Charts/bar-chart-with-context-bubbles/",
tags: {
comparison: true,
"change-over-time": true
},
dataFiles: [
{ name: "data.csv", path: "data.csv" }
]
},
{
name: "Beeswarm",
url: "https://onsdigital.github.io/Charts/beeswarm/",
Expand Down