<?xml version="1.0" encoding="utf-8" ?>
<rss xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" xmlns:activity="http://activitystrea.ms/spec/1.0/" version="2.0">
<channel>
<title><![CDATA[Cginjs &amp;gt; C.m.A Lib &amp;gt; Canvas]]></title>
<link>http://cginjs.com/canvas</link>
<description><![CDATA[Canvas]]></description>
<language>ko</language>
<pubDate>Tue, 28 Apr 2026 02:56:34 +0900</pubDate>
<lastBuildDate>Tue, 28 Apr 2026 02:56:34 +0900</lastBuildDate>
<generator>Cginjs</generator>
<copyright><![CDATA[Cginjs]]></copyright>
<image>
<url><![CDATA[http://cginjs.com/data/common/logo_img]]></url>
<title><![CDATA[Cginjs]]></title>
<link>http://cginjs.com</link>
</image>
<item>
<author>최고관리자</author>
<title>Canvas Watermark 텍스트 X 좌표, Y 좌표, 회전각도, 투명도 컨트롤</title>
<link>http://cginjs.com/canvas/6</link>
<description><![CDATA[<pre class="prettyprint lang-css linenums notranslate pre-word-wrap">&lt;style&gt;
.watermark_ex_wrapper{position: relative; display: inline-block;padding:5px;text-align:center;}
.watermark_ex_wrapper .watermark_ex_input_box {position: relative; display: inline-block; float: left; width: 100%; padding:5px;}
.watermark_ex_wrapper .watermark_ex_input_box .div_space{position: relative; clear:both; width: 100%; height: 5px;}
.watermark_ex_wrapper .watermark_ex_input_box span{position: relative; margin:5px;}
.watermark_ex_wrapper .watermark_ex_input_box span .btn_add_watermark_ex{float: right;}
.watermark_ex_wrapper .watermark_ex_input_box span input[type='number'].frm_input{text-align:center; width:60px;}
.watermark_ex_wrapper .watermark_ex_input_box span input[type='number'].frm_ex_watermark_x{}
.watermark_ex_wrapper .watermark_ex_input_box span input[type='number'].frm_ex_watermark_y{}
.watermark_ex_wrapper .watermark_ex_input_box span input[type='color'].frm_color {width: 30px; height: 30px; border-radius: 30px; border: 1px solid #ccc; padding: 0; cursor: pointer; -webkit-appearance: none; -moz-appearance: none; appearance: none; background-color: transparent;}
.watermark_ex_wrapper .watermark_ex_input_box span input[type='color'].frm_color::-webkit-color-swatch-wrapper {padding: 2px;}
.watermark_ex_wrapper .watermark_ex_input_box span input[type='color'].frm_color::-webkit-color-swatch {border-radius: 50%;border: none;}
.watermark_ex_wrapper .watermark_ex_input_box span.frm_ex_watermark_gradient_box{position: relative; width: 100%; padding:0; margin:5px; 0;}
.watermark_ex_wrapper .watermark_ex_input_box .gradient_none{display: none;}
.watermark_ex_wrapper .watermark_ex_input_box .gradient_none.active{display: inline-block;}
.watermark_ex_wrapper .watermark_ex_input_box span.frm_ex_watermark_text_box{position: relative; display: inline-block; width: 100%; padding:0; margin:5px; 0;}
.watermark_ex_wrapper .watermark_ex_input_box span.frm_ex_watermark_text_box::after{position: absolute;top:2px;right:7px;content:""attr(data-stitle)"";display:inline-block;font-weight: normal;color:#7c7c7c;}
.watermark_ex_wrapper .watermark_ex_input_box span.frm_ex_watermark_text_box:hover::after{content:"";}
.watermark_ex_wrapper .watermark_ex_input_box .frm_ex_watermark_text_box textarea.frm_ex_watermark_text{width:100%; min-height:50px;}
&lt;/style&gt;</pre><pre class="prettyprint lang-html linenums notranslate pre-word-wrap">&lt;div class="watermark_ex_wrapper"&gt;
	&lt;img id="target_image_ex" src="/cma_img/cginjs_sample.png" alt="원본 이미지" /&gt;
	&lt;div class="watermark_ex_input_box"&gt;
		&lt;span&gt;폰트크기 : &lt;input type="number" value="30" class="frm_input frm_ex_watermark_fontsize frm_ex_watermark" min="5" placeholder="폰트크기" /&gt;&lt;/span&gt;
		&lt;span class="ex_watermark_color"&gt;&lt;font&gt;폰트색&lt;/font&gt; : &lt;input type="color" value="#ffffff" class="frm_color frm_ex_watermark_color frm_ex_watermark" min="5" placeholder="폰트색" /&gt;&lt;/span&gt;
		&lt;span&gt;
			&lt;select class="frm_input frm_ex_watermark_text_align frm_ex_watermark"&gt;
				&lt;option value=""&gt;:: 텍스트 정렬 :: &lt;/option&gt;
				&lt;option value="start"&gt;start(디폴트)&lt;/option&gt;
				&lt;option value="end"&gt;end&lt;/option&gt;
				&lt;option value="center" selected="selected"&gt;center&lt;/option&gt;
				&lt;option value="left"&gt;left&lt;/option&gt;
				&lt;option value="right"&gt;right&lt;/option&gt;
			&lt;/select&gt;
		&lt;/span&gt;
		&lt;span&gt;
			&lt;select class="frm_input frm_ex_watermark_text_baseline frm_ex_watermark"&gt;
				&lt;option value=""&gt;:: 텍스트 상하정렬 :: &lt;/option&gt;
				&lt;option value="alphabetic"&gt;alphabetic(디폴트)&lt;/option&gt;
				&lt;option value="top"&gt;top&lt;/option&gt;
				&lt;option value="hanging"&gt;hanging&lt;/option&gt;
				&lt;option value="middle" selected="selected"&gt;middle&lt;/option&gt;
				&lt;option value="ideographic"&gt;ideographic&lt;/option&gt;
				&lt;option value="bottom"&gt;bottom&lt;/option&gt;
			&lt;/select&gt;
		&lt;/span&gt;
		&lt;span&gt;
			&lt;select class="frm_input frm_ex_watermark_line_type frm_ex_watermark"&gt;
				&lt;option value=""&gt;:: 선 타입 :: &lt;/option&gt;
				&lt;option value="fill" selected="selected"&gt;채워진 텍스트&lt;/option&gt;
				&lt;option value="stroke"&gt;선 텍스트&lt;/option&gt;
			&lt;/select&gt;
		&lt;/span&gt;
		&lt;span&gt;최대 Width : &lt;input type="number" value="0" class="frm_input frm_ex_watermark_max_width frm_ex_watermark" min="0" placeholder="최대 Width" /&gt;&lt;/span&gt;
		&lt;span&gt;
			&lt;select class="frm_input frm_ex_gradient_use frm_ex_watermark"&gt;
				&lt;option value="y"&gt;그라데이션 사용(Y)&lt;/option&gt;
				&lt;option value="n" selected="selected"&gt;그라데이션 사용(N)&lt;/option&gt;
			&lt;/select&gt;
		&lt;/span&gt;
		&lt;div class="div_space gradient_none"&gt;&lt;/div&gt;
		&lt;span class="frm_ex_watermark_gradient_box gradient_none" data-stitle="그라데이션(gradient)"&gt;
			&lt;span&gt;그라데이션 Color 1&lt;/font&gt; : &lt;input type="color" value="#99ff00" class="frm_color frm_ex_watermark_gradient_color1 frm_ex_watermark" min="5" placeholder="그라데이션 Color 1" /&gt;&lt;/span&gt;
			&lt;span&gt;오프셋 1 : &lt;input type="number" value="0.0" class="frm_input frm_ex_watermark_gradient_num1 frm_ex_watermark" min="0.0" max="1.0" step="0.1" placeholder="그라데이션 오프셋 1" /&gt;&lt;/span&gt;

			&lt;span&gt;그라데이션 Color 2&lt;/font&gt; : &lt;input type="color" value="#0099ff" class="frm_color frm_ex_watermark_gradient_color2 frm_ex_watermark" min="5" placeholder="그라데이션 Color 2" /&gt;&lt;/span&gt;
			&lt;span&gt;오프셋 2 : &lt;input type="number" value="0.5" class="frm_input frm_ex_watermark_gradient_num2 frm_ex_watermark" min="0.0" max="1.0" step="0.1" placeholder="그라데이션 오프셋 2" /&gt;&lt;/span&gt;

			&lt;span&gt;그라데이션 Color 3&lt;/font&gt; : &lt;input type="color" value="#ee5155" class="frm_color frm_ex_watermark_gradient_color3 frm_ex_watermark" min="5" placeholder="그라데이션 Color 3" /&gt;&lt;/span&gt;
			&lt;span&gt;오프셋 3 : &lt;input type="number" value="1.0" class="frm_input frm_ex_watermark_gradient_num3 frm_ex_watermark" min="0.0" max="1.0" step="0.1" placeholder="그라데이션 오프셋 3" /&gt;&lt;/span&gt;
		&lt;/span&gt;
		&lt;div class="div_space"&gt;&lt;/div&gt;
		&lt;span&gt;X 좌표 : &lt;input type="number" value="0" class="frm_input frm_ex_watermark_x frm_ex_watermark" min="0" placeholder="X 좌표" /&gt;&lt;/span&gt;
		&lt;span&gt;Y 좌표 : &lt;input type="number" value="0" class="frm_input frm_ex_watermark_y frm_ex_watermark" min="0" placeholder="Y 좌표" /&gt;&lt;/span&gt;
		&lt;span&gt;회전각도 : &lt;input type="number" value="0" class="frm_input frm_ex_watermark_rotate frm_ex_watermark" min="-360" max="360" placeholder="회전각도" /&gt;&lt;/span&gt;
		&lt;span&gt;투명도 : &lt;input type="number" value="0.5" class="frm_input frm_ex_watermark_alpha frm_ex_watermark" min="0.0" max="1.0" step="0.1" placeholder="투명도(Alpha)" /&gt;&lt;/span&gt;
		&lt;span&gt;&lt;button class="btn btn_add_watermark_ex"&gt;Add Watermark&lt;/button&gt;&lt;/span&gt;
		&lt;span class="frm_ex_watermark_text_box" data-stitle="Watermark 내용"&gt;
			&lt;textarea class="frm_input frm_ex_watermark_text frm_ex_watermark" placeholder="Watermark 내용"&gt;@워터마크 Cginjs.com&lt;/textarea&gt;
		&lt;/span&gt;
	&lt;/div&gt;
	&lt;div id="output_container"&gt;&lt;/div&gt;
&lt;/div&gt;</pre><pre class="prettyprint lang-js linenums notranslate pre-word-wrap">&lt;script&gt;
function addWatermarkInputInit() {
	var imgElement = document.getElementById('target_image_ex');
	var $watermark_ex_input_box = $('.watermark_ex_wrapper .watermark_ex_input_box');

	// 진행하기 전에 두 이미지가 모두 로드되었는지 확인 (특히 동적으로 로드되는 경우)
	if (!imgElement.complete) {
		console.error("이미지가 완전히 로드되지 않았습니다.");
		return;
	}

	var img_width = imgElement.naturalWidth;
	var img_height = imgElement.naturalHeight;

	var padding = 20;
	var watermarkWidth = 100;
	var watermarkHeight = img_height * (watermarkWidth / img_height);
	var x = img_width - watermarkWidth - padding;
	var y = img_height - watermarkHeight - padding;

	$watermark_ex_input_box.find('input[type="number"].frm_ex_watermark_x').val(x - 100);
	$watermark_ex_input_box.find('input[type="number"].frm_ex_watermark_y').val(y + 50);
}

function addWatermarkToText() {
	var imgElement = document.getElementById('target_image_ex');
	var $watermark_ex_input_box = $('.watermark_ex_wrapper .watermark_ex_input_box');
	var canvas_x = parseInt( $watermark_ex_input_box.find('input[type="number"].frm_ex_watermark_x').val() ); 
	var canvas_y = parseInt( $watermark_ex_input_box.find('input[type="number"].frm_ex_watermark_y').val() ); 
	var canvas_rotate = parseInt( $watermark_ex_input_box.find('input[type="number"].frm_ex_watermark_rotate').val() ); 
	var sfontsize = parseInt( $watermark_ex_input_box.find('input[type="number"].frm_ex_watermark_fontsize').val() ); 
	var canvas_alpha = parseFloat( $watermark_ex_input_box.find('input[type="number"].frm_ex_watermark_alpha').val() ).toFixed(1); 
	var max_width = parseInt( $watermark_ex_input_box.find('input[type="number"].frm_ex_watermark_max_width').val() ).toFixed(1);
	var max_width_str = (max_width &gt; 0) ? max_width : '';
	var watermark_text = $.trim( $watermark_ex_input_box.find('textarea.frm_ex_watermark_text').val() ); 
	var font_color = $.trim( $watermark_ex_input_box.find('input[type="color"].frm_ex_watermark_color').val() ); 
	var text_align = $.trim( $watermark_ex_input_box.find('select.frm_ex_watermark_text_align').val() ); 
	text_align = text_align ? text_align : 'center';

	var text_baseline = $.trim( $watermark_ex_input_box.find('select.frm_ex_watermark_text_baseline').val() ); 
	text_baseline = text_baseline ? text_baseline : 'middle';

	var line_type = $.trim( $watermark_ex_input_box.find('select.frm_ex_watermark_line_type').val() ); // 선 타입 : fill : 채워진 텍스트, stroke : 선 텍스트
	line_type = line_type ? line_type : 'fill';

	var gradient_use = $.trim( $watermark_ex_input_box.find('select.frm_ex_gradient_use').val() ); 
	var gradient_color1 = $.trim( $watermark_ex_input_box.find('input[type="color"].frm_ex_watermark_gradient_color1').val() ); 
	var gradient_num1 = parseFloat( $watermark_ex_input_box.find('input[type="number"].frm_ex_watermark_gradient_num1').val() ).toFixed(1);
	var gradient_color2 = $.trim( $watermark_ex_input_box.find('input[type="color"].frm_ex_watermark_gradient_color2').val() ); 
	var gradient_num2 = parseFloat( $watermark_ex_input_box.find('input[type="number"].frm_ex_watermark_gradient_num2').val() ).toFixed(1);
	var gradient_color3 = $.trim( $watermark_ex_input_box.find('input[type="color"].frm_ex_watermark_gradient_color3').val() ); 
	var gradient_num3 = parseFloat( $watermark_ex_input_box.find('input[type="number"].frm_ex_watermark_gradient_num3').val() ).toFixed(1);

	// 진행하기 전에 두 이미지가 모두 로드되었는지 확인 (특히 동적으로 로드되는 경우)
	if (!imgElement.complete) {
		console.error("이미지가 완전히 로드되지 않았습니다.");
		return;
	}

	var canvas = document.createElement('canvas');
	var ctx = canvas.getContext('2d');

	// 캔버스 크기를 원본 이미지의 크기로 설정
	canvas.width = imgElement.naturalWidth;
	canvas.height = imgElement.naturalHeight;

	// 원본 이미지를 캔버스에 그리기
	ctx.drawImage(imgElement, 0, 0, canvas.width, canvas.height);

	// 워터마크 모양 사용자 지정
	ctx.font = sfontsize+'px Arial';
	ctx.textAlign = text_align; // 텍스트 정렬 : start(디폴트)|end|center|left|right
	ctx.textBaseline = text_baseline; // 상하정렬 : alphabetic(디폴트)|top|hanging|middle|ideographic|bottom

	var watermarkText = watermark_text;
	var x = canvas.width / 2;
	var y = canvas.height / 2;

	// 선택 사항: 대각선 효과를 위해 워터마크를 회전할 수 있슴
	ctx.save(); // 현재 캔버스 상태를 저장
	ctx.translate(canvas_x, canvas_y); // 원점을 중심으로 이동

	// 워터마크 회전
	var rotate_calc = ( (canvas_rotate * Math.PI) / 180 );
	ctx.rotate(rotate_calc); // 가도가 양수이면 시계반향 , 각도가 음수미염 반시계 방향으로 canvas_rotate만큼 좌표계를 기울임

	// 선택 사항: 투명도 조정(globalAlpha 값은 0~1 사이)
	ctx.globalAlpha = canvas_alpha;


	// 선형 그라데이션 객체 생성
	var gradient = ctx.createLinearGradient(0, 0, 0, 100); //그라데이션 방향 (X0, Y0, X1, Y1)

	// 그라데이션 색 추가
	gradient.addColorStop(gradient_num1, gradient_color1);
	gradient.addColorStop(gradient_num2, gradient_color2);
	gradient.addColorStop(gradient_num3, gradient_color3);

	// 텍스트 그리기
	if(line_type == 'fill') {
		ctx.fillStyle = (gradient_use == 'y') ? gradient : font_color; // 글자색
		max_width_str ? ctx.fillText(watermarkText, 0, 0, max_width_str) : ctx.fillText(watermarkText, 0, 0); // 채워진 텍스트
	} else {
		ctx.strokeStyle = (gradient_use == 'y') ? gradient : font_color; // 테두리색
		max_width_str ? ctx.strokeText(watermarkText, 0, 0, max_width_str) : ctx.strokeText(watermarkText, 0, 0); // 선 텍스트
	}


	ctx.restore(); // 캔버스의 원래 상태를 복원

	// 선택 사항: 캔버스 전체에 워터마크를 반복 표시
	// 이는 더 복잡한 논리를 필요로 하지만 기본 원리는 동일

		// --- 결과 출력 ---
	//캔버스를 이미지로 변환하여 표시하거나 다운로드
	var watermarkedImageUrl = canvas.toDataURL(); // 캔버스 콘텐츠를 데이터 URL로 변환
	var newImg = new Image();
	newImg.src = watermarkedImageUrl;
	$('#output_container').html(newImg); // 새 이미지를 DOM에 추가
}

addWatermarkInputInit();

$(function(e) {
	$(document).on('change', '.watermark_ex_wrapper .watermark_ex_input_box .frm_ex_gradient_use', function(e){ 
		var sValue = $(this).val();
		var $gradient_none = $('.watermark_ex_input_box .gradient_none');
		(sValue == 'y') ? $gradient_none.addClass('active') : $gradient_none.removeClass('active');
		
	});

	$(document).on('change', '.watermark_ex_wrapper .watermark_ex_input_box .frm_ex_watermark_line_type', function(e){ 
		var sValue = $(this).val();
		var $ex_watermark_color = $('.watermark_ex_input_box span.ex_watermark_color');
		var $ex_input = $ex_watermark_color.find('.frm_ex_watermark_color');
		var stext = (sValue == 'fill') ? '폰트색' : '테두리색';
		$ex_watermark_color.find('font').text(stext); $ex_input.attr('placeholder', stext);
	});

	$(document).on('click', '.watermark_ex_wrapper .watermark_ex_input_box .btn_add_watermark_ex', function(e){ 
		addWatermarkToText();
	});

	$(document).on('change keyup', '.watermark_ex_wrapper .watermark_ex_input_box .frm_ex_watermark', function(e){ 
		addWatermarkToText();
	});
});
&lt;/script&gt;</pre>]]></description>
<dc:creator>최고관리자</dc:creator>
<dc:language>ko</dc:language>
<dc:date>Thu, 12 Feb 2026 15:44:17 +0900</dc:date>
</item>
<item>
<author>최고관리자</author>
<title>Canvas Watermark 텍스트</title>
<link>http://cginjs.com/canvas/5</link>
<description><![CDATA[<pre class="prettyprint lang-css linenums notranslate pre-word-wrap">&lt;style&gt;
.watermark_ex_wrapper{position: relative; display: inline-block;padding:5px;text-align:center;}
.watermark_ex_wrapper .watermark_ex_input_box {position: relative; display: inline-block; float: left; width: 100%; padding:5px;}
.watermark_ex_wrapper .watermark_ex_input_box .btn_add_watermark_ex{float: right;}
&lt;/style&gt;</pre><pre class="prettyprint lang-html linenums notranslate pre-word-wrap">&lt;div class="watermark_ex_wrapper"&gt;
	&lt;img id="target_image_ex" src="/cma_img/cginjs_sample.png" alt="원본 이미지" /&gt;
	&lt;div class="watermark_ex_input_box"&gt;
		&lt;button class="btn btn_add_watermark_ex"&gt;Add Watermark&lt;/button&gt;
	&lt;/div&gt;
	&lt;div id="output_container"&gt;&lt;/div&gt;
&lt;/div&gt;</pre><pre class="prettyprint lang-js linenums notranslate pre-word-wrap">&lt;script&gt;
function addWatermarkToText() {
	var imgElement = document.getElementById('target_image_ex');
	var $watermark_ex_input_box = $('.watermark_ex_wrapper .watermark_ex_input_box');
	var canvas_x = parseInt( $watermark_ex_input_box.find('input[type="number"].frm_ex_watermark_x').val() ); 
	var canvas_y = parseInt( $watermark_ex_input_box.find('input[type="number"].frm_ex_watermark_y').val() ); 

	// 진행하기 전에 두 이미지가 모두 로드되었는지 확인 (특히 동적으로 로드되는 경우)
	if (!imgElement.complete) {
		console.error("이미지가 완전히 로드되지 않았습니다.");
		return;
	}

	var canvas = document.createElement('canvas');
	var ctx = canvas.getContext('2d');

	// 캔버스 크기를 원본 이미지의 크기로 설정
	canvas.width = imgElement.naturalWidth;
	canvas.height = imgElement.naturalHeight;

	// 원본 이미지를 캔버스에 그리기
	ctx.drawImage(imgElement, 0, 0, canvas.width, canvas.height);

	// 워터마크 모양 사용자 지정
	ctx.font = '30px Arial';
	ctx.fillStyle = 'rgba(255, 255, 255, 0.5)'; // 글자색 및 불투명도
	ctx.textAlign = 'center'; // 텍스트 정렬 : start(디폴트)|end|center|left|right
	ctx.textBaseline = 'middle'; // 상하정렬 : alphabetic(디폴트)|top|hanging|middle|ideographic|bottom

	var watermarkText = '@워터마크 Cginjs.com';
	var x = canvas.width / 2;
	var y = canvas.height / 2;

	// 선택 사항: 대각선 효과를 위해 워터마크를 회전할 수 있슴
	ctx.save(); // 현재 캔버스 상태를 저장

	//ctx.translate(x, y); // 원점을 중심으로 이동
	ctx.translate(x - 200, 100);

	// 텍스트 그리기
	ctx.fillText(watermarkText, 0, 0);

	ctx.restore(); // 캔버스의 원래 상태를 복원

	// 선택 사항: 캔버스 전체에 워터마크를 반복 표시
	// 이는 더 복잡한 논리를 필요로 하지만 기본 원리는 동일

		// --- 결과 출력 ---
	//캔버스를 이미지로 변환하여 표시하거나 다운로드
	var watermarkedImageUrl = canvas.toDataURL(); // 캔버스 콘텐츠를 데이터 URL로 변환
	var newImg = new Image();
	newImg.src = watermarkedImageUrl;
	$('#output_container').html(newImg); // 새 이미지를 DOM에 추가
}

$(function(e) {
	$(document).on('click', '.watermark_ex_wrapper .watermark_ex_input_box .btn_add_watermark_ex', function(e){ 
		addWatermarkToText();
	});
});
&lt;/script&gt;</pre><p><br /></p>]]></description>
<dc:creator>최고관리자</dc:creator>
<dc:language>ko</dc:language>
<dc:date>Thu, 12 Feb 2026 15:43:11 +0900</dc:date>
</item>
<item>
<author>최고관리자</author>
<title>Canvas Watermark 이미지 X 좌표, Y 좌표, 회전각도, 투명도 컨트롤</title>
<link>http://cginjs.com/canvas/4</link>
<description><![CDATA[<pre class="prettyprint lang-css linenums notranslate pre-word-wrap">&lt;style&gt;
.watermark_ex_wrapper{position: relative; display: inline-block;padding:5px;text-align:center;}
.watermark_ex_wrapper .watermark_ex_input_box {position: relative; display: inline-block; float: left; width: 100%; padding:5px;}
.watermark_ex_wrapper .watermark_ex_input_box .btn_add_watermark_ex{display: none;}
.watermark_ex_wrapper .watermark_ex_input_box input[type='number'].frm_input{text-align:center; width:60px; margin-right:10px;}
.watermark_ex_wrapper .watermark_ex_input_box input[type='number'].frm_ex_watermark_x{}
.watermark_ex_wrapper .watermark_ex_input_box input[type='number'].frm_ex_watermark_y{}
.watermark_ex_wrapper .watermark_ex_input_box input[type='number'].frm_ex_watermark_height{ margin:0 10px;}
.watermark_ex_wrapper .watermark_ex_input_box input[type='number']:read-only{background: #f1f1f1;}
.watermark_ex_wrapper .watermark_ex_input_box .watermark_img_size_info{position: relative; float: right;}
.watermark_ex_wrapper img#watermark_image_source_ex{display: none;}
&lt;/style&gt;</pre><pre class="prettyprint lang-html linenums notranslate pre-word-wrap">&lt;div class="watermark_ex_wrapper"&gt;
	&lt;img id="target_image_ex" src="/cma_img/cginjs_sample.png" alt="원본 이미지" /&gt;

	&lt;div class="watermark_ex_input_box"&gt;
		&lt;button class="btn btn_add_watermark_ex"&gt;Add Watermark&lt;/button&gt;
		X 좌표 : &lt;input type="number" value="0" class="frm_input frm_ex_watermark_x frm_ex_focus" min="0" placeholder="X 좌표" /&gt;
		Y 좌표 : &lt;input type="number" value="0" class="frm_input frm_ex_watermark_y frm_ex_focus" min="0" placeholder="Y 좌표" /&gt;
		회전각도 : &lt;input type="number" value="0" class="frm_input frm_ex_watermark_rotate frm_ex_focus" min="-360" max="360" placeholder="회전각도" /&gt;
		투명도 : &lt;input type="number" value="0.5" class="frm_input frm_ex_watermark_alpha frm_ex_focus" frm_ex_focus" min="0.0" max="1.0" step="0.1" placeholder="투명도(Alpha)" /&gt;

		&lt;span class="watermark_img_size_info"&gt;
			워터마크 이미지 size : 
			&lt;input type="number" value="0" class="frm_input frm_ex_watermark_width no_action" readonly="readonly" placeholder="워터마크 이미지 width" /&gt;
			x
			&lt;input type="number" value="0" class="frm_input frm_ex_watermark_height no_action" readonly="readonly" placeholder="Y 좌표" /&gt;
		&lt;/span&gt;

	&lt;/div&gt;

	&lt;div id="output_container"&gt;&lt;/div&gt;
	&lt;img id="watermark_image_source_ex" src="/data/common/logo_img" alt="워터마크 이미지" /&gt;
&lt;/div&gt;</pre><pre class="prettyprint lang-js linenums notranslate pre-word-wrap">&lt;script&gt;
function addWatermarkInputInit() {
	var imgElement = document.getElementById('target_image_ex');
	var watermarkElement = document.getElementById('watermark_image_source_ex');
	var $watermark_ex_input_box = $('.watermark_ex_wrapper .watermark_ex_input_box');

	var watermark_img_width = watermarkElement.naturalWidth;
	var watermark_img_height = watermarkElement.naturalHeight;

	var img_width = imgElement.naturalWidth;
	var img_height = imgElement.naturalHeight;

	var padding = 20;
	var watermarkWidth = 100;
	var watermarkHeight = img_height * (watermarkWidth / img_height);
	var x = img_width - watermarkWidth - padding;
	var y = img_height - watermarkHeight - padding;

	$watermark_ex_input_box.find('input[type="number"].frm_ex_watermark_x').val(x);
	$watermark_ex_input_box.find('input[type="number"].frm_ex_watermark_y').val(y);

	$watermark_ex_input_box.find('input[type="number"].frm_ex_watermark_width').val(watermark_img_width);
	$watermark_ex_input_box.find('input[type="number"].frm_ex_watermark_height').val(watermark_img_height);
}

function addWatermarkToImage() {
	var imgElement = document.getElementById('target_image_ex');
	var watermarkElement = document.getElementById('watermark_image_source_ex');
	var $watermark_ex_input_box = $('.watermark_ex_wrapper .watermark_ex_input_box');
	var canvas_x = parseInt( $watermark_ex_input_box.find('input[type="number"].frm_ex_watermark_x').val() ); 
	var canvas_y = parseInt( $watermark_ex_input_box.find('input[type="number"].frm_ex_watermark_y').val() ); 
	var canvas_rotate = parseInt( $watermark_ex_input_box.find('input[type="number"].frm_ex_watermark_rotate').val() ); 
	var canvas_alpha = parseFloat( $watermark_ex_input_box.find('input[type="number"].frm_ex_watermark_alpha').val() ).toFixed(1); 

	// 진행하기 전에 두 이미지가 모두 로드되었는지 확인 (특히 동적으로 로드되는 경우)
	if (!imgElement.complete || !watermarkElement.complete) {
		console.error("이미지가 완전히 로드되지 않았습니다.");
		return;
	}

	var canvas = document.createElement('canvas');
	var ctx = canvas.getContext('2d');

	// 캔버스 크기를 원본 이미지의 크기로 설정
	canvas.width = imgElement.naturalWidth;
	canvas.height = imgElement.naturalHeight;

	// 원본 이미지를 캔버스에 그리기
	ctx.drawImage(imgElement, 0, 0, canvas.width, canvas.height);

	// --- 워터마크 그리기 ---
	// 선택 사항: 투명도 조정(globalAlpha 값은 0~1 사이)
	ctx.globalAlpha = canvas_alpha;

	// 워터마크 회전
	var rotate_calc = ( (canvas_rotate * Math.PI) / 180 );
	ctx.rotate(rotate_calc); // 가도가 양수이면 시계반향 , 각도가 음수미염 반시계 방향으로 canvas_rotate만큼 좌표계를 기울임

	// 워터마크 위치를 정의 (예: 여백을 두고 오른쪽 하단 모서리).
	var padding = 20;
	var watermarkWidth = 100; // Adjust size as needed
	var watermarkHeight = watermarkElement.naturalHeight * (watermarkWidth / watermarkElement.naturalWidth);
	var x = canvas.width - watermarkWidth - padding;
	var y = canvas.height - watermarkHeight - padding;
	
	// 필요에 따라 크기를 조정
	ctx.drawImage(watermarkElement, canvas_x, canvas_y, watermarkWidth, watermarkHeight);

	// 선택 사항: 텍스트 워터마크를 대신 또는 추가로 추가할 수 있음.
	// ctx.globalAlpha = 0.7;
	// ctx.fillStyle = 'white';
	// ctx.font = '30px Arial';
	// ctx.fillText('My Brand Name', 50, 50);

	// --- 결과 출력 ---
	//캔버스를 이미지로 변환하여 표시하거나 다운로드
	var watermarkedImageUrl = canvas.toDataURL(); // 캔버스 콘텐츠를 데이터 URL로 변환
	var newImg = new Image();
	newImg.src = watermarkedImageUrl;
	$('#output_container').html(newImg); // 새 이미지를 DOM에 추가
}

addWatermarkInputInit();
$(function(e) {
	$(document).on('click', '.btn_add_watermark_ex', function(e){ 
		addWatermarkToImage();
	});

	$(document).on('change', '.watermark_ex_input_box input[type="number"].frm_input:not(.no_action)', function(e){ 
		addWatermarkToImage();
	});
});
&lt;/script&gt;</pre><p><br /></p>]]></description>
<dc:creator>최고관리자</dc:creator>
<dc:language>ko</dc:language>
<dc:date>Wed, 11 Feb 2026 18:19:14 +0900</dc:date>
</item>
<item>
<author>최고관리자</author>
<title>Canvas Watermark 이미지</title>
<link>http://cginjs.com/canvas/3</link>
<description><![CDATA[<pre class="prettyprint lang-css linenums notranslate pre-word-wrap">&lt;style&gt;
.btn_add_watermark_ex{margin:5px 0;}
img#watermark_image_source_ex{display: none;}
&lt;/style&gt;</pre><pre class="prettyprint lang-html linenums notranslate pre-word-wrap">&lt;img id="target_image_ex" src="/cma_img/cginjs_sample.png" alt="원본 이미지" /&gt;
&lt;button class="btn btn_add_watermark_ex"&gt;Add Watermark&lt;/button&gt;
&lt;div id="output_container"&gt;&lt;/div&gt;
&lt;img id="watermark_image_source_ex" src="/data/common/logo_img" alt="워터마크 이미지" /&gt;</pre><pre class="prettyprint lang-js linenums notranslate pre-word-wrap">&lt;script&gt;
function addWatermarkToImage() {
	var imgElement = document.getElementById('target_image_ex');
	var watermarkElement = document.getElementById('watermark_image_source_ex');
	
	// 진행하기 전에 두 이미지가 모두 로드되었는지 확인 (특히 동적으로 로드되는 경우)
	if (!imgElement.complete || !watermarkElement.complete) {
		console.error("이미지가 완전히 로드되지 않았습니다.");
		return;
	}

	var canvas = document.createElement('canvas');
	var ctx = canvas.getContext('2d');

	// 캔버스 크기를 원본 이미지의 크기로 설정
	canvas.width = imgElement.naturalWidth;
	canvas.height = imgElement.naturalHeight;

	// 원본 이미지를 캔버스에 그리기
	ctx.drawImage(imgElement, 0, 0, canvas.width, canvas.height);

	// --- 워터마크 그리기 ---
	// 선택 사항: 투명도 조정(globalAlpha 값은 0~1 사이)
	ctx.globalAlpha = 0.5;

	// 워터마크 위치를 정의 (예: 여백을 두고 오른쪽 하단 모서리).
	var padding = 20;
	var watermarkWidth = 100; // Adjust size as needed
	var watermarkHeight = watermarkElement.naturalHeight * (watermarkWidth / watermarkElement.naturalWidth);
	var x = canvas.width - watermarkWidth - padding;
	var y = canvas.height - watermarkHeight - padding;
	
	// 필요에 따라 크기를 조정
	ctx.drawImage(watermarkElement, x, y, watermarkWidth, watermarkHeight);

	// 선택 사항: 텍스트 워터마크를 대신 또는 추가로 추가할 수 있음.
	// ctx.globalAlpha = 0.7;
	// ctx.fillStyle = 'white';
	// ctx.font = '30px Arial';
	// ctx.fillText('My Brand Name', 50, 50);

	// --- 결과 출력 ---
	//캔버스를 이미지로 변환하여 표시하거나 다운로드
	var watermarkedImageUrl = canvas.toDataURL(); // 캔버스 콘텐츠를 데이터 URL로 변환
	var newImg = new Image();
	newImg.src = watermarkedImageUrl;
	$('#output_container').html(newImg); // 새 이미지를 DOM에 추가
}

$(function(e) {
	$(document).on('click', '.btn_add_watermark_ex', function(e){ 
		addWatermarkToImage();
	});
});
&lt;/script&gt;</pre><p><br /></p>]]></description>
<dc:creator>최고관리자</dc:creator>
<dc:language>ko</dc:language>
<dc:date>Wed, 11 Feb 2026 14:14:50 +0900</dc:date>
</item>
<item>
<author>최고관리자</author>
<title>Canvas 이미지 드롭 후 드롭 이미지 정보 출력</title>
<link>http://cginjs.com/canvas/2</link>
<description><![CDATA[<pre class="prettyprint lang-css linenums notranslate pre-word-wrap">&lt;style&gt;
#canvas_ex { border: 2px dashed #ccc; }
#canvas_ex.hover { border-color: #333; background-color: #f0f0f0; }
.canvas_ex_history{position: relative; clear: both; width:100%; margin:5px 0; padding:5px; font-size: 1.12em; display: none; }
.canvas_ex_history.active{display: inline-block;}
.canvas_ex_history.active img{width:40px; min-height: 30px; margin-right: 5px;}
.canvas_ex_history.active strong {color:red;}
.canvas_ex_history.active .space1 {clear: both;width: 100%;height: 1px;}
.canvas_ex_history.active .space1.gray {background:#ccc;}
.canvas_ex_history.active .space5 {clear: both;width: 100%;height: 5px;}
&lt;/style&gt;</pre><pre class="prettyprint lang-html linenums notranslate pre-word-wrap">&lt;h3&gt;이미지 파일을 캔버스에 드롭하세요&lt;/h3&gt;
&lt;div class="canvas_ex_history"&gt;&lt;/div&gt;
&lt;canvas id="canvas_ex" width="1200" height="300" class="canvas_ex"&gt;&lt;/canvas&gt;</pre><pre class="prettyprint lang-js linenums notranslate pre-word-wrap">&lt;script&gt;
$(function(e) {
	var canvas = document.getElementById('canvas_ex');
	var ctx = canvas.getContext('2d');
	var $canvas = $('#canvas_ex');
	var $canvas_ex_history = $('.canvas_ex_history'), ex_history_cnt = 0; ex_history_tag  = '';
	var new_w = 200, new_h = 200;

	// 1. 드래그 오버 (드롭 허용)
	$canvas.on('dragover', function(e) {
		e.preventDefault(); // 브라우저 기본 동작 방지
		e.stopPropagation();
		$(this).addClass('hover'); // 시각적 효과
	});

	// 2. 드래그 리브 (효과 제거)
	$canvas.on('dragleave', function(e) {
		e.preventDefault();
		e.stopPropagation();
		$(this).removeClass('hover');
	});

	// 3. 드롭 이벤트 처리
	$canvas.on('drop', function(e) {
		e.preventDefault();
		e.stopPropagation();
		$(this).removeClass('hover');

		// 드롭된 파일 가져오기
		var files = e.originalEvent.dataTransfer.files;
		if (files.length &gt; 0) {
			handleFile(e, files[0]);
		}
	});

	// 타임스탬프 값을 년월일로 변환
	function fileTimestamp(t){
		var date = new Date(t);
		var year = date.getFullYear();
		var month = "0" + (date.getMonth()+1);
		var day = "0" + date.getDate();
		var hour = "0" + date.getHours();
		var minute = "0" + date.getMinutes();
		var second = "0" + date.getSeconds();
		return year + "-" + month.substr(-2) + "-" + day.substr(-2) + " " + hour.substr(-2) + ":" + minute.substr(-2) + ":" + second.substr(-2);
	}

	// 파일 읽기 및 캔버스에 그리기
	function handleFile(e, file) {
		if (!file.type.match('image.*')) {
			alert('이미지 파일만 가능합니다.');
			return;
		}
		file['ext'] = file.name.split('.').pop().toLowerCase();
		file['width'] = 0;
		file['height'] = 0;
		file['filetime'] = fileTimestamp(file.lastModified);// 타임스탬프 값을 년월일로 변환
		file['x'] = e.offsetX;
		file['y'] = e.offsetY;

		//console.log(e);

		var reader = new FileReader();
		reader.onload = function(event) {
			var img = new Image();
			img.onload = function() {
				// 캔버스 크기 조정 (선택사항)
				// canvas.width = img.width;
				// canvas.height = img.height;
				// 이미지 그리기

				file['width'] = img.width;
				file['height'] = img.height;
				file['width_ratio'] = Math.ceil( (img.width / img.height) * new_h ); // 이미지 비율
				file['height_ratio'] = Math.ceil( (img.height / img.width) * new_w ); // 이미지 비율

				// 캔버스 중앙 계산
				var canvas_x = (canvas.width - file['width_ratio']) / 2;
				var canvas_y = (canvas.height - file['height_ratio']) / 2;

				//ctx.drawImage(img, 0, 0, img.width, img.height); // 원보 그대로
				ctx.drawImage(img, file['x'], file['y'], file['width_ratio'], file['height_ratio']); // 비율에 맞게 이미지 적용후
				console.log(file);

				ex_history_cnt++;

				var ex_history_tag = $canvas_ex_history.html();

				ex_history_tag += $canvas_ex_history.html() ? '&lt;div class="space5"&gt;&lt;/div&gt;&lt;div class="space1 gray"&gt;&lt;/div&gt;&lt;div class="space5"&gt;&lt;/div&gt;' : '';
				ex_history_tag += '&lt;img src="'+event.target.result+'" alt="" /&gt;';

				ex_history_tag += ex_history_cnt+' ) ';
				ex_history_tag += 'x : &lt;strong&gt;'+file['x']+'&lt;/strong&gt;';
				ex_history_tag += ' , y : &lt;strong&gt;'+file['y']+'&lt;/strong&gt;';
				ex_history_tag += ' , 파일명 : &lt;strong&gt;'+file['name']+'&lt;/strong&gt;';
				ex_history_tag += ' , 확장자 : &lt;strong&gt;'+file['ext']+'&lt;/strong&gt;';
				ex_history_tag += ' , 용량 : &lt;strong&gt;'+file['size'].toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")+'Byte&lt;/strong&gt;';
				ex_history_tag += ' , 크기 : &lt;strong&gt;'+file['width']+'&lt;/strong&gt; X &lt;strong&gt;'+file['height']+'&lt;/strong&gt;';
				ex_history_tag += ' , 날짜 : &lt;strong&gt;'+file['filetime']+'&lt;/strong&gt;';

				$canvas_ex_history.addClass('active');
				$canvas_ex_history.html(ex_history_tag);

			}
			img.src = event.target.result;
		}
		reader.readAsDataURL(file);
	}
});
&lt;/script&gt;</pre><p><br /></p><p><br /></p>]]></description>
<dc:creator>최고관리자</dc:creator>
<dc:language>ko</dc:language>
<dc:date>Wed, 11 Feb 2026 13:03:26 +0900</dc:date>
</item>
<item>
<author>최고관리자</author>
<title>Canvas에 텍스트 출력 드래그 해서 텍스트 위치 변경</title>
<link>http://cginjs.com/canvas/1</link>
<description><![CDATA[<p></p><pre class="prettyprint lang-html linenums notranslate pre-word-wrap">&lt;canvas id="canvas_ex" width="1200" height="300" class="canvas_ex" style="border: 1px solid #ccc;"&gt;&lt;/canvas&gt;
&lt;input type="text" id="draw_text" class="frm_input full_input frm_ex_focus" value="안녕하세요. 반갑습니다."&gt;</pre>

<p></p><pre class="prettyprint lang-js linenums notranslate pre-word-wrap">&lt;script&gt;
var canvas = document.getElementById("canvas_ex");
var ctx = canvas.getContext("2d");

// 1. 텍스트 상태
let text = {
	x: 50,
	y: 50,
	str: document.getElementById("draw_text").value,
	color: "black",
	width: 0,
	height: 20 // 폰트 크기 기반
};
let isDragging = false;
let offsetX, offsetY;

// 텍스트 크기 측정 (초기화)
ctx.font = "20px Arial";
text.width = ctx.measureText(text.str).width;

function draw() {
	var stext = document.getElementById("draw_text").value;
	ctx.clearRect(0, 0, canvas.width, canvas.height);
	ctx.fillStyle = text.color;
	ctx.font = "20px Arial";
	ctx.fillText(stext, text.x, text.y);
}

// 2. 이벤트 리스너
canvas.addEventListener('mousedown', (e) =&gt; {
	// 마우스 위치가 텍스트 영역 내에 있는지 확인
	if (e.offsetX &gt; text.x &amp;&amp; e.offsetX &lt; text.x + text.width &amp;&amp;
		e.offsetY &gt; text.y - text.height &amp;&amp; e.offsetY &lt; text.y) {
		isDragging = true;
		// 클릭한 지점과 텍스트 좌상단과의 오프셋 계산
		offsetX = e.offsetX - text.x;
		offsetY = e.offsetY - text.y;
	}
});

canvas.addEventListener('mousemove', (e) =&gt; {
	if (isDragging) {
		text.x = e.offsetX - offsetX;
		text.y = e.offsetY - offsetY;
		draw(); // 3. 재그리기
	}
});

canvas.addEventListener('mouseup', () =&gt; {
	isDragging = false;
});

draw(); // 초기 그림

document.getElementById("draw_text").addEventListener("keyup", function() {
	draw();
});

document.getElementById("draw_text").dispatchEvent(new Event("keyup"));

$(document).ready(function() {
	var canvas = document.getElementById('canvas_ex');
	var ctx = canvas.getContext('2d');

	// 드래그 영역 설정
	$('#canvas_ex').on('dragover', function(e) {
		e.preventDefault();
		e.stopPropagation();
	});

	// 드롭 이벤트 처리
	$('#canvas_ex').on('drop', function(e) {
		e.preventDefault();
		e.stopPropagation();

		var files = e.originalEvent.dataTransfer.files;
		if (files.length &gt; 0) {
			var file = files[0];
			var reader = new FileReader();

			reader.onload = function(event) {
				var img = new Image();
				img.onload = function() {
					// 드롭한 위치에 이미지 그리기 (마우스 좌표 계산 필요)
					ctx.drawImage(img, 0, 0, 200, 200); // 200x200 크기로 예시
				}
				img.src = event.target.result;
			}
			reader.readAsDataURL(file);
		}
	});
});
&lt;/script&gt;</pre>]]></description>
<dc:creator>최고관리자</dc:creator>
<dc:language>ko</dc:language>
<dc:date>Tue, 10 Feb 2026 19:18:14 +0900</dc:date>
</item>
</channel>
</rss>
