Reputation: 75
I'm using chart.js (or more specifically vue-chartjs) for a component I want to use on a dashboard page. The user is supposed to be able to add new charts to the component using the dashboard. Since the component itself is of fixed size, I need the charts to properly align themselves and more importantly, resize in order to fit their parent container. I tried out a bunch of things but most ended with either the charts not filling out the container properly or overflowing the container vertically. Here is my code:
<script setup>
import { ref, onMounted } from 'vue';
import VueSlider from 'vue-slider-component';
import 'vue-slider-component/theme/default.css';
import { Doughnut } from 'vue-chartjs';
import { Chart as ChartJS, registerables } from 'chart.js';
ChartJS.register(...registerables);
const data1 = {
// not relevant
};
const minYear = 2010;
const maxYear = 2024;
const charts = ref([]);
const isPlaying = ref(false);
const currentYear = ref(minYear);
let animationFrame = null;
function updateCharts() {
charts.value.forEach(chartData => {
chartData.data = data1[currentYear.value];
});
}
function addChart(data, colors) {
const chartData = ref(data[currentYear.value]);
const chart = {
chart: null,
data: chartData,
colors: colors
};
charts.value.push(chart);
}
function playSlider() {
// not relevant
}
function handleSliderChange(value) {
if (value >= minYear && value <= maxYear && value != currentYear.value) {
currentYear.value = value;
updateCharts();
}
}
onMounted(() => {
const colors1 = ['#36A2EB', '#FF6384', '#FFCE56'];
addChart(data1, colors1);
});
</script>
<template>
<div id="main">
<div id="chartContainers" class="chart-container">
<div v-for="(chartData, index) in charts" :key="index" class="chart-wrapper">
<div class="canvas-container">
<Doughnut
:data="{ labels: ['Male', 'Female', 'NB'], datasets: [{ data: chartData.data, backgroundColor: chartData.colors }] }"
:options="{ responsive: true, maintainAspectRatio: false, animation: { animateRotate: true, animateScale: true }, plugins: { tooltip: { enabled: true } } }"
/>
</div>
</div>
</div>
<vue-slider id="yearSlider" v-model="currentYear" :min="minYear" :max="maxYear" :interval="1" @change="handleSliderChange" :disabled="isPlaying"/>
<p id="currentYear">Year: {{ currentYear }}</p>
<button id="playButton" @click="playSlider">{{ isPlaying ? 'Pause' : 'Play' }}</button>
</div>
</template>
<style>
#main {
width: 1000px;
height: 1000px;
position: absolute;
top: 0;
bottom: 100;
left: 0;
right: 0;
margin: auto;
}
.chart-container {
display: flex;
flex-wrap: wrap;
justify-content: center;
max-height: 40%;
gap: 20px;
margin: auto;
padding-top: 20px;
}
.chart-container .chart-wrapper {
flex: 1 1 45%;
max-width: 45%;
min-width: 300px;
position: relative;
}
.canvas-container {
width: 100%;
height: 40vh;
position: relative;
}
canvas {
width: 100%;
height: 100%;
}
#yearSlider {
width: 100%;
margin-top: 20px;
}
#currentYear {
text-align: center;
margin-top: 10px;
}
#playButton {
display: block;
margin: 20px auto;
padding: 10px 20px;
text-align: center;
cursor: pointer;
background-color: #4CAF50;
color: white;
border: none;
border-radius: 5px;
}
</style>
Can someone help?
Upvotes: 0
Views: 135