| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142 |
- <template>
- <div
- class="db--chart"
- >
- <Doughnut
- v-if="props.maxSubscriber > 0"
- :data="myData"
- :options="myOptions"
- />
- </div>
- </template>
- <script setup>
- /***********************
- * import
- ************************/
- import { Doughnut } from "vue-chartjs"
- import { Chart as ChartJS, Title, Tooltip, Legend, BarElement, LineController, LineElement, PointElement, ArcElement, CategoryScale, LinearScale } from 'chart.js';
- /***********************
- * plugins inject
- ************************/
- // props
- const props = defineProps({
- maxSubscriber: {
- type: Number,
- default: 0
- },
- curSubscriber: {
- type: Number,
- default: 0
- }
- })
- /** 차트 Cneter Text Plugin */
- 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 max = centerTextOptions.maxValue;
- const curr = centerTextOptions.currentValue;
- ctx.restore();
- const fontSize = (height / 150).toFixed(2);
- ctx.font = `${fontSize}em`;
- const text = `${curr}/${max}`;
- const textX = Math.round((width - ctx.measureText(text).width) / 2);
- const textY = height / 2 - 10;
- ctx.fillText(text, textX, textY);
- const percentText = `${fnGetPercentValue(max, curr)}%`;
- const percentTextX = Math.round((width - ctx.measureText(percentText).width) / 2);
- const percentTextY = height / 2 + 15;
- ctx.fillText(percentText, percentTextX, percentTextY);
- ctx.save();
- }
- }
- }
- };
- ChartJS.register(
- Title,
- Tooltip,
- Legend,
- BarElement,
- LineController,
- LineElement,
- PointElement,
- CategoryScale,
- ArcElement,
- LinearScale,
- centerTextPlugin
- )
- /***********************
- * data & created
- ************************/
- const chartData = ref({
- labels: ['현재 가입자 수', '남은 가입자 수'],
- datasets: [
- {
- data: [props.curSubscriber, (props.maxSubscriber - props.curSubscriber)],
- 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.curSubscriber, (props.maxSubscriber - props.curSubscriber)]
- return tempData.value
- })
- const myOptions = computed(()=>{
- const tempOptions = ref(_cloneDeep(chartOptions.value))
- tempOptions.value.plugins.centerText = {currentValue: props.curSubscriber, maxValue: props.maxSubscriber}
- return tempOptions.value
- })
- /***********************
- * Methods
- ************************/
- /** make percent data */
- const fnGetPercentValue = (max, curr) => {
- return useUtil.toRoundFix((curr / max) * 100, 0);
- }
- </script>
|