'commit'
This commit is contained in:
@@ -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="<mxfile host="Electron" agent="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" version="28.1.2" scale="1" border="0"> <diagram name="第 1 页" id="Ju8HBPQ0NuOidMe9okl8"> <mxGraphModel dx="1426" dy="841" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0"> <root> <mxCell id="0" /> <mxCell id="1" parent="0" /> <mxCell id="5g9AZhaBOiL0pv-xpRXJ-1" value="" style="html=1;shadow=0;dashed=0;align=center;verticalAlign=middle;shape=mxgraph.arrows2.stylisedArrow;dy=0.6;dx=66;notch=0;feather=0.27;" vertex="1" parent="1"> <mxGeometry x="140" y="390" width="240" height="60" as="geometry" /> </mxCell> </root> </mxGraphModel> </diagram> </mxfile> "><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 |
@@ -74,9 +74,11 @@
|
||||
return;
|
||||
}
|
||||
|
||||
// 获取中心点坐标
|
||||
const centerX = parseFloat(centerDot.style.left);
|
||||
const centerY = parseFloat(centerDot.style.top);
|
||||
// 获取中心点坐标(修复:使用getBoundingClientRect确保坐标正确)
|
||||
const centerRect = centerDot.getBoundingClientRect();
|
||||
const containerRect = backgroundContainer.getBoundingClientRect();
|
||||
const centerX = centerRect.left - containerRect.left;
|
||||
const centerY = centerRect.top - containerRect.top;
|
||||
|
||||
// 获取所有箭头
|
||||
const arrows = document.querySelectorAll('.arrow-container');
|
||||
@@ -91,43 +93,73 @@
|
||||
});
|
||||
}
|
||||
|
||||
// 单个箭头动画函数 - 同样放在DOMContentLoaded回调内部
|
||||
// 单个箭头动画函数
|
||||
function animateArrow(arrow, targetX, targetY) {
|
||||
// 获取箭头当前位置
|
||||
let currentX = parseFloat(arrow.style.left) || 0;
|
||||
let currentY = parseFloat(arrow.style.top) || 0;
|
||||
// 获取箭头图片尺寸(固定为155px×173px)
|
||||
const arrowWidth = 155;
|
||||
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() {
|
||||
// 计算到目标的距离
|
||||
const dx = targetX - currentX;
|
||||
const dy = targetY - currentY;
|
||||
const dx = adjustedTargetX - currentX;
|
||||
const dy = adjustedTargetY - currentY;
|
||||
const distance = Math.sqrt(dx * dx + dy * dy);
|
||||
|
||||
// 如果距离小于5px,停止动画
|
||||
if (distance < 5) {
|
||||
// 确保箭头最终位置准确
|
||||
arrow.style.left = targetX + 'px';
|
||||
arrow.style.top = targetY + 'px';
|
||||
// 当距离小于2px时停止动画(确保到达调整后的目标位置)
|
||||
if (distance < 2) {
|
||||
arrow.style.left = (adjustedTargetX - centerOffsetX) + 'px';
|
||||
arrow.style.top = (adjustedTargetY - centerOffsetY) + 'px';
|
||||
return;
|
||||
}
|
||||
|
||||
// 计算移动步长(距离的5%,确保靠近目标时减速)
|
||||
const step = distance * 0.05;
|
||||
const step = Math.max(distance * 0.05, 1);
|
||||
const moveX = (dx / distance) * step;
|
||||
const moveY = (dy / distance) * step;
|
||||
|
||||
// 更新位置
|
||||
currentX += moveX;
|
||||
currentY += moveY;
|
||||
arrow.style.left = currentX + 'px';
|
||||
arrow.style.top = currentY + 'px';
|
||||
arrow.style.left = (currentX - centerOffsetX) + 'px';
|
||||
arrow.style.top = (currentY - centerOffsetY) + 'px';
|
||||
|
||||
// 继续动画
|
||||
requestAnimationFrame(updatePosition);
|
||||
}
|
||||
|
||||
// 开始动画
|
||||
updatePosition();
|
||||
}
|
||||
// 加载保存的元素
|
||||
@@ -207,15 +239,22 @@
|
||||
container.appendChild(textElement);
|
||||
}
|
||||
|
||||
// 设置位置
|
||||
// 设置位置 - 使用中心点作为参照
|
||||
const arrowWidth = 155;
|
||||
const arrowHeight = 173;
|
||||
const centerOffsetX = arrowWidth / 2;
|
||||
const centerOffsetY = arrowHeight / 2;
|
||||
|
||||
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 {
|
||||
const x = Math.random() * (backgroundContainer.offsetWidth - 155);
|
||||
const y = Math.random() * (backgroundContainer.offsetHeight - 173);
|
||||
container.style.left = `${x}px`;
|
||||
container.style.top = `${y}px`;
|
||||
// 随机位置也使用中心点作为参照
|
||||
const x = Math.random() * (backgroundContainer.offsetWidth - arrowWidth) + centerOffsetX;
|
||||
const y = Math.random() * (backgroundContainer.offsetHeight - arrowHeight) + centerOffsetY;
|
||||
container.style.left = (x - centerOffsetX) + 'px';
|
||||
container.style.top = (y - centerOffsetY) + 'px';
|
||||
}
|
||||
|
||||
// 双击编辑文字
|
||||
@@ -286,16 +325,27 @@
|
||||
// 保存/加载功能
|
||||
function saveAllElements() {
|
||||
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({
|
||||
type: 'arrow',
|
||||
imagePath: container.dataset.imagePath,
|
||||
text: container.dataset.text || '',
|
||||
left: container.style.left,
|
||||
top: container.style.top
|
||||
imagePath: arrow.dataset.imagePath,
|
||||
// 计算并保存中心点位置
|
||||
left: left + centerOffsetX,
|
||||
top: top + centerOffsetY,
|
||||
text: arrow.dataset.text || ''
|
||||
});
|
||||
});
|
||||
// 新增:保存中心点数据
|
||||
|
||||
// 保存中心点
|
||||
if (centerDot) {
|
||||
elements.push({
|
||||
type: 'center',
|
||||
@@ -303,34 +353,34 @@
|
||||
top: centerDot.style.top
|
||||
});
|
||||
}
|
||||
localStorage.setItem('mapElements', JSON.stringify(elements));
|
||||
alert('保存成功!');
|
||||
|
||||
localStorage.setItem('savedElements', 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); }
|
||||
}
|
||||
const savedElements = JSON.parse(localStorage.getItem('savedElements') || '[]');
|
||||
const arrowWidth = 155;
|
||||
const arrowHeight = 173;
|
||||
const centerOffsetX = arrowWidth / 2;
|
||||
const centerOffsetY = arrowHeight / 2;
|
||||
|
||||
savedElements.forEach(item => {
|
||||
if (item.type === 'arrow') {
|
||||
// 加载时使用中心点坐标减去偏移量得到左上角位置
|
||||
addImageToContainer(item.imagePath, {
|
||||
left: item.left - centerOffsetX,
|
||||
top: item.top - centerOffsetY
|
||||
}, item.text);
|
||||
} else if (item.type === 'center') {
|
||||
// 创建中心点
|
||||
centerDot = document.createElement('div');
|
||||
centerDot.className = 'center-dot';
|
||||
centerDot.style.left = item.left;
|
||||
centerDot.style.top = item.top;
|
||||
backgroundContainer.appendChild(centerDot);
|
||||
}
|
||||
});
|
||||
}
|
||||
}); // DOMContentLoaded回调结束
|
||||
// 确保这里没有残留的startAnimation函数定义
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 5.8 KiB |
Reference in New Issue
Block a user