Files
sam-kd/filedrive/view_tmpimg.php
hskwon aca1767eb9 초기 커밋: 5130 레거시 시스템
- URL 하드코딩 → .env APP_URL 기반 동적 URL로 변경
- DB 연결 하드코딩 → .env 기반으로 변경
- MySQL strict mode DATE 오류 수정
2025-12-10 20:14:31 +09:00

324 lines
10 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
$img = isset($_GET['img']) ? $_GET['img'] : '';
$rotation = isset($_GET['rotation']) ? intval($_GET['rotation']) : 0;
// 보안: tmpimg 경로만 허용
if (strpos($img, '/tmpimg/') !== 0) {
die('잘못된 접근');
}
?>
<!DOCTYPE html>
<html>
<head>
<title>이미지 보기</title>
<style>
body, html {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
overflow: hidden;
background-color: #000;
cursor: pointer;
}
.image-container {
width: 100vw;
height: 100vh;
position: relative;
overflow: hidden;
display: flex;
align-items: center;
justify-content: center;
}
.image-container img {
max-width: none;
max-height: none;
width: auto;
height: auto;
display: block;
transform: rotate(<?php echo $rotation; ?>deg);
object-fit: contain;
transition: transform 0.3s ease;
cursor: move;
}
.close-button {
position: fixed;
top: 20px;
right: 20px;
background: rgba(0, 0, 0, 0.7);
color: white;
border: none;
border-radius: 50%;
width: 40px;
height: 40px;
font-size: 20px;
cursor: pointer;
z-index: 1000;
display: flex;
align-items: center;
justify-content: center;
}
.close-button:hover {
background: rgba(0, 0, 0, 0.9);
}
.zoom-controls {
position: fixed;
top: 20px;
left: 20px;
display: flex;
gap: 10px;
z-index: 1000;
}
.zoom-button {
background: rgba(0, 0, 0, 0.7);
color: white;
border: none;
border-radius: 50%;
width: 40px;
height: 40px;
font-size: 18px;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
transition: background 0.3s ease;
}
.zoom-button:hover {
background: rgba(0, 0, 0, 0.9);
}
.zoom-button:disabled {
opacity: 0.5;
cursor: not-allowed;
}
.reset-button {
background: rgba(0, 0, 0, 0.7);
color: white;
border: none;
border-radius: 20px;
padding: 8px 16px;
font-size: 14px;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
transition: background 0.3s ease;
}
.reset-button:hover {
background: rgba(0, 0, 0, 0.9);
}
.loading {
color: white;
font-size: 18px;
text-align: center;
}
.error {
color: #ff6b6b;
font-size: 18px;
text-align: center;
padding: 20px;
}
.zoom-info {
position: fixed;
bottom: 20px;
left: 20px;
background: rgba(0, 0, 0, 0.7);
color: white;
padding: 8px 12px;
border-radius: 20px;
font-size: 14px;
z-index: 1000;
}
</style>
</head>
<body>
<button class="close-button" onclick="closeWindow()" title="닫기 (ESC)">×</button>
<div class="zoom-controls">
<button class="zoom-button" onclick="zoomIn()" title="확대 (Ctrl + +)">+</button>
<button class="zoom-button" onclick="zoomOut()" title="축소 (Ctrl + -)"></button>
<button class="reset-button" onclick="resetZoom()" title="원본 크기 (Ctrl + 0)">원본</button>
</div>
<div class="zoom-info" id="zoomInfo">100%</div>
<div class="image-container">
<img src="<?php echo htmlspecialchars($img); ?>" alt="이미지" id="popupImage" style="display: none;">
<div id="loadingMessage" class="loading">이미지를 불러오는 중...</div>
<div id="errorMessage" class="error" style="display: none;">이미지를 불러올 수 없습니다.</div>
</div>
<script>
let currentZoom = 1;
let isDragging = false;
let startX, startY, translateX = 0, translateY = 0;
const MIN_ZOOM = 0.1;
const MAX_ZOOM = 5;
const ZOOM_STEP = 0.2;
// 창 닫기 함수
function closeWindow() {
window.close();
}
// 줌 인
function zoomIn() {
if (currentZoom < MAX_ZOOM) {
currentZoom = Math.min(currentZoom + ZOOM_STEP, MAX_ZOOM);
updateZoom();
}
}
// 줌 아웃
function zoomOut() {
if (currentZoom > MIN_ZOOM) {
currentZoom = Math.max(currentZoom - ZOOM_STEP, MIN_ZOOM);
updateZoom();
}
}
// 줌 리셋
function resetZoom() {
currentZoom = 1;
translateX = 0;
translateY = 0;
updateZoom();
}
// 줌 업데이트
function updateZoom() {
const img = document.getElementById('popupImage');
const zoomInfo = document.getElementById('zoomInfo');
const zoomInBtn = document.querySelector('.zoom-button:first-child');
const zoomOutBtn = document.querySelector('.zoom-button:nth-child(2)');
// 회전, 확대/축소, 이동을 모두 적용
img.style.transform = `rotate(<?php echo $rotation; ?>deg) scale(${currentZoom}) translate(${translateX}px, ${translateY}px)`;
zoomInfo.textContent = Math.round(currentZoom * 100) + '%';
// 버튼 활성화/비활성화
zoomInBtn.disabled = currentZoom >= MAX_ZOOM;
zoomOutBtn.disabled = currentZoom <= MIN_ZOOM;
}
// 마우스 드래그 시작
function startDrag(e) {
if (currentZoom > 1) {
isDragging = true;
startX = e.clientX - translateX;
startY = e.clientY - translateY;
document.body.style.cursor = 'grabbing';
e.preventDefault();
}
}
// 마우스 드래그 중
function drag(e) {
if (isDragging) {
translateX = e.clientX - startX;
translateY = e.clientY - startY;
updateZoom();
e.preventDefault();
}
}
// 마우스 드래그 종료
function endDrag() {
isDragging = false;
document.body.style.cursor = 'pointer';
}
// 이미지 로딩이 완료되면 실행될 함수
function onImageLoad() {
// 로딩 메시지 숨기기
document.getElementById('loadingMessage').style.display = 'none';
// 이미지 표시
document.getElementById('popupImage').style.display = 'block';
// 이 창을 연 부모 창(opener)이 있고, 닫히지 않았는지 확인
if (window.opener && !window.opener.closed) {
// 부모 창에 hideImageLoadingModal 함수가 있는지 확인하고 호출
if (typeof window.opener.hideImageLoadingModal === 'function') {
window.opener.hideImageLoadingModal();
}
}
}
// 이미지 로딩 실패 시 실행될 함수
function onImageError() {
// 로딩 메시지 숨기기
document.getElementById('loadingMessage').style.display = 'none';
// 에러 메시지 표시
document.getElementById('errorMessage').style.display = 'block';
// 부모 창의 로딩 모달도 숨기기
if (window.opener && !window.opener.closed) {
if (typeof window.opener.hideImageLoadingModal === 'function') {
window.opener.hideImageLoadingModal();
}
}
}
const imgElement = document.getElementById('popupImage');
// 이미지의 load 이벤트에 리스너 추가
imgElement.addEventListener('load', onImageLoad);
imgElement.addEventListener('error', onImageError);
// 만약 이미지가 이미 캐시되어 있다면 'load' 이벤트가 발생하지 않을 수 있으므로,
// complete 속성을 확인하여 수동으로 함수를 호출합니다.
if (imgElement.complete) {
if (imgElement.naturalWidth > 0) {
onImageLoad();
} else {
onImageError();
}
}
// 마우스 이벤트 리스너 추가
imgElement.addEventListener('mousedown', startDrag);
document.addEventListener('mousemove', drag);
document.addEventListener('mouseup', endDrag);
// 휠 줌 기능 (이미지 위에서만)
imgElement.addEventListener('wheel', function(e) {
e.preventDefault();
if (e.deltaY < 0) {
zoomIn();
} else {
zoomOut();
}
});
// 키보드 단축키
document.addEventListener('keydown', function(event) {
if (event.key === 'Escape') {
closeWindow();
} else if (event.ctrlKey || event.metaKey) {
switch(event.key) {
case '=':
case '+':
event.preventDefault();
zoomIn();
break;
case '-':
event.preventDefault();
zoomOut();
break;
case '0':
event.preventDefault();
resetZoom();
break;
}
}
});
// 배경 클릭으로 창 닫기 (줌이 1일 때만)
document.addEventListener('click', function(event) {
if (currentZoom <= 1 && (event.target === document.body || event.target.classList.contains('image-container'))) {
closeWindow();
}
});
</script>
</body>
</html>