Compare commits
3 Commits
89b7f0162f
...
13a282d93a
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
13a282d93a | ||
|
|
0665987a03 | ||
|
|
da2f3cfbff |
@@ -158,7 +158,7 @@ html, body {
|
|||||||
display: none;
|
display: none;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 4px;
|
gap: 2px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -193,17 +193,22 @@ html, body {
|
|||||||
font-style: italic;
|
font-style: italic;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 镜像按钮样式 */
|
||||||
|
.toolbar-btn.mirror-btn {
|
||||||
|
font-size: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
.toolbar-divider {
|
.toolbar-divider {
|
||||||
width: 1px;
|
width: 1px;
|
||||||
height: 24px;
|
height: 24px;
|
||||||
background: #ddd;
|
background: #ddd;
|
||||||
margin: 0 2px;
|
margin: 0 1px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.toolbar-label {
|
.toolbar-label {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 4px;
|
gap: 2px;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
color: #666;
|
color: #666;
|
||||||
}
|
}
|
||||||
@@ -233,6 +238,28 @@ html, body {
|
|||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.rotate-slider {
|
||||||
|
width: 100px;
|
||||||
|
height: 32px;
|
||||||
|
cursor: pointer;
|
||||||
|
accent-color: #4a90e2;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 旋转度数显示固定宽度 */
|
||||||
|
#rotateValue {
|
||||||
|
display: inline-block;
|
||||||
|
min-width: 40px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 百分比显示固定宽度 */
|
||||||
|
#opacityValue, #bgScaleValue, #bgOpacityValue {
|
||||||
|
display: inline-block;
|
||||||
|
min-width: 40px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
/* 字号滚轮选择器 */
|
/* 字号滚轮选择器 */
|
||||||
.roller-picker {
|
.roller-picker {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|||||||
@@ -57,6 +57,14 @@
|
|||||||
<input type="range" id="opacitySlider" min="0" max="100" value="100" class="opacity-slider">
|
<input type="range" id="opacitySlider" min="0" max="100" value="100" class="opacity-slider">
|
||||||
<span id="opacityValue">100%</span>
|
<span id="opacityValue">100%</span>
|
||||||
</label>
|
</label>
|
||||||
|
<div class="toolbar-divider"></div>
|
||||||
|
<label class="toolbar-label">
|
||||||
|
<span>旋转</span>
|
||||||
|
<input type="range" id="rotateSlider" min="-180" max="180" value="0" class="rotate-slider">
|
||||||
|
<span id="rotateValue">0°</span>
|
||||||
|
</label>
|
||||||
|
<div class="toolbar-divider"></div>
|
||||||
|
<button class="toolbar-btn mirror-btn" id="mirrorHBtn" title="水平镜像">↔</button>
|
||||||
</div>
|
</div>
|
||||||
<!-- 背景图编辑工具 -->
|
<!-- 背景图编辑工具 -->
|
||||||
<div class="toolbar-group bg-tools" id="bgTools">
|
<div class="toolbar-group bg-tools" id="bgTools">
|
||||||
|
|||||||
64
js/script.js
64
js/script.js
@@ -21,6 +21,9 @@
|
|||||||
const bgTools = document.getElementById('bgTools');
|
const bgTools = document.getElementById('bgTools');
|
||||||
const opacitySlider = document.getElementById('opacitySlider');
|
const opacitySlider = document.getElementById('opacitySlider');
|
||||||
const opacityValue = document.getElementById('opacityValue');
|
const opacityValue = document.getElementById('opacityValue');
|
||||||
|
const rotateSlider = document.getElementById('rotateSlider');
|
||||||
|
const rotateValue = document.getElementById('rotateValue');
|
||||||
|
const mirrorHBtn = document.getElementById('mirrorHBtn');
|
||||||
const bgScaleSlider = document.getElementById('bgScaleSlider');
|
const bgScaleSlider = document.getElementById('bgScaleSlider');
|
||||||
const bgScaleValue = document.getElementById('bgScaleValue');
|
const bgScaleValue = document.getElementById('bgScaleValue');
|
||||||
const bgOpacitySlider = document.getElementById('bgOpacitySlider');
|
const bgOpacitySlider = document.getElementById('bgOpacitySlider');
|
||||||
@@ -125,6 +128,53 @@
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 旋转滑块
|
||||||
|
rotateSlider.addEventListener('input', (e) => {
|
||||||
|
if (selectedOverlay) {
|
||||||
|
let rotateDeg = parseInt(e.target.value);
|
||||||
|
|
||||||
|
// 吸附功能:在 0°、-90°、90° 附近吸附
|
||||||
|
const snapAngles = [0, -90, 90];
|
||||||
|
const snapThreshold = 5; // 吸附阈值 5 度
|
||||||
|
|
||||||
|
for (const snapAngle of snapAngles) {
|
||||||
|
if (Math.abs(rotateDeg - snapAngle) < snapThreshold) {
|
||||||
|
rotateDeg = snapAngle;
|
||||||
|
// 更新滑动条位置
|
||||||
|
rotateSlider.value = rotateDeg;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
selectedOverlay.style.transform = `rotate(${rotateDeg}deg)`;
|
||||||
|
rotateValue.textContent = rotateDeg + '°';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 水平镜像按钮
|
||||||
|
mirrorHBtn.addEventListener('click', () => {
|
||||||
|
if (selectedOverlay) {
|
||||||
|
const img = selectedOverlay.querySelector('img');
|
||||||
|
if (img) {
|
||||||
|
const currentTransform = img.style.transform || '';
|
||||||
|
const isMirroredH = currentTransform.includes('scaleX(-1)');
|
||||||
|
|
||||||
|
// 移除之前的 scaleX 变换
|
||||||
|
let newTransform = currentTransform.replace(/scaleX\(-?1\)/g, '').trim();
|
||||||
|
|
||||||
|
// 如果之前没有水平镜像,则添加
|
||||||
|
if (!isMirroredH) {
|
||||||
|
newTransform = newTransform ? newTransform + ' scaleX(-1)' : 'scaleX(-1)';
|
||||||
|
mirrorHBtn.classList.add('active');
|
||||||
|
} else {
|
||||||
|
mirrorHBtn.classList.remove('active');
|
||||||
|
}
|
||||||
|
|
||||||
|
img.style.transform = newTransform;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// 背景图缩放滑块
|
// 背景图缩放滑块
|
||||||
bgScaleSlider.addEventListener('input', (e) => {
|
bgScaleSlider.addEventListener('input', (e) => {
|
||||||
bgImageScale = e.target.value / 100;
|
bgImageScale = e.target.value / 100;
|
||||||
@@ -622,6 +672,20 @@
|
|||||||
const currentOpacity = overlayEl.style.opacity || '1';
|
const currentOpacity = overlayEl.style.opacity || '1';
|
||||||
opacitySlider.value = parseFloat(currentOpacity) * 100;
|
opacitySlider.value = parseFloat(currentOpacity) * 100;
|
||||||
opacityValue.textContent = opacitySlider.value + '%';
|
opacityValue.textContent = opacitySlider.value + '%';
|
||||||
|
|
||||||
|
// 更新旋转滑块为当前层叠图的旋转角度
|
||||||
|
const currentTransform = overlayEl.style.transform || '';
|
||||||
|
const rotateMatch = currentTransform.match(/rotate\(([-\d.]+)deg\)/);
|
||||||
|
const currentRotate = rotateMatch ? parseFloat(rotateMatch[1]) : 0;
|
||||||
|
rotateSlider.value = currentRotate;
|
||||||
|
rotateValue.textContent = currentRotate + '°';
|
||||||
|
|
||||||
|
// 更新镜像按钮状态
|
||||||
|
const img = overlayEl.querySelector('img');
|
||||||
|
if (img) {
|
||||||
|
const imgTransform = img.style.transform || '';
|
||||||
|
mirrorHBtn.classList.toggle('active', imgTransform.includes('scaleX(-1)'));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 计算图片滑动边界
|
// 计算图片滑动边界
|
||||||
|
|||||||
Reference in New Issue
Block a user