💻 다아아아 기록 개인 사이트 이동

IT SW 개발

[Highcharts] 하이차트 Ctrl+C, Ctrl+V로 문서에 복사 붙여넣기_(2)

다아아아 2026. 6. 17. 11:14

 

글이 길어서 그런가 한번에 글을 작성했더니 

로드되는데 문제가 있어 글을 2개로 나눠 작성한다.

 

블로그에 다시 정리하기 위해 테스트를 진행했고 수정한 코드는 아래와 같다. 

<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>Highcharts Ctrl+C Clipboard Demo</title>


	<script src="https://unpkg.com/highcharts/highcharts.js"></script>
	<script src="https://unpkg.com/highcharts/modules/exporting.js"></script>
	<script src="https://code.jquery.com/jquery-3.0.0.min.js"></script>

	<style>
		body {
			font-family: Arial, sans-serif;
			margin: 20px;
		}

		.chartContainer {
			border: 2px solid transparent;
			border-radius: 8px;
			padding: 10px;
		}

		.chartContainer.selected {
			border-color: #bdbdbd;
		}

		.controls {
			text-align: center;
			margin-top: 15px;
		}
	</style>
</head>

<body>

	<h2>Highcharts 12.x Ctrl+C 이미지 복사</h2>
	<p>차트를 클릭한 뒤 Ctrl+C를 누르면 PNG 이미지가 클립보드에 복사됩니다.</p>

	<div id="container" class="chartContainer"></div>

	<div class="controls">
		<select id="ChType">
			<option value="column">column</option>
			<option value="pie">pie</option>
			<option value="line">line</option>
		</select>
	</div>

	<script>
		const albumName = [
			'2Cool4School', 'O!RUL8,2', 'School Love Affair', 'Dark&Wild',
			'화양연화 pt.1', '화양연화 pt.2', 'Young Forever',
			'WINGS', 'WINGS 외전', 'Love Yourself'
		];

		const albumNum = [
			101637, 118170, 191444, 199090,
			353063, 432740, 440367,
			827947, 749954, 1376915
		];

		let chart;
		let selected = false;

		function createChart(type) {

			const seriesData = type === 'pie'
				? albumName.map((name, i) => ({
					name: name,
					y: albumNum[i]
				}))
				: albumNum;

			chart = Highcharts.chart('container', {
				chart: {
					type: type
				},

				title: {
					text: 'BTS Album Sale Rate'
				},

				subtitle: {
					text: 'Ctrl+C → PNG Clipboard Copy'
				},

				credits: {
					text: 'MTFIS'
				},

				xAxis: {
					categories: albumName
				},

				yAxis: {
					title: {
						text: '앨범 판매량'
					}
				},

				exporting: {
					enabled: true,
					local: true,
					fallbackToExportServer: false
				},

				series: [{
					name: 'Sale Rate',
					data: seriesData
				}]
			});
		}

		async function copyChartToClipboard() {

			try {

				const svg = chart.getSVG();

				const svgBlob = new Blob(
					[svg],
					{ type: 'image/svg+xml;charset=utf-8' }
				);

				const url = URL.createObjectURL(svgBlob);

				const img = new Image();

				img.onload = async function () {

					const canvas = document.createElement('canvas');

					canvas.width = img.width;
					canvas.height = img.height;

					const ctx = canvas.getContext('2d');

					ctx.drawImage(img, 0, 0);

					canvas.toBlob(async function (blob) {

						await navigator.clipboard.write([
							new ClipboardItem({
								'image/png': blob
							})
						]);

						alert('차트가 클립보드에 복사되었습니다.');

					}, 'image/png');

					URL.revokeObjectURL(url);
				};

				img.src = url;

			} catch (err) {

				console.error(err);
				alert('복사 실패: 브라우저가 이미지 클립보드를 지원하는지 확인하세요.');
			}
		}

		document.getElementById('container').addEventListener('click', function () {

			selected = true;
			this.classList.add('selected');
		});

		document.addEventListener('keydown', function (e) {

			if (selected && e.ctrlKey && e.key.toLowerCase() === 'c') {

				e.preventDefault();
				copyChartToClipboard();
			}
		});

		document.getElementById('ChType').addEventListener('change', function () {

			createChart(this.value);

			document.getElementById('container')
				.classList.remove('selected');

			selected = false;
		});

		createChart('column');
	</script>

</body>



동작은 다음과 같다.

차트 생성 → 차트 클릭 → Ctrl + C → 차트 SVG 추출 → Canvas에 그림 → PNG 변환 → 클립보드 저장 → Ctrl+V

 

지금 보면 간단한 기능이지만 개발 초창기 시절의 삽질 기록을 남긴다는 의미로 정리해본다.

개인적으로 개발 블로그에서 가장 싫어하는 것 중 하나가 예제 코드는 있는데 복사는 막아놓은 글이기 때문에
내 블로그에 올라오는 모든 예제 코드는 복사가 가능하도록 작성하고 있다.
그래도 혹시 HTML 예제 파일 자체가 필요하다는 댓글이 있다면 수정 후 파일도 함께 첨부하도록 하겠다.