|
<!DOCTYPE html> |
|
<html lang="ja"> |
|
<head> |
|
<meta charset="UTF-8"> |
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
|
<title>画像編集ツール</title> |
|
<style> |
|
body { |
|
font-family: Arial, sans-serif; |
|
margin: 0; |
|
padding: 0; |
|
overflow: hidden; |
|
height: 100vh; |
|
--bg-color: #f0f0f0; |
|
} |
|
#preview-container { |
|
position: fixed; |
|
top: 0; |
|
left: 0; |
|
width: 100%; |
|
height: 100%; |
|
background-color: var(--bg-color); |
|
overflow: hidden; |
|
position: relative; |
|
} |
|
#preview-image { |
|
position: absolute; |
|
cursor: move; |
|
transform-origin: center center; |
|
display: none; |
|
} |
|
.control-point { |
|
position: absolute; |
|
width: 10px; |
|
height: 10px; |
|
background-color: #4285f4; |
|
border-radius: 50%; |
|
cursor: pointer; |
|
z-index: 10; |
|
display: none; |
|
} |
|
.rotate-handle { |
|
position: absolute; |
|
width: 30px; |
|
height: 30px; |
|
background-color: #4285f4; |
|
color: white; |
|
border-radius: 50%; |
|
display: none; |
|
align-items: center; |
|
justify-content: center; |
|
font-size: 18px; |
|
cursor: pointer; |
|
z-index: 10; |
|
font-family: sans-serif; |
|
transform: translate(-20%, 0%); |
|
} |
|
.settings-panel { |
|
position: fixed; |
|
top: 20px; |
|
right: 20px; |
|
width: 300px; |
|
background-color: white; |
|
border-radius: 8px; |
|
box-shadow: 0 0 15px rgba(0,0,0,0.2); |
|
z-index: 100; |
|
overflow: hidden; |
|
} |
|
.panel-header { |
|
padding: 10px 15px; |
|
background-color: #4285f4; |
|
color: white; |
|
cursor: move; |
|
display: flex; |
|
justify-content: space-between; |
|
align-items: center; |
|
} |
|
.panel-title { |
|
font-weight: bold; |
|
} |
|
.toggle-panel { |
|
background: none; |
|
border: none; |
|
color: white; |
|
font-size: 16px; |
|
cursor: pointer; |
|
} |
|
.panel-content { |
|
padding: 15px; |
|
transition: all 0.3s ease; |
|
} |
|
.panel-collapsed .panel-content { |
|
display: none; |
|
} |
|
.form-group { |
|
display: flex; |
|
margin-bottom: 15px; |
|
align-items: center; |
|
} |
|
.form-group label { |
|
width: 80px; |
|
font-weight: bold; |
|
} |
|
.form-group input { |
|
width: 70px; |
|
padding: 5px; |
|
margin-right: 10px; |
|
} |
|
button { |
|
padding: 8px 15px; |
|
background-color: #4285f4; |
|
color: white; |
|
border: none; |
|
border-radius: 4px; |
|
cursor: pointer; |
|
font-size: 14px; |
|
margin-right: 5px; |
|
} |
|
button:hover { |
|
background-color: #3367d6; |
|
} |
|
.upload-section { |
|
margin-bottom: 20px; |
|
padding: 15px; |
|
border: 2px dashed #ccc; |
|
border-radius: 8px; |
|
text-align: center; |
|
} |
|
.fullscreen-mode { |
|
position: fixed; |
|
top: 0; |
|
left: 0; |
|
width: 100%; |
|
height: 100%; |
|
background-color: inherit; |
|
z-index: 1000; |
|
cursor: none !important; |
|
} |
|
.close-fullscreen { |
|
position: fixed; |
|
top: 20px; |
|
right: 20px; |
|
color: #333; |
|
font-size: 30px; |
|
cursor: pointer; |
|
z-index: 1001; |
|
background-color: rgba(255,255,255,0.7); |
|
width: 40px; |
|
height: 40px; |
|
border-radius: 50%; |
|
display: flex; |
|
align-items: center; |
|
justify-content: center; |
|
box-shadow: 0 0 5px rgba(0,0,0,0.2); |
|
} |
|
.color-picker { |
|
display: flex; |
|
align-items: center; |
|
margin-bottom: 15px; |
|
} |
|
.color-picker label { |
|
width: 80px; |
|
font-weight: bold; |
|
} |
|
.color-picker input { |
|
width: 60px; |
|
height: 30px; |
|
padding: 0; |
|
border: 1px solid #ddd; |
|
} |
|
.hidden { |
|
display: none !important; |
|
} |
|
.flip-buttons { |
|
display: flex; |
|
margin-bottom: 15px; |
|
} |
|
.flip-buttons button { |
|
flex: 1; |
|
} |
|
.pointer-lock { |
|
cursor: none !important; |
|
} |
|
</style> |
|
</head> |
|
<body> |
|
<div id="preview-container"> |
|
<img id="preview-image" style="-webkit-user-drag: none;"> |
|
<div class="rotate-handle" id="rotate-handle">↺</div> |
|
|
|
</div> |
|
|
|
<div class="settings-panel" id="settings-panel"> |
|
<div class="panel-header" id="panel-header"> |
|
<span class="panel-title">画像設定</span> |
|
<button class="toggle-panel" id="toggle-panel">−</button> |
|
</div> |
|
<div class="panel-content"> |
|
<div class="upload-section"> |
|
<input type="file" id="image-upload" accept="image/*"> |
|
<p>画像をドラッグ&ドロップ</p> |
|
</div> |
|
|
|
<div class="color-picker"> |
|
<label>背景色:</label> |
|
<input type="color" id="bg-color" value="#f0f0f0"> |
|
</div> |
|
|
|
<div class="form-group"> |
|
<label>X位置:</label> |
|
<input type="number" id="pos-x"> |
|
<label>Y位置:</label> |
|
<input type="number" id="pos-y"> |
|
</div> |
|
<div class="form-group"> |
|
<label>幅:</label> |
|
<input type="number" id="width"> |
|
<label>高さ:</label> |
|
<input type="number" id="height"> |
|
</div> |
|
<div class="form-group"> |
|
<label>回転:</label> |
|
<input type="number" id="rotation" value="0"> |
|
<span>度</span> |
|
</div> |
|
|
|
<div class="flip-buttons"> |
|
<button id="flip-horizontal">左右反転</button> |
|
<button id="flip-vertical">上下反転</button> |
|
</div> |
|
|
|
<button id="ok-button">全画面表示</button> |
|
</div> |
|
</div> |
|
|
|
<script> |
|
document.addEventListener('DOMContentLoaded', function() { |
|
const uploadInput = document.getElementById('image-upload'); |
|
const previewContainer = document.getElementById('preview-container'); |
|
const previewImage = document.getElementById('preview-image'); |
|
const rotateHandle = document.getElementById('rotate-handle'); |
|
const posXInput = document.getElementById('pos-x'); |
|
const posYInput = document.getElementById('pos-y'); |
|
const widthInput = document.getElementById('width'); |
|
const heightInput = document.getElementById('height'); |
|
const rotationInput = document.getElementById('rotation'); |
|
const okButton = document.getElementById('ok-button'); |
|
const bgColorInput = document.getElementById('bg-color'); |
|
const flipHorizontalBtn = document.getElementById('flip-horizontal'); |
|
const flipVerticalBtn = document.getElementById('flip-vertical'); |
|
const settingsPanel = document.getElementById('settings-panel'); |
|
const panelHeader = document.getElementById('panel-header'); |
|
const togglePanel = document.getElementById('toggle-panel'); |
|
|
|
let isDragging = false; |
|
let activeControlPoint = null; |
|
let isRotating = false; |
|
let isDraggingPanel = false; |
|
let startX, startY; |
|
let startWidth, startHeight; |
|
let startRotation; |
|
let startImageX, startImageY; |
|
let startPanelX, startPanelY; |
|
let aspectRatio = 1; |
|
let isFullscreen = false; |
|
let scaleX = 1; |
|
let scaleY = 1; |
|
|
|
|
|
bgColorInput.addEventListener('input', function() { |
|
const bgColor = this.value; |
|
previewContainer.style.backgroundColor = bgColor; |
|
document.documentElement.style.setProperty('--bg-color', bgColor); |
|
}); |
|
|
|
|
|
const ControlPointType = { |
|
TOP_LEFT: 'top-left', |
|
TOP_CENTER: 'top-center', |
|
TOP_RIGHT: 'top-right', |
|
MIDDLE_LEFT: 'middle-left', |
|
MIDDLE_RIGHT: 'middle-right', |
|
BOTTOM_LEFT: 'bottom-left', |
|
BOTTOM_CENTER: 'bottom-center', |
|
BOTTOM_RIGHT: 'bottom-right' |
|
}; |
|
|
|
|
|
uploadInput.addEventListener('change', handleImageUpload); |
|
previewContainer.addEventListener('dragover', function(e) { |
|
e.preventDefault(); |
|
e.stopPropagation(); |
|
previewContainer.style.backgroundColor = '#e0e0e0'; |
|
}); |
|
previewContainer.addEventListener('dragleave', function(e) { |
|
e.preventDefault(); |
|
e.stopPropagation(); |
|
previewContainer.style.backgroundColor = bgColorInput.value; |
|
}); |
|
previewContainer.addEventListener('drop', function(e) { |
|
e.preventDefault(); |
|
e.stopPropagation(); |
|
previewContainer.style.backgroundColor = bgColorInput.value; |
|
if (e.dataTransfer.files.length) { |
|
uploadInput.files = e.dataTransfer.files; |
|
handleImageUpload(); |
|
} |
|
}); |
|
|
|
function handleImageUpload() { |
|
const file = uploadInput.files[0]; |
|
if (!file) return; |
|
|
|
const reader = new FileReader(); |
|
reader.onload = function(e) { |
|
previewImage.src = e.target.result; |
|
previewImage.style.display = 'block'; |
|
rotateHandle.style.display = 'block'; |
|
|
|
previewImage.onload = function() { |
|
|
|
const containerWidth = previewContainer.clientWidth; |
|
const containerHeight = previewContainer.clientHeight; |
|
const imgWidth = previewImage.naturalWidth; |
|
const imgHeight = previewImage.naturalHeight; |
|
|
|
aspectRatio = imgWidth / imgHeight; |
|
|
|
|
|
let initWidth = Math.min(imgWidth, containerWidth * 0.8); |
|
let initHeight = initWidth / aspectRatio; |
|
|
|
if (initHeight > containerHeight * 0.8) { |
|
initHeight = containerHeight * 0.8; |
|
initWidth = initHeight * aspectRatio; |
|
} |
|
|
|
|
|
const initX = (containerWidth - initWidth) / 2; |
|
const initY = (containerHeight - initHeight) / 2; |
|
|
|
updateImageStyle(initX, initY, initWidth, initHeight, 0); |
|
updateFormInputs(initX, initY, initWidth, initHeight, 0); |
|
createControlPoints(); |
|
|
|
|
|
document.querySelectorAll('.control-point').forEach(point => { |
|
point.style.display = 'block'; |
|
}); |
|
}; |
|
}; |
|
reader.readAsDataURL(file); |
|
} |
|
|
|
|
|
function createControlPoints() { |
|
|
|
document.querySelectorAll('.control-point').forEach(el => el.remove()); |
|
|
|
|
|
const positions = [ |
|
{ type: ControlPointType.TOP_LEFT, left: 0, top: 0 }, |
|
{ type: ControlPointType.TOP_CENTER, left: 50, top: 0 }, |
|
{ type: ControlPointType.TOP_RIGHT, left: 100, top: 0 }, |
|
{ type: ControlPointType.MIDDLE_LEFT, left: 0, top: 50 }, |
|
{ type: ControlPointType.MIDDLE_RIGHT, left: 100, top: 50 }, |
|
{ type: ControlPointType.BOTTOM_LEFT, left: 0, top: 100 }, |
|
{ type: ControlPointType.BOTTOM_CENTER, left: 50, top: 100 }, |
|
{ type: ControlPointType.BOTTOM_RIGHT, left: 100, top: 100 } |
|
]; |
|
|
|
positions.forEach(pos => { |
|
const point = document.createElement('div'); |
|
point.className = 'control-point'; |
|
point.dataset.type = pos.type; |
|
point.style.display = 'none'; |
|
|
|
|
|
point.style.left = `calc(${pos.left}% - 5px)`; |
|
point.style.top = `calc(${pos.top}% - 5px)`; |
|
|
|
|
|
point.addEventListener('mousedown', startControlPointDrag); |
|
|
|
previewImage.parentNode.appendChild(point); |
|
}); |
|
} |
|
|
|
|
|
function updateImageStyle(x, y, width, height, rotation) { |
|
previewImage.style.left = `${x}px`; |
|
previewImage.style.top = `${y}px`; |
|
previewImage.style.width = `${width}px`; |
|
previewImage.style.height = `${height}px`; |
|
previewImage.style.transform = `rotate(${rotation}deg) scaleX(${scaleX}) scaleY(${scaleY})`; |
|
|
|
|
|
const rotateX = x + width / 2 - 15; |
|
const rotateY = y - 40; |
|
rotateHandle.style.left = `${rotateX}px`; |
|
rotateHandle.style.top = `${rotateY}px`; |
|
|
|
|
|
updateControlPointsPosition(x, y, width, height, rotation); |
|
} |
|
|
|
|
|
function updateControlPointsPosition(x, y, width, height, rotation) { |
|
const points = document.querySelectorAll('.control-point'); |
|
const centerX = x + width / 2; |
|
const centerY = y + height / 2; |
|
|
|
points.forEach(point => { |
|
const type = point.dataset.type; |
|
let pointX, pointY; |
|
|
|
switch(type) { |
|
case ControlPointType.TOP_LEFT: |
|
pointX = x; |
|
pointY = y; |
|
break; |
|
case ControlPointType.TOP_CENTER: |
|
pointX = centerX - 5; |
|
pointY = y; |
|
break; |
|
case ControlPointType.TOP_RIGHT: |
|
pointX = x + width - 10; |
|
pointY = y; |
|
break; |
|
case ControlPointType.MIDDLE_LEFT: |
|
pointX = x; |
|
pointY = centerY - 5; |
|
break; |
|
case ControlPointType.MIDDLE_RIGHT: |
|
pointX = x + width - 10; |
|
pointY = centerY - 5; |
|
break; |
|
case ControlPointType.BOTTOM_LEFT: |
|
pointX = x; |
|
pointY = y + height - 10; |
|
break; |
|
case ControlPointType.BOTTOM_CENTER: |
|
pointX = centerX - 5; |
|
pointY = y + height - 10; |
|
break; |
|
case ControlPointType.BOTTOM_RIGHT: |
|
pointX = x + width - 10; |
|
pointY = y + height - 10; |
|
break; |
|
} |
|
|
|
|
|
if (rotation !== 0) { |
|
const rad = rotation * Math.PI / 180; |
|
const rotatedX = centerX + (pointX - centerX) * Math.cos(rad) - (pointY - centerY) * Math.sin(rad); |
|
const rotatedY = centerY + (pointX - centerX) * Math.sin(rad) + (pointY - centerY) * Math.cos(rad); |
|
pointX = rotatedX; |
|
pointY = rotatedY; |
|
} |
|
|
|
point.style.left = `${pointX}px`; |
|
point.style.top = `${pointY}px`; |
|
}); |
|
} |
|
|
|
|
|
function updateFormInputs(x, y, width, height, rotation) { |
|
posXInput.value = Math.round(x); |
|
posYInput.value = Math.round(y); |
|
widthInput.value = Math.round(width); |
|
heightInput.value = Math.round(height); |
|
rotationInput.value = Math.round(rotation); |
|
} |
|
|
|
|
|
previewImage.addEventListener('mousedown', function(e) { |
|
if (!isFullscreen && e.target === previewImage) { |
|
isDragging = true; |
|
startX = e.clientX; |
|
startY = e.clientY; |
|
startImageX = parseFloat(previewImage.style.left || '0'); |
|
startImageY = parseFloat(previewImage.style.top || '0'); |
|
e.preventDefault(); |
|
} |
|
}); |
|
|
|
|
|
function startControlPointDrag(e) { |
|
if (!isFullscreen) { |
|
activeControlPoint = e.target.dataset.type; |
|
startX = e.clientX; |
|
startY = e.clientY; |
|
startWidth = parseFloat(previewImage.style.width); |
|
startHeight = parseFloat(previewImage.style.height); |
|
startImageX = parseFloat(previewImage.style.left || '0'); |
|
startImageY = parseFloat(previewImage.style.top || '0'); |
|
e.preventDefault(); |
|
e.stopPropagation(); |
|
} |
|
} |
|
|
|
|
|
rotateHandle.addEventListener('mousedown', function(e) { |
|
if (!isFullscreen) { |
|
isRotating = true; |
|
startX = e.clientX; |
|
startY = e.clientY; |
|
startRotation = parseFloat(rotationInput.value) || 0; |
|
e.preventDefault(); |
|
} |
|
}); |
|
|
|
|
|
panelHeader.addEventListener('mousedown', function(e) { |
|
if (!isFullscreen && (e.target === panelHeader || e.target.classList.contains('panel-title'))) { |
|
isDraggingPanel = true; |
|
startX = e.clientX; |
|
startY = e.clientY; |
|
startPanelX = settingsPanel.offsetLeft; |
|
startPanelY = settingsPanel.offsetTop; |
|
e.preventDefault(); |
|
} |
|
}); |
|
|
|
|
|
togglePanel.addEventListener('click', function() { |
|
if (!isFullscreen) { |
|
settingsPanel.classList.toggle('panel-collapsed'); |
|
togglePanel.textContent = settingsPanel.classList.contains('panel-collapsed') ? '+' : '−'; |
|
} |
|
}); |
|
|
|
|
|
document.addEventListener('mousemove', function(e) { |
|
if (isFullscreen) return; |
|
|
|
if (isDragging) { |
|
const dx = e.clientX - startX; |
|
const dy = e.clientY - startY; |
|
const newX = startImageX + dx; |
|
const newY = startImageY + dy; |
|
|
|
const currentWidth = parseFloat(previewImage.style.width); |
|
const currentHeight = parseFloat(previewImage.style.height); |
|
const rotation = parseFloat(rotationInput.value) || 0; |
|
|
|
updateImageStyle(newX, newY, currentWidth, currentHeight, rotation); |
|
updateFormInputs(newX, newY, currentWidth, currentHeight, rotation); |
|
} else if (activeControlPoint) { |
|
const dx = e.clientX - startX; |
|
const dy = e.clientY - startY; |
|
let newWidth = startWidth; |
|
let newHeight = startHeight; |
|
let newX = startImageX; |
|
let newY = startImageY; |
|
const rotation = parseFloat(rotationInput.value) || 0; |
|
|
|
switch(activeControlPoint) { |
|
case ControlPointType.TOP_LEFT: |
|
newWidth = startWidth - dx; |
|
newHeight = newWidth / aspectRatio; |
|
newX = startImageX + dx; |
|
newY = startImageY + (startHeight - newHeight); |
|
break; |
|
case ControlPointType.TOP_CENTER: |
|
newHeight = startHeight - dy; |
|
newY = startImageY + dy; |
|
break; |
|
case ControlPointType.TOP_RIGHT: |
|
newWidth = startWidth + dx; |
|
newHeight = newWidth / aspectRatio; |
|
newY = startImageY + (startHeight - newHeight); |
|
break; |
|
case ControlPointType.MIDDLE_LEFT: |
|
newWidth = startWidth - dx; |
|
newX = startImageX + dx; |
|
break; |
|
case ControlPointType.MIDDLE_RIGHT: |
|
newWidth = startWidth + dx; |
|
break; |
|
case ControlPointType.BOTTOM_LEFT: |
|
newWidth = startWidth - dx; |
|
newHeight = newWidth / aspectRatio; |
|
newX = startImageX + dx; |
|
break; |
|
case ControlPointType.BOTTOM_CENTER: |
|
newHeight = startHeight + dy; |
|
break; |
|
case ControlPointType.BOTTOM_RIGHT: |
|
newWidth = startWidth + dx; |
|
newHeight = newWidth / aspectRatio; |
|
break; |
|
} |
|
|
|
|
|
newWidth = Math.max(10, newWidth); |
|
newHeight = Math.max(10, newHeight); |
|
|
|
updateImageStyle(newX, newY, newWidth, newHeight, rotation); |
|
updateFormInputs(newX, newY, newWidth, newHeight, rotation); |
|
} else if (isRotating) { |
|
const centerX = parseFloat(previewImage.style.left) + parseFloat(previewImage.style.width) / 2; |
|
const centerY = parseFloat(previewImage.style.top) + parseFloat(previewImage.style.height) / 2; |
|
|
|
const angle = Math.atan2(e.clientY - centerY, e.clientX - centerX) * 180 / Math.PI; |
|
const newRotation = (angle + 90) % 360; |
|
|
|
const currentX = parseFloat(previewImage.style.left); |
|
const currentY = parseFloat(previewImage.style.top); |
|
const currentWidth = parseFloat(previewImage.style.width); |
|
const currentHeight = parseFloat(previewImage.style.height); |
|
|
|
updateImageStyle(currentX, currentY, currentWidth, currentHeight, newRotation); |
|
updateFormInputs(currentX, currentY, currentWidth, currentHeight, newRotation); |
|
} else if (isDraggingPanel) { |
|
const dx = e.clientX - startX; |
|
const dy = e.clientY - startY; |
|
|
|
let newLeft = startPanelX + dx; |
|
let newTop = startPanelY + dy; |
|
|
|
|
|
newLeft = Math.max(0, Math.min(window.innerWidth - settingsPanel.offsetWidth, newLeft)); |
|
newTop = Math.max(0, Math.min(window.innerHeight - panelHeader.offsetHeight, newTop)); |
|
|
|
settingsPanel.style.left = `${newLeft}px`; |
|
settingsPanel.style.top = `${newTop}px`; |
|
} |
|
}); |
|
|
|
|
|
document.addEventListener('mouseup', function() { |
|
isDragging = false; |
|
activeControlPoint = null; |
|
isRotating = false; |
|
isDraggingPanel = false; |
|
}); |
|
|
|
|
|
posXInput.addEventListener('input', updateFromForm); |
|
posYInput.addEventListener('input', updateFromForm); |
|
widthInput.addEventListener('input', updateFromForm); |
|
heightInput.addEventListener('input', updateFromForm); |
|
rotationInput.addEventListener('input', updateFromForm); |
|
|
|
function updateFromForm() { |
|
const x = parseFloat(posXInput.value) || 0; |
|
const y = parseFloat(posYInput.value) || 0; |
|
const width = parseFloat(widthInput.value) || 100; |
|
const height = parseFloat(heightInput.value) || 100; |
|
const rotation = parseFloat(rotationInput.value) || 0; |
|
|
|
updateImageStyle(x, y, width, height, rotation); |
|
} |
|
|
|
|
|
flipHorizontalBtn.addEventListener('click', function() { |
|
scaleX *= -1; |
|
updateImageStyle( |
|
parseFloat(previewImage.style.left), |
|
parseFloat(previewImage.style.top), |
|
parseFloat(previewImage.style.width), |
|
parseFloat(previewImage.style.height), |
|
parseFloat(rotationInput.value) || 0 |
|
); |
|
}); |
|
|
|
flipVerticalBtn.addEventListener('click', function() { |
|
scaleY *= -1; |
|
updateImageStyle( |
|
parseFloat(previewImage.style.left), |
|
parseFloat(previewImage.style.top), |
|
parseFloat(previewImage.style.width), |
|
parseFloat(previewImage.style.height), |
|
parseFloat(rotationInput.value) || 0 |
|
); |
|
}); |
|
|
|
|
|
okButton.addEventListener('click', toggleFullscreen); |
|
|
|
function toggleFullscreen() { |
|
if (!previewImage.src) return; |
|
|
|
if (isFullscreen) { |
|
exitFullscreen(); |
|
} else { |
|
enterFullscreen(); |
|
} |
|
} |
|
|
|
function enterFullscreen() { |
|
isFullscreen = true; |
|
(document.documentElement.requestFullscreen || document.documentElement.webkitRequestFullscreen || document.documentElement.mozRequestFullScreen || document.documentElement.msRequestFullscreen).call(document.documentElement); |
|
|
|
document.querySelectorAll('.control-point').forEach(point => { |
|
point.classList.add('hidden'); |
|
}); |
|
rotateHandle.classList.add('hidden'); |
|
settingsPanel.classList.add('hidden'); |
|
|
|
|
|
previewContainer.classList.add('fullscreen-mode'); |
|
|
|
|
|
previewImage.style.cursor = 'default'; |
|
|
|
|
|
const closeButton = document.createElement('div'); |
|
closeButton.className = 'close-fullscreen'; |
|
closeButton.innerHTML = '×'; |
|
closeButton.addEventListener('click', exitFullscreen); |
|
document.body.appendChild(closeButton); |
|
|
|
|
|
document.addEventListener('keydown', handleFullscreenKeydown); |
|
|
|
|
|
document.body.style.cursor = 'none'; |
|
} |
|
|
|
function exitFullscreen() { |
|
isFullscreen = false; |
|
(document.exitFullscreen || document.webkitExitFullscreen || document.mozCancelFullScreen || document.msExitFullscreen).call(document); |
|
|
|
|
|
document.querySelectorAll('.control-point').forEach(point => { |
|
point.classList.remove('hidden'); |
|
}); |
|
rotateHandle.classList.remove('hidden'); |
|
settingsPanel.classList.remove('hidden'); |
|
|
|
|
|
previewContainer.classList.remove('fullscreen-mode'); |
|
|
|
|
|
previewImage.style.cursor = 'move'; |
|
|
|
|
|
const closeButton = document.querySelector('.close-fullscreen'); |
|
if (closeButton) closeButton.remove(); |
|
|
|
|
|
document.body.style.cursor = ''; |
|
|
|
|
|
document.removeEventListener('keydown', handleFullscreenKeydown); |
|
} |
|
|
|
function handleFullscreenKeydown(e) { |
|
if (e.key === 'Escape') { |
|
exitFullscreen(); |
|
} |
|
} |
|
}); |
|
</script> |
|
</body> |
|
</html> |