This commit is contained in:
2025-09-09 15:45:39 +08:00
parent dfa70f71b3
commit eb6ae9f324
4 changed files with 115 additions and 69 deletions

View File

@@ -1,4 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Do not edit this file with editors other than draw.io -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg" style="background: transparent; background-color: transparent; color-scheme: light dark;" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="241px" height="61px" viewBox="-0.5 -0.5 241 61" content="&lt;mxfile host=&quot;Electron&quot; agent=&quot;Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/28.1.2 Chrome/138.0.7204.243 Electron/37.4.0 Safari/537.36&quot; version=&quot;28.1.2&quot; scale=&quot;1&quot; border=&quot;0&quot;&gt;&#10; &lt;diagram name=&quot;第 1 页&quot; id=&quot;Ju8HBPQ0NuOidMe9okl8&quot;&gt;&#10; &lt;mxGraphModel dx=&quot;1426&quot; dy=&quot;841&quot; grid=&quot;1&quot; gridSize=&quot;10&quot; guides=&quot;1&quot; tooltips=&quot;1&quot; connect=&quot;1&quot; arrows=&quot;1&quot; fold=&quot;1&quot; page=&quot;1&quot; pageScale=&quot;1&quot; pageWidth=&quot;827&quot; pageHeight=&quot;1169&quot; math=&quot;0&quot; shadow=&quot;0&quot;&gt;&#10; &lt;root&gt;&#10; &lt;mxCell id=&quot;0&quot; /&gt;&#10; &lt;mxCell id=&quot;1&quot; parent=&quot;0&quot; /&gt;&#10; &lt;mxCell id=&quot;5g9AZhaBOiL0pv-xpRXJ-1&quot; value=&quot;&quot; style=&quot;html=1;shadow=0;dashed=0;align=center;verticalAlign=middle;shape=mxgraph.arrows2.stylisedArrow;dy=0.6;dx=66;notch=0;feather=0.27;&quot; vertex=&quot;1&quot; parent=&quot;1&quot;&gt;&#10; &lt;mxGeometry x=&quot;140&quot; y=&quot;390&quot; width=&quot;240&quot; height=&quot;60&quot; as=&quot;geometry&quot; /&gt;&#10; &lt;/mxCell&gt;&#10; &lt;/root&gt;&#10; &lt;/mxGraphModel&gt;&#10; &lt;/diagram&gt;&#10;&lt;/mxfile&gt;&#10;"><defs/><g><g data-cell-id="0"><g data-cell-id="1"><g data-cell-id="5g9AZhaBOiL0pv-xpRXJ-1"><g><path d="M 0 8.1 L 174 18 L 164 0 L 240 30 L 164 60 L 174 42 L 0 51.9 L 0 30 Z" fill="#ffffff" stroke="#000000" stroke-miterlimit="10" pointer-events="all" style="fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/></g></g></g></g></g></svg>

Before

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.8 KiB

View File

@@ -74,9 +74,11 @@
return; return;
} }
// 获取中心点坐标 // 获取中心点坐标修复使用getBoundingClientRect确保坐标正确
const centerX = parseFloat(centerDot.style.left); const centerRect = centerDot.getBoundingClientRect();
const centerY = parseFloat(centerDot.style.top); const containerRect = backgroundContainer.getBoundingClientRect();
const centerX = centerRect.left - containerRect.left;
const centerY = centerRect.top - containerRect.top;
// 获取所有箭头 // 获取所有箭头
const arrows = document.querySelectorAll('.arrow-container'); const arrows = document.querySelectorAll('.arrow-container');
@@ -91,43 +93,73 @@
}); });
} }
// 单个箭头动画函数 - 同样放在DOMContentLoaded回调内部 // 单个箭头动画函数
function animateArrow(arrow, targetX, targetY) { function animateArrow(arrow, targetX, targetY) {
// 获取箭头当前位置 // 获取箭头图片尺寸固定为155px×173px
let currentX = parseFloat(arrow.style.left) || 0; const arrowWidth = 155;
let currentY = parseFloat(arrow.style.top) || 0; const arrowHeight = 173;
// 计算中心点偏移量(宽度和高度的一半)
const centerOffsetX = arrowWidth / 2;
const centerOffsetY = arrowHeight / 2;
// 定义停止距离(箭头中心点与目标中心点的距离)
const stopDistance = 50;
// 获取箭头当前位置(相对于背景容器)
const rect = arrow.getBoundingClientRect();
const containerRect = backgroundContainer.getBoundingClientRect();
// 当前位置需要加上偏移量,获取实际中心点位置
let currentX = rect.left - containerRect.left + centerOffsetX;
let currentY = rect.top - containerRect.top + centerOffsetY;
// 添加随机偏移避免重叠
const offsetRange = 20;
const randomOffsetX = (Math.random() - 0.5) * offsetRange;
const randomOffsetY = (Math.random() - 0.5) * offsetRange;
const finalTargetX = targetX + randomOffsetX;
const finalTargetY = targetY + randomOffsetY;
// 计算方向向量和距离
const dxTotal = finalTargetX - currentX;
const dyTotal = finalTargetY - currentY;
const distanceTotal = Math.sqrt(dxTotal * dxTotal + dyTotal * dyTotal);
// 计算调整后的目标位置保持stopDistance距离
let adjustedTargetX, adjustedTargetY;
if (distanceTotal > stopDistance) {
// 如果距离大于停止距离,计算新目标位置
const ratio = (distanceTotal - stopDistance) / distanceTotal;
adjustedTargetX = currentX + dxTotal * ratio;
adjustedTargetY = currentY + dyTotal * ratio;
} else {
// 如果已在停止距离内,保持当前位置
adjustedTargetX = currentX;
adjustedTargetY = currentY;
}
// 动画帧函数
function updatePosition() { function updatePosition() {
// 计算到目标的距离 const dx = adjustedTargetX - currentX;
const dx = targetX - currentX; const dy = adjustedTargetY - currentY;
const dy = targetY - currentY;
const distance = Math.sqrt(dx * dx + dy * dy); const distance = Math.sqrt(dx * dx + dy * dy);
// 如果距离小于5px停止动画 // 距离小于2px停止动画(确保到达调整后的目标位置)
if (distance < 5) { if (distance < 2) {
// 确保箭头最终位置准确 arrow.style.left = (adjustedTargetX - centerOffsetX) + 'px';
arrow.style.left = targetX + 'px'; arrow.style.top = (adjustedTargetY - centerOffsetY) + 'px';
arrow.style.top = targetY + 'px';
return; return;
} }
// 计算移动步长距离的5%,确保靠近目标时减速) const step = Math.max(distance * 0.05, 1);
const step = distance * 0.05;
const moveX = (dx / distance) * step; const moveX = (dx / distance) * step;
const moveY = (dy / distance) * step; const moveY = (dy / distance) * step;
// 更新位置
currentX += moveX; currentX += moveX;
currentY += moveY; currentY += moveY;
arrow.style.left = currentX + 'px'; arrow.style.left = (currentX - centerOffsetX) + 'px';
arrow.style.top = currentY + 'px'; arrow.style.top = (currentY - centerOffsetY) + 'px';
// 继续动画
requestAnimationFrame(updatePosition); requestAnimationFrame(updatePosition);
} }
// 开始动画
updatePosition(); updatePosition();
} }
// 加载保存的元素 // 加载保存的元素
@@ -191,13 +223,13 @@
const container = document.createElement('div'); const container = document.createElement('div');
container.className = 'arrow-container'; container.className = 'arrow-container';
container.dataset.imagePath = imagePath; container.dataset.imagePath = imagePath;
const newImage = document.createElement('div'); const newImage = document.createElement('div');
newImage.className = 'arrow-image'; newImage.className = 'arrow-image';
newImage.style.backgroundImage = `url('${imagePath}')`; newImage.style.backgroundImage = `url('${imagePath}')`;
container.appendChild(newImage); container.appendChild(newImage);
// 添加文字元素 // 添加文字元素
if (textContent) { if (textContent) {
const textElement = document.createElement('div'); const textElement = document.createElement('div');
@@ -206,16 +238,23 @@
container.dataset.text = textContent; container.dataset.text = textContent;
container.appendChild(textElement); container.appendChild(textElement);
} }
// 设置位置 // 设置位置 - 使用中心点作为参照
const arrowWidth = 155;
const arrowHeight = 173;
const centerOffsetX = arrowWidth / 2;
const centerOffsetY = arrowHeight / 2;
if (position) { if (position) {
container.style.left = position.left; // 修复:直接使用传递的左上角位置,不再减去偏移量
container.style.top = position.top; container.style.left = parseFloat(position.left) + 'px';
container.style.top = parseFloat(position.top) + 'px';
} else { } else {
const x = Math.random() * (backgroundContainer.offsetWidth - 155); // 随机位置也使用中心点作为参照
const y = Math.random() * (backgroundContainer.offsetHeight - 173); const x = Math.random() * (backgroundContainer.offsetWidth - arrowWidth) + centerOffsetX;
container.style.left = `${x}px`; const y = Math.random() * (backgroundContainer.offsetHeight - arrowHeight) + centerOffsetY;
container.style.top = `${y}px`; container.style.left = (x - centerOffsetX) + 'px';
container.style.top = (y - centerOffsetY) + 'px';
} }
// 双击编辑文字 // 双击编辑文字
@@ -286,16 +325,27 @@
// 保存/加载功能 // 保存/加载功能
function saveAllElements() { function saveAllElements() {
const elements = []; const elements = [];
document.querySelectorAll('.arrow-container').forEach(container => { const arrowWidth = 155;
const arrowHeight = 173;
const centerOffsetX = arrowWidth / 2;
const centerOffsetY = arrowHeight / 2;
document.querySelectorAll('.arrow-container').forEach(arrow => {
// 保存中心点坐标而非左上角坐标
const left = parseFloat(arrow.style.left) || 0;
const top = parseFloat(arrow.style.top) || 0;
elements.push({ elements.push({
type: 'arrow', type: 'arrow',
imagePath: container.dataset.imagePath, imagePath: arrow.dataset.imagePath,
text: container.dataset.text || '', // 计算并保存中心点位置
left: container.style.left, left: left + centerOffsetX,
top: container.style.top top: top + centerOffsetY,
text: arrow.dataset.text || ''
}); });
}); });
// 新增:保存中心点数据
// 保存中心点
if (centerDot) { if (centerDot) {
elements.push({ elements.push({
type: 'center', type: 'center',
@@ -303,34 +353,34 @@
top: centerDot.style.top top: centerDot.style.top
}); });
} }
localStorage.setItem('mapElements', JSON.stringify(elements));
alert('保存成功!'); localStorage.setItem('savedElements', JSON.stringify(elements));
alert('位置已保存');
} }
function loadAllElements() { function loadAllElements() {
const savedData = localStorage.getItem('mapElements'); const savedElements = JSON.parse(localStorage.getItem('savedElements') || '[]');
if (savedData) { const arrowWidth = 155;
try { const arrowHeight = 173;
JSON.parse(savedData).forEach(element => { const centerOffsetX = arrowWidth / 2;
if (element.type === 'arrow') { const centerOffsetY = arrowHeight / 2;
addImageToContainer(element.imagePath, {left: element.left, top: element.top}, element.text);
} savedElements.forEach(item => {
// 新增:处理中心点数据 if (item.type === 'arrow') {
else if (element.type === 'center') { // 加载时使用中心点坐标减去偏移量得到左上角位置
// 如果已有中心点,先移除 addImageToContainer(item.imagePath, {
if (centerDot) { left: item.left - centerOffsetX,
centerDot.remove(); top: item.top - centerOffsetY
} }, item.text);
// 创建新的中心点 } else if (item.type === 'center') {
centerDot = document.createElement('div'); // 创建中心点
centerDot.className = 'center-dot'; centerDot = document.createElement('div');
centerDot.style.left = element.left; centerDot.className = 'center-dot';
centerDot.style.top = element.top; centerDot.style.left = item.left;
backgroundContainer.appendChild(centerDot); centerDot.style.top = item.top;
} backgroundContainer.appendChild(centerDot);
}); }
} catch (e) { console.error('加载失败:', e); } });
}
} }
}); // DOMContentLoaded回调结束 }); // DOMContentLoaded回调结束
// 确保这里没有残留的startAnimation函数定义 // 确保这里没有残留的startAnimation函数定义

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.8 KiB