Skip to content
Snippets Groups Projects
BeeswarmChart.vue 6.21 KiB
Newer Older
  • Learn to ignore specific revisions
  • Cee Nell's avatar
    Cee Nell committed
    <template>
    
    Cee Nell's avatar
    Cee Nell committed
        <section id="beeswarm">
            <div id="text1" class="text-container">
    
    Cee Nell's avatar
    Cee Nell committed
                <p>Everyone needs access to clean water. Water insecurity is influenced by a number of social vulnerability indicators. This includes 
    
    Cee Nell's avatar
    Cee Nell committed
                    <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>
    
    Cee Nell's avatar
    Cee Nell committed
            </div>
    
    Cee Nell's avatar
    Cee Nell committed
            <div id="beeswarm-chart-container"></div>
        </section>
    
    Cee Nell's avatar
    Cee Nell committed
    </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 = {
    
    Cee Nell's avatar
    Cee Nell committed
        Demographiccharacteristics: "#092836",
        Landtenure: "#2a468f",
        Livingconditions: "#7a5195",
        Socioeconomicstatus: "#1b695e",
        Health: "#ef5675",
        Riskperception: "#ff764a",
        Exposure: "#ffa600"
    
    Cee Nell's avatar
    Cee Nell committed
    }
    
    // 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)
    
    Cee Nell's avatar
    Cee Nell committed
    
    
    Cee Nell's avatar
    Cee Nell committed
        const yScale = d3.scaleLinear()
    
            .domain([40, d3.max(data.value, d => d.level_agreement)])
    
    Cee Nell's avatar
    Cee Nell committed
            .range([margin.bottom+height, margin.top]);
    
                
        // 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]);
    
    
    Cee Nell's avatar
    Cee Nell committed
        const yAxis = svg.append('g')
    
            .attr("transform", "translate(0," + (height - 50) + ")")
    
    Cee Nell's avatar
    Cee Nell committed
            .call(d3.axisLeft(yScale))
    
    Cee Nell's avatar
    Cee Nell committed
        // add label to y axis
    
        svg.append('text')
    
    Cee Nell's avatar
    Cee Nell committed
            .attr("class", "yLabel")
    
            .attr("text-anchor", "start")
            .attr("x", 10)
            .attr("y", 20)
            .text("High level of Agreement");
    
        svg.append('text')
    
    Cee Nell's avatar
    Cee Nell committed
            .attr("class", "yLabel")
    
            .attr("text-anchor", "start")
            .attr("x", 10)
            .attr("y", height-50)
            .text("Inconclusive");
    
    Cee Nell's avatar
    Cee Nell committed
    
        // set forces
    
    Cee Nell's avatar
    Cee Nell committed
        const forceY = d3.forceY(d => yScale(d.level_agreement)).strength(1);
    
    Cee Nell's avatar
    Cee Nell committed
        const forceX = d3.forceX((width/1.5)).strength(0.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(' ', '')])
    
    
    Cee Nell's avatar
    Cee Nell committed
        // run simulation
    
        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);
        }
    
    Cee Nell's avatar
    Cee Nell committed
    }
    
    
    </script>
      
    <style scoped lang="scss">
    $switchWidth: 12rem;
    
    Cee Nell's avatar
    Cee Nell committed
    $Demographiccharacteristics: "#625D0B";
    $Landtenure: "#5C0601";
    $Livingconditions: "#0B4E8B";
    $Socioeconomicstatus: "#DC8260";
    $Health: "#7F4A89";
    $Riskperception: "#249CB1";
    $Exposure: "#B47D83";
    
    
    Cee Nell's avatar
    Cee Nell committed
    
    #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;
    }
    
    Cee Nell's avatar
    Cee Nell committed
    .yLabel {
        font-weight: bold;
    }
    
    Cee Nell's avatar
    Cee Nell committed
    .tooltip {
        font-size: 16px;
        background-color: white;
        border: solid;
        border-width: 2px;
        border-radius: 5px;
        padding: 5px;
        position: absolute;
    }
    
    
    Cee Nell's avatar
    Cee Nell committed
    
    .highlight {
        color: white;
        padding: 0.25px 5px;
        border-radius: 10px;
        white-space: nowrap;
    
    Cee Nell's avatar
    Cee Nell committed
        font-weight: bold;
    
    Cee Nell's avatar
    Cee Nell committed
    }
    .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;
    }
    
    
    Cee Nell's avatar
    Cee Nell committed
    </style>