Newer
Older
<section id="beeswarm">
<div id="text1" class="text-container">
<p>Everyone needs access to clean water. Water insecurity is influenced by a number of social vulnerability indicators. This includes
<span class="highlight demographicCharacteristics" id="demographicCharacteristics" >demographic characteristics</span>,
<span class="highlight health" id="health" >health</span>,
<span class="highlight livingConditions" id="livingConditions">living conditions</span>,
<span class="highlight socioeconomicStatus" id="socioeconomicStatus" >socioeconomic status</span>,
<span class="highlight landTenure" id="landTenure" >land tenure</span>,
<span class="highlight riskPerception" id="riskPerception" >risk perception</span>, and
<span class="highlight exposureToStressors" id="exposureToStressors">exposure to stressors</span> (like drought or pollution).
</p>
</template>
<script setup>
import { onMounted, ref, watch } from "vue";
import * as d3 from 'd3';
// global variables
const publicPath = import.meta.env.BASE_URL;
const dataSet1 = ref([]);
const dataSet2 = ref([]);
const selectedDataSet = ref('dataSet1');
const categoryCenters = {}
let data = dataSet1;
let simulation;
// set up svg
let svg;
const height = 800;
const width = 800;
let margin = {top: 30, right: 20, bottom: 20, left: 30}
// set colors for bubble charts
const dimensionColors = {
Demographiccharacteristics: "#092836",
Landtenure: "#2a468f",
Livingconditions: "#7a5195",
Socioeconomicstatus: "#1b695e",
Health: "#ef5675",
Riskperception: "#ff764a",
Exposure: "#ffa600"
}
// load data and then make chart
onMounted(() => {
console.log("component mounted");
loadDatasets().then(() => {
if (selectedDataSet.value.length > 0) {
createBeeswarmChart(selectedDataSet);
} else {
console.error('Error loading data:', error)
}
});
});
async function loadDatasets() {
dataSet1.value = await loadData('determinant_uncertainty.csv');
dataSet2.value = await loadData('indicator_uncertainty.csv')
}
async function loadData(fileName) {
return await d3.csv(publicPath + fileName, d => {
d.level_agreement = +(+d.level_agreement).toFixed(2);
d.evidence_val = +d.evidence_val;
d.sig_value = +d.sig_value;
return d;
});
};
function createBeeswarmChart() {
svg = d3
.selectAll('#beeswarm-chart-container')
.append('svg')
.attr('class', 'beeswarmSvg')
.attr('width', width)
.attr('height', height)
.domain([40, d3.max(data.value, d => d.level_agreement)])
// set radius based on evidence value
const radiusScale = d3.scaleLinear()
.domain([d3.min(data.value, d => d.evidence_val), d3.max(data.value, d => d.evidence_val)])
.range([10, 90]);
.attr("transform", "translate(0," + (height - 50) + ")")
.attr("text-anchor", "start")
.attr("x", 10)
.attr("y", 20)
.text("High level of Agreement");
svg.append('text')
.attr("text-anchor", "start")
.attr("x", 10)
.attr("y", height-50)
.text("Inconclusive");
const forceY = d3.forceY(d => yScale(d.level_agreement)).strength(1);
const forceCollide = d3.forceCollide(d => radiusScale(d.evidence_val) + 2); //forceCollide for bubbles sized by evidence_val
const forceManyBody = d3.forceManyBody().strength(-15); // Adjust the strength as needed
const bubbles = svg
.selectAll('.bubble')
.data(data.value)
.enter()
.append('circle')
.attr('class', 'bubble')
.attr('r', d => radiusScale(d.evidence_val))
.style('fill', (d) => dimensionColors[d.dimension.replace(' ', '')])
const simulation = d3
.forceSimulation()
.force('x', forceX)
.force('y', forceY)
.force('collide', forceCollide)
.force('charge', forceManyBody)
.nodes(data.value)
.on('tick', ticked)
.alpha(0.2)
/* simulation = d3.forceSimulation()
.force("x", forceX)
.force("y", forceY)
.force("collide", forceCollide)
.force("charge", forceManyBody)
.nodes(data.value)
.on("tick", ticked)
.alpha(.2)
.restart(); */
function ticked() {
bubbles
.attr("cx", d => d.x)
.attr("cy", d => d.y);
}
}
</script>
<style scoped lang="scss">
$switchWidth: 12rem;
$Demographiccharacteristics: "#625D0B";
$Landtenure: "#5C0601";
$Livingconditions: "#0B4E8B";
$Socioeconomicstatus: "#DC8260";
$Health: "#7F4A89";
$Riskperception: "#249CB1";
$Exposure: "#B47D83";
#beeswarm-chart-container {
text-align: center;
position: relative;
}
#beeswarm-chart-container svg {
max-width: 100%;
max-height: 100%;
height: auto; /* Maintain aspect ratio */
display: inline-block;
}
.bubble {
stroke: black;
stroke-width: 2px;
fill-opacity: 0.8;
}
.chart-text {
user-select: none;
}
.tooltip {
font-size: 16px;
background-color: white;
border: solid;
border-width: 2px;
border-radius: 5px;
padding: 5px;
position: absolute;
}
.highlight {
color: white;
padding: 0.25px 5px;
border-radius: 10px;
white-space: nowrap;
}
.demographicCharacteristics {
background-color: #092836;
}
.landTenure {
background-color: #2a468f;
}
.livingConditions {
background-color: #7a5195;
}
.socioeconomicStatus {
background-color: #1b695e;
}
.health {
background-color: #ef5675;
}
.riskPerception {
background-color: #ff6b4a;
}
.exposureToStressors {
background-color: #ffa600;
}