| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134 |
- <template>
- <div class="db--chart">
- <doughnut
- :options="myOptions"
- :data="myData"
- />
- </div>
- </template>
- <script setup>
- import { Doughnut } from "vue-chartjs"
- import {
- Chart as ChartJS,
- Title,
- Tooltip,
- Legend,
- BarElement,
- LineController,
- LineElement,
- PointElement,
- CategoryScale,
- ArcElement,
- LinearScale,
- Filler,
- } from "chart.js"
- ChartJS.register(
- Title,
- Tooltip,
- Legend,
- BarElement,
- LineController,
- LineElement,
- PointElement,
- CategoryScale,
- ArcElement,
- LinearScale,
- Filler
- )
- // props
- const props = defineProps({
- propsChartData: {
- type: Object,
- default: function () {
- return {}
- }
- },
- propsChartOptions: {
- type: Object,
- default: function () {
- return {}
- }
- },
- })
- const centerTextPlugin = {
- id: 'centerText',
- beforeDraw(chart) {
- if(chart.config.type === 'doughnut'){
- const { width, height, ctx } = chart;
- const centerTextOptions = chart.config.options.plugins.centerText;
- if (centerTextOptions && !useUtil.isNull(centerTextOptions.currentValue) && !useUtil.isNull(centerTextOptions.maxValue)) {
- const currentValue = centerTextOptions.currentValue;
- const maxValue = centerTextOptions.maxValue;
- const percentage = Math.round((currentValue / maxValue) * 100);
- ctx.restore();
- const fontSize = (height / 150).toFixed(2);
- ctx.font = `${fontSize}em`;
- const text = `${currentValue}/${maxValue}`;
- const textX = Math.round((width - ctx.measureText(text).width) / 2);
- const textY = height / 2 - 10;
- ctx.fillText(text, textX, textY);
- const percentText = `${percentage}%`;
- const percentTextX = Math.round((width - ctx.measureText(percentText).width) / 2);
- const percentTextY = height / 2 + 15;
- ctx.fillText(percentText, percentTextX, percentTextY);
- ctx.save();
- }
- }
- }
- };
- ChartJS.register(centerTextPlugin)
- const chartData = ref({
- labels: ['현재 가입자 수', '최대 가입자 수'],
- datasets: [
- {
- data: [70,30],
- backgroundColor: ['#438dff','#EAEAEA'],
- borderWidth: 0,
- borderRadius: 200,
- }
- ]
- })
- const chartOptions = ref({
- responsive: true,
- maintainAspectRatio: false,
- cutout: '60%',
- plugins: {
- centerText: {
- currentValue: 65,
- maxValue: 100,
- },
- legend: {
- display: false
- },
- tooltip: {
- callbacks: {
- label: function(tooltipItem) {
- return tooltipItem.label + ': '+ tooltipItem.raw;// + tooltipItem.raw.toFixed(2) + '%'
- }
- }
- },
- centerText: centerTextPlugin
- }
- })
- const myData = computed(()=>{
- const tempData = ref(_cloneDeep(chartData.value))
- tempData.value.datasets[0].data = props.propsChartData
- return tempData.value
- })
- const myOptions = computed(()=>{
- const tempOptions = ref(_cloneDeep(chartOptions.value))
- tempOptions.value.plugins.centerText = props.propsChartOptions
- return tempOptions.value
- })
- </script>
|