如何在 Vue3 將 Chart.js 圖表下載成圖片

將網頁圖表輸出成圖檔也是常常被 PM 大人要求的功能,這周就來記錄一下如何在 Vue3 框架中,將 Chart.js 圖表輸出成 PNG 圖片。

圖表 DOM 元素

首先設定圖表的 DOM 元素,記得 <canvas> 裡面要加上 ref=”chartElement”。

<template>
	<main>
		<button @click="downloadChart" style="margin-bottom: 20px">切換數據</button>
		<div class="canvas-box">
			<!-- 生成圖表的 canvas -->
			<canvas ref="chartElement"></canvas>
		</div>
	</main>
</template>

圖表初始化

<script setup>
import { ref, shallowRef, computed, watch, nextTick, onMounted } from 'vue';
import Chart from 'chart.js/auto';

// 要跑圖表折線的資料陣列
const dataArray = ref([10, 20, 15, 25]);

// 取得要放圖表的 canvas 元素
const chartElement = ref(null);

// 儲存 new Chart 生成的圖表
const dataChart = shallowRef(null);

const init = (ws) => {
	dataChart.value = new Chart(chartElement.value.getContext('2d'), {
		type: 'line',
		data: {
			labels: ['鋼鐵人', '蜘蛛人', '美國隊長', '雷神'],
			datasets: [
				{
					label: '出勤次數',
					data: ws.value,
					backgroundColor: '#B7EDA1',
					borderColor: '#1BAD4F',
					borderWidth: 1,
					fill: true,
				},
			],
		},
		options: {
			responsive: true,
			maintainAspectRatio: false,
		},		
	});
};

function downloadChart() {
	// 將 Canvas 轉換為圖片
	// 取得 canvas DOM 元素  
	const chartInstance = chartElement.value;

	// 創建下載連結並觸發點擊
	const imageURL = chartInstance.toDataURL('image/png');

	// 創建下載連結並觸發點擊
	const downloadLink = document.createElement('a');
	downloadLink.href = imageURL;
	const fileName = `myFlieName.png`;
	downloadLink.download = fileName;
	downloadLink.click();
}


onMounted(() => {
	nextTick(() => {
		init(dataArray);
	});
});

下載函式

這裡要取得 canvas DOM 元素,使用 toDataURL 的方式來輸出圖片。

要注意的是 Composition API 與 Option API 的取得 DOM 的寫法不同。

Composition API 範例程式碼

function downloadChart() {
	// 將 Canvas 轉換為圖片
	// 取得 canvas DOM 元素  
	const chartInstance = chartElement.value;

	// 創建下載連結並觸發點擊
	const imageURL = chartInstance.toDataURL('image/png');

	// 創建下載連結並觸發點擊
	const downloadLink = document.createElement('a');
	downloadLink.href = imageURL;
	const fileName = `myFlieName.png`;
	downloadLink.download = fileName;
	downloadLink.click();
}

Option API 範例程式碼

downloadChart() {
        // 將 Canvas 轉換為圖片
        const chartInstance = this.$refs.chartElement.$el;

        // 創建下載連結並觸發點擊
        const imageURL = chartInstance.toDataURL("image/png");

        // 創建下載連結並觸發點擊
        const downloadLink = document.createElement("a");
        downloadLink.href = imageURL;
        const fileName = `${vm.fileName}圖.png`;
        downloadLink.download = fileName;
        downloadLink.click();
},

幫圖片加上背景

下載圖表後,我發現 PNG 圖檔的背景式透明的,在這裡要以 Chart.js plugin 的方式幫圖表加上背景顏色。

const plugin = {
	id: 'customCanvasBackgroundColor',
	beforeDraw: (chart, args, options) => {
		const { ctx } = dataChart.value;
		ctx.save();
		ctx.globalCompositeOperation = 'destination-over';
		ctx.fillStyle = options.color || '#99ffff';
		ctx.fillRect(0, 0, chart.width, chart.height);
		ctx.restore();
	},
};

在 init 函式的 new Chart 方法要加上,plugins 屬性:

const init = (ws) => {
	dataChart.value = new Chart(chartElement.value.getContext('2d'), {
		type: 'line',
		data: {
			labels: ['鋼鐵人', '蜘蛛人', '美國隊長', '雷神'],
			datasets: [
				{
					label: '出勤次數',
					data: ws.value,
					backgroundColor: '#B7EDA1',
					borderColor: '#1BAD4F',
					borderWidth: 1,
					fill: true,
				},
			],
		},
		options: {
			responsive: true,
			maintainAspectRatio: false,
		},
		// plugins 加在這裡
		plugins: [plugin],
	});
};

這樣輸出成 PNG ,就不會是透明背景了。

相關文章

Leave a Reply

Your email address will not be published. Required fields are marked *