262 lines
8.8 KiB
JavaScript
262 lines
8.8 KiB
JavaScript
//===============================================================================
|
|
// #region Fabric.js 캔버스 텍스트 및 이미지 삽입 관련 이벤트 및 함수
|
|
//===============================================================================
|
|
|
|
/** 이미지 업로드 변경 이벤트: 선택한 이미지를 Fabric 캔버스에 추가 */
|
|
$('#canvas-image-upload').change(function (event) {
|
|
const files = event.target.files;
|
|
for (let i = 0; i < files.length; i++) {
|
|
const file = files[i];
|
|
if (file.type.startsWith('image/')) {
|
|
const reader = new FileReader();
|
|
reader.onload = function (e) {
|
|
fabric.Image.fromURL(e.target.result, function (img) {
|
|
// 이미지 중앙 배치 및 캔버스에 추가
|
|
img.set({
|
|
left: fabricCanvas.width / 2 - img.width / 2,
|
|
top: fabricCanvas.height / 2 - img.height / 2,
|
|
selectable: true
|
|
});
|
|
fabricCanvas.add(img);
|
|
fabricCanvas.renderAll();
|
|
});
|
|
}
|
|
reader.readAsDataURL(file);
|
|
} else {
|
|
alert('이미지 파일을 선택해주세요.');
|
|
}
|
|
}
|
|
// 파일 입력 초기화
|
|
$('#canvas-image-upload').val('');
|
|
});
|
|
|
|
/** 텍스트 삽입 버튼 클릭 이벤트: 사용자 입력 텍스트를 Fabric 캔버스에 IText 객체로 추가 */
|
|
$('#canvas-insert-text-btn').click(function () {
|
|
const text = prompt("추가할 텍스트를 입력하세요:", "새 텍스트");
|
|
if (text) {
|
|
const itext = new fabric.IText(text, {
|
|
left: fabricCanvas.width / 2,
|
|
top: fabricCanvas.height / 2,
|
|
fontSize: 20,
|
|
fill: '#000000',
|
|
selectable: true,
|
|
objectCaching: false
|
|
});
|
|
fabricCanvas.add(itext);
|
|
fabricCanvas.setActiveObject(itext);
|
|
}
|
|
});
|
|
|
|
/** 공용 함수: 부분 선택이 있으면 부분만, 없으면 전체 텍스트에 스타일 토글 */
|
|
function toggleCanvasTextStyle(styleName, toggleValues) {
|
|
const activeObject = fabricCanvas.getActiveObject();
|
|
if (!activeObject || activeObject.type !== 'i-text') return;
|
|
|
|
// 선택 범위 가져오기
|
|
const start = activeObject.selectionStart;
|
|
const end = activeObject.selectionEnd;
|
|
|
|
// 전체 텍스트에 적용하는 경우
|
|
if (start === end) {
|
|
const current = activeObject[styleName];
|
|
// 현재 스타일값을 토글
|
|
const newVal = (current === toggleValues[0]) ? toggleValues[1] : toggleValues[0];
|
|
activeObject.set(styleName, newVal);
|
|
} else {
|
|
// 부분 선택이 있는 경우
|
|
const currentStyles = activeObject.getSelectionStyles(start, end);
|
|
let allSame = true;
|
|
for (let i = 0; i < currentStyles.length; i++) {
|
|
if (currentStyles[i][styleName] !== toggleValues[0]) {
|
|
allSame = false;
|
|
break;
|
|
}
|
|
}
|
|
// 스타일 토글 값 결정
|
|
const newVal = allSame ? toggleValues[1] : toggleValues[0];
|
|
activeObject.setSelectionStyles({
|
|
[styleName]: newVal
|
|
}, start, end);
|
|
}
|
|
fabricCanvas.renderAll();
|
|
}
|
|
|
|
/** 캔버스 굵게 버튼 클릭 이벤트 */
|
|
$('#canvas-bold-btn').click(function () {
|
|
// fontWeight를 'bold' <-> 'normal' 로 토글
|
|
toggleCanvasTextStyle('fontWeight', ['bold', 'normal']);
|
|
});
|
|
|
|
/** 캔버스 기울임 버튼 클릭 이벤트 */
|
|
$('#canvas-italic-btn').click(function () {
|
|
// fontStyle을 'italic' <-> 'normal' 로 토글
|
|
toggleCanvasTextStyle('fontStyle', ['italic', 'normal']);
|
|
});
|
|
|
|
/** 캔버스 밑줄 버튼 클릭 이벤트 */
|
|
$('#canvas-underline-btn').click(function () {
|
|
const activeObject = fabricCanvas.getActiveObject();
|
|
if (!activeObject || activeObject.type !== 'i-text') return;
|
|
|
|
const start = activeObject.selectionStart;
|
|
const end = activeObject.selectionEnd;
|
|
if (start === end) {
|
|
// 전체 텍스트 밑줄 토글
|
|
activeObject.set('underline', !activeObject.get('underline'));
|
|
} else {
|
|
// 부분 선택 영역에 대해 밑줄 토글
|
|
const currentStyles = activeObject.getSelectionStyles(start, end);
|
|
let allUnderlined = true;
|
|
for (let i = 0; i < currentStyles.length; i++) {
|
|
if (!currentStyles[i].underline) {
|
|
allUnderlined = false;
|
|
break;
|
|
}
|
|
}
|
|
const newVal = !allUnderlined;
|
|
activeObject.setSelectionStyles({
|
|
underline: newVal
|
|
}, start, end);
|
|
}
|
|
fabricCanvas.renderAll();
|
|
});
|
|
|
|
/** 캔버스 텍스트 색상 변경 이벤트 */
|
|
$('#canvas-text-color-picker').on('input', function () {
|
|
const color = $(this).val();
|
|
applyCanvasTextColor(color);
|
|
});
|
|
|
|
/** 캔버스 글자 크기 변경 이벤트: 직접 입력된 값 적용 */
|
|
$('#canvas-font-size-btn').change(function () {
|
|
const fontSize = parseInt($(this).val(), 10);
|
|
const activeObject = fabricCanvas.getActiveObject();
|
|
if (activeObject && activeObject.type === 'i-text') {
|
|
activeObject.set('fontSize', fontSize);
|
|
fabricCanvas.renderAll();
|
|
}
|
|
});
|
|
|
|
/** 펜 설정 토글 버튼 클릭 이벤트 (옵션 예시) */
|
|
$('#pen-settings-btn').click(function () {
|
|
$('#pen-settings').toggle();
|
|
});
|
|
|
|
/** 펜 색상 변경 이벤트 */
|
|
$('#pen-color-picker').change(function () {
|
|
if (fabricCanvas.isDrawingMode) {
|
|
fabricCanvas.freeDrawingBrush.color = $(this).val();
|
|
}
|
|
});
|
|
|
|
/** 펜 두께 변경 이벤트 */
|
|
$('#pen-thickness').change(function () {
|
|
if (fabricCanvas.isDrawingMode) {
|
|
fabricCanvas.freeDrawingBrush.width = parseInt($(this).val(), 10) || 2;
|
|
}
|
|
});
|
|
|
|
/** 드로잉 모드 토글 버튼 클릭 이벤트 */
|
|
$('#toggle-draw-btn').click(function () {
|
|
if (fabricCanvas) {
|
|
isDrawingMode = !isDrawingMode;
|
|
fabricCanvas.isDrawingMode = isDrawingMode;
|
|
if (isDrawingMode) {
|
|
$(this).addClass('on');
|
|
$('#pen-settings').show();
|
|
// 새로운 PencilBrush 설정 및 기본 속성 적용
|
|
fabricCanvas.freeDrawingBrush = new fabric.PencilBrush(fabricCanvas);
|
|
fabricCanvas.freeDrawingBrush.color = $('#pen-color-picker').val();
|
|
fabricCanvas.freeDrawingBrush.width = parseInt($('#pen-thickness').val(), 10) || 2;
|
|
fabricCanvas.freeDrawingCursor = 'url("image/svg/pen-btn.svg") 3 15, auto';
|
|
console.log('드로잉 모드 활성');
|
|
} else {
|
|
$(this).removeClass('on');
|
|
$('#pen-settings').hide();
|
|
fabricCanvas.freeDrawingCursor = 'default';
|
|
console.log('드로잉 비활성');
|
|
}
|
|
}
|
|
});
|
|
|
|
/** 캔버스 이미지 삽입 버튼 클릭 이벤트: 이미지 업로드 창 트리거 */
|
|
$('#canvas-insert-image-btn').click(function () {
|
|
$('#canvas-image-upload').click();
|
|
});
|
|
|
|
/** 캔버스 텍스트 색상 적용 함수 */
|
|
function applyCanvasTextColor(color) {
|
|
const obj = fabricCanvas.getActiveObject();
|
|
if (!obj || obj.type !== 'i-text') return;
|
|
|
|
const s = obj.selectionStart;
|
|
const e = obj.selectionEnd;
|
|
|
|
if (s < e) {
|
|
// 부분 선택 구간만 색상 변경
|
|
obj.setSelectionStyles({
|
|
fill: color
|
|
}, s, e);
|
|
} else {
|
|
// 전체 텍스트 색상 변경
|
|
obj.set('fill', color);
|
|
}
|
|
|
|
// 즉시 반영
|
|
obj.dirty = true;
|
|
obj.setCoords();
|
|
fabricCanvas.renderAll();
|
|
}
|
|
|
|
/** 캔버스 텍스트 배경색 변경 함수 */
|
|
function applyCanvasBackgroundColor(color) {
|
|
const obj = fabricCanvas.getActiveObject();
|
|
if (!obj || obj.type !== 'i-text') return;
|
|
|
|
const s = obj.selectionStart;
|
|
const e = obj.selectionEnd;
|
|
|
|
if (s < e) {
|
|
// 부분 선택 구간만 배경색 변경
|
|
obj.setSelectionStyles({
|
|
backgroundColor: color
|
|
}, s, e);
|
|
} else {
|
|
// 전체 텍스트 배경색 변경
|
|
obj.set('backgroundColor', color);
|
|
}
|
|
|
|
// 즉시 반영
|
|
obj.dirty = true;
|
|
obj.setCoords();
|
|
fabricCanvas.renderAll();
|
|
}
|
|
|
|
/** 캔버스 폰트 크기 적용 함수 */
|
|
function applyCanvasFontSize(fontSize) {
|
|
const obj = fabricCanvas.getActiveObject();
|
|
if (!obj || obj.type !== 'i-text') return;
|
|
|
|
const s = obj.selectionStart;
|
|
const e = obj.selectionEnd;
|
|
|
|
if (s < e) {
|
|
// 부분 선택 구간만 폰트 크기 변경
|
|
obj.setSelectionStyles({
|
|
fontSize: fontSize
|
|
}, s, e);
|
|
} else {
|
|
// 전체 텍스트 폰트 크기 변경
|
|
obj.set('fontSize', fontSize);
|
|
}
|
|
|
|
// 즉시 반영
|
|
obj.dirty = true;
|
|
obj.setCoords();
|
|
fabricCanvas.renderAll();
|
|
}
|
|
|
|
//===============================================================================
|
|
// #endregion Fabric.js 캔버스 텍스트 및 이미지 삽입 관련
|
|
//===============================================================================
|