Files
dsProject/dsLightRag/XingJun/move.html
2025-09-09 15:21:27 +08:00

343 lines
16 KiB
HTML
Raw 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.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>箭头动画</title>
<style>
body { margin: 0; padding: 0; height: 100vh; display: flex; overflow: hidden; }
.background-container { position: relative; flex: 1; height: 100vh; background-image: url('background.png'); background-position: center; background-repeat: no-repeat; background-size: contain; z-index: 1; }
.control-panel { width: 200px; background-color: #fff; border-left: 1px solid #ccc; padding: 20px; height: 100vh; box-sizing: border-box; z-index: 2; overflow-y: auto; }
.control-section { margin-bottom: 30px; }
.control-section h3 { margin-top: 0; padding-bottom: 10px; border-bottom: 1px solid #eee; }
.image-selector { display: grid; grid-template-columns: repeat(2, 1fr); gap: 10px; margin-top: 15px; }
.image-btn { width: 70px; height: 70px; border: 2px solid #ddd; border-radius: 4px; cursor: pointer; background-size: contain; background-repeat: no-repeat; background-position: center; transition: all 0.2s; }
.image-btn:hover { border-color: #4CAF50; transform: scale(1.05); }
.image-btn:active { transform: scale(0.98); }
.arrow-container { position: absolute; pointer-events: auto; }
.arrow-image { width: 155px; height: 173px; background-size: contain; background-repeat: no-repeat; cursor: move; }
.save-btn { width: 100%; padding: 10px; background-color: #4CAF50; color: white; border: none; border-radius: 4px; cursor: pointer; font-size: 16px; margin-top: 20px; }
.save-btn:hover { background-color: #45a049; }
.arrow-text { position: absolute; top: '100%'; left: '50%'; transform: translateX(-50%); margin-top: '-5px'; font-weight: bold; color: red; font-size: 16px; white-space: nowrap; text-align: center; width: 100%; background-color: transparent; padding: 3px 8px; border-radius: 4px; }
#contextMenu { position: absolute; display: none; background: white; border: 1px solid #ccc; padding: 5px; z-index: 9999; }
#deleteArrow { padding: 3px 10px; cursor: pointer; }
/* 新增红点样式 */
.center-dot { position: absolute; width: 8px; height: 8px; background: red; border-radius: 50%; transform: translate(-50%, -50%); pointer-events: none; z-index: 5; }
</style>
</head>
<body>
<div class="background-container"></div>
<div class="control-panel">
<div class="control-section">
<h3>增加箭头</h3>
<div class="image-selector">
<div class="image-btn" data-image="./1.png" style="background-image: url('./1.png');"></div>
<div class="image-btn" data-image="./2.png" style="background-image: url('./2.png');"></div>
<div class="image-btn" data-image="./3.png" style="background-image: url('./3.png');"></div>
<div class="image-btn" data-image="./4.png" style="background-image: url('./4.png');"></div>
<div class="image-btn" data-image="./5.png" style="background-image: url('./5.png');"></div>
<div class="image-btn" data-image="./6.png" style="background-image: url('./6.png');"></div>
</div>
<button class="save-btn" id="savePositionsBtn">保存位置</button>
<button class="save-btn" id="markCenterBtn" style="margin-top: 10px;">标记中心点</button>
<button class="save-btn" id="startAnimationBtn" style="margin-top: 10px;">开始</button>
<button class="save-btn" id="resetBtn" style="margin-top: 10px;">重置</button>
</div>
</div>
<div id="contextMenu"><div id="deleteArrow">删除箭头</div></div>
<script>
// 修复核心整理所有JS代码到单个script标签内
document.addEventListener('DOMContentLoaded', function() {
const backgroundContainer = document.querySelector('.background-container');
const imageButtons = document.querySelectorAll('.image-btn');
const saveBtn = document.getElementById('savePositionsBtn');
const markCenterBtn = document.getElementById('markCenterBtn');
const startAnimationBtn = document.getElementById('startAnimationBtn');
const resetBtn = document.getElementById('resetBtn');
const contextMenu = document.getElementById('contextMenu');
const deleteArrow = document.getElementById('deleteArrow');
let selectedArrow = null;
let centerDot = null;
// 添加重置按钮事件监听器
resetBtn.addEventListener('click', function() {
location.reload();
});
// 添加开始按钮事件监听器
startAnimationBtn.addEventListener('click', startAnimation);
// 动画控制函数 - 确保在DOMContentLoaded回调内部定义
function startAnimation() {
// 检查是否已设置中心点
if (!centerDot) {
alert('请先确定中心点');
return;
}
// 获取中心点坐标
const centerX = parseFloat(centerDot.style.left);
const centerY = parseFloat(centerDot.style.top);
// 获取所有箭头
const arrows = document.querySelectorAll('.arrow-container');
if (arrows.length === 0) {
alert('没有可移动的箭头');
return;
}
// 为每个箭头添加动画
arrows.forEach(arrow => {
animateArrow(arrow, centerX, centerY);
});
}
// 单个箭头动画函数 - 同样放在DOMContentLoaded回调内部
function animateArrow(arrow, targetX, targetY) {
// 获取箭头当前位置
let currentX = parseFloat(arrow.style.left) || 0;
let currentY = parseFloat(arrow.style.top) || 0;
// 动画帧函数
function updatePosition() {
// 计算到目标的距离
const dx = targetX - currentX;
const dy = targetY - currentY;
const distance = Math.sqrt(dx * dx + dy * dy);
// 如果距离小于5px停止动画
if (distance < 5) {
// 确保箭头最终位置准确
arrow.style.left = targetX + 'px';
arrow.style.top = targetY + 'px';
return;
}
// 计算移动步长距离的5%,确保靠近目标时减速)
const step = distance * 0.05;
const moveX = (dx / distance) * step;
const moveY = (dy / distance) * step;
// 更新位置
currentX += moveX;
currentY += moveY;
arrow.style.left = currentX + 'px';
arrow.style.top = currentY + 'px';
// 继续动画
requestAnimationFrame(updatePosition);
}
// 开始动画
updatePosition();
}
// 加载保存的元素
loadAllElements();
// 绑定箭头按钮事件
imageButtons.forEach(button => {
button.addEventListener('click', () => {
const imagePath = button.getAttribute('data-image');
addImageToContainer(imagePath);
});
});
// 保存按钮事件
saveBtn.addEventListener('click', saveAllElements);
// 右键菜单事件
deleteArrow.addEventListener('click', function() {
if (selectedArrow) {
selectedArrow.remove();
saveAllElements();
contextMenu.style.display = 'none';
selectedArrow = null;
}
});
// 点击空白处关闭菜单
document.addEventListener('click', function() {
contextMenu.style.display = 'none';
selectedArrow = null;
});
// 标记中心点功能
markCenterBtn.addEventListener('click', function() {
// 移除旧点
if (centerDot) {
centerDot.remove();
centerDot = null;
}
// 创建新点
function handleMapClick(e) {
const rect = backgroundContainer.getBoundingClientRect();
const x = e.clientX - rect.left;
const y = e.clientY - rect.top;
centerDot = document.createElement('div');
centerDot.className = 'center-dot';
centerDot.style.left = x + 'px';
centerDot.style.top = y + 'px';
backgroundContainer.appendChild(centerDot);
backgroundContainer.removeEventListener('click', handleMapClick);
}
backgroundContainer.addEventListener('click', handleMapClick);
});
// 添加箭头函数
function addImageToContainer(imagePath, position = null, textContent = '') {
const container = document.createElement('div');
container.className = 'arrow-container';
container.dataset.imagePath = imagePath;
const newImage = document.createElement('div');
newImage.className = 'arrow-image';
newImage.style.backgroundImage = `url('${imagePath}')`;
container.appendChild(newImage);
// 添加文字元素
if (textContent) {
const textElement = document.createElement('div');
textElement.className = 'arrow-text';
textElement.textContent = textContent;
container.dataset.text = textContent;
container.appendChild(textElement);
}
// 设置位置
if (position) {
container.style.left = position.left;
container.style.top = position.top;
} else {
const x = Math.random() * (backgroundContainer.offsetWidth - 155);
const y = Math.random() * (backgroundContainer.offsetHeight - 173);
container.style.left = `${x}px`;
container.style.top = `${y}px`;
}
// 双击编辑文字
container.addEventListener('dblclick', (e) => {
e.stopPropagation();
const currentText = container.dataset.text || '';
const textContent = prompt('请输入文字:', currentText);
if (textContent !== null) {
if (textContent.trim() === '') {
container.querySelector('.arrow-text')?.remove();
delete container.dataset.text;
} else {
let textElement = container.querySelector('.arrow-text');
if (!textElement) {
textElement = document.createElement('div');
textElement.className = 'arrow-text';
container.appendChild(textElement);
}
textElement.textContent = textContent;
container.dataset.text = textContent;
}
}
});
// 右键菜单支持
container.addEventListener('contextmenu', function(e) {
e.preventDefault();
selectedArrow = this;
contextMenu.style.left = `${e.clientX}px`;
contextMenu.style.top = `${e.clientY}px`;
contextMenu.style.display = 'block';
});
// 拖拽功能
makeElementDraggable(container);
backgroundContainer.appendChild(container);
return container;
}
// 拖拽实现
function makeElementDraggable(element) {
let isDragging = false, offsetX, offsetY;
element.addEventListener('mousedown', (e) => {
if (e.button === 2) return; // 忽略右键
isDragging = true;
const rect = element.getBoundingClientRect();
offsetX = e.clientX - rect.left;
offsetY = e.clientY - rect.top;
element.style.zIndex = '10';
});
document.addEventListener('mousemove', (e) => {
if (!isDragging) return;
const x = e.clientX - offsetX;
const y = e.clientY - offsetY;
element.style.left = `${x}px`;
element.style.top = `${y}px`;
});
document.addEventListener('mouseup', () => {
if (isDragging) {
isDragging = false;
element.style.zIndex = '2';
}
});
}
// 保存/加载功能
function saveAllElements() {
const elements = [];
document.querySelectorAll('.arrow-container').forEach(container => {
elements.push({
type: 'arrow',
imagePath: container.dataset.imagePath,
text: container.dataset.text || '',
left: container.style.left,
top: container.style.top
});
});
// 新增:保存中心点数据
if (centerDot) {
elements.push({
type: 'center',
left: centerDot.style.left,
top: centerDot.style.top
});
}
localStorage.setItem('mapElements', JSON.stringify(elements));
alert('保存成功!');
}
function loadAllElements() {
const savedData = localStorage.getItem('mapElements');
if (savedData) {
try {
JSON.parse(savedData).forEach(element => {
if (element.type === 'arrow') {
addImageToContainer(element.imagePath, {left: element.left, top: element.top}, element.text);
}
// 新增:处理中心点数据
else if (element.type === 'center') {
// 如果已有中心点,先移除
if (centerDot) {
centerDot.remove();
}
// 创建新的中心点
centerDot = document.createElement('div');
centerDot.className = 'center-dot';
centerDot.style.left = element.left;
centerDot.style.top = element.top;
backgroundContainer.appendChild(centerDot);
}
});
} catch (e) { console.error('加载失败:', e); }
}
}
}); // DOMContentLoaded回调结束
// 确保这里没有残留的startAnimation函数定义
</script>
</body>
</html>