Skip to content

Commit

Permalink
完成
Browse files Browse the repository at this point in the history
  • Loading branch information
wanglin2 committed Jun 15, 2022
1 parent 5a532a9 commit a7c1e38
Show file tree
Hide file tree
Showing 3 changed files with 97 additions and 59 deletions.
33 changes: 28 additions & 5 deletions src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -51,20 +51,43 @@ const reRender = () => {
onDragMove();
};
// 矩形移动事件
const onDragMove = () => {
// 计算路径
const computeRoutes = (easy) => {
// 计算出所有可能的点
let { startPoint, endPoint, fakeStartPoint, fakeEndPoint, points } =
computedProbablyPoints(startPos.value, endPos.value);
computedProbablyPoints(startPos.value, endPos.value, easy);
// 绘制辅助点
drawTestDots(points);
let routes = [];
if (userAStar.value) {
// 使用A*算法
routes = aStar.start(fakeStartPoint, fakeEndPoint, points);
routes = aStar.start(
easy ? startPoint : fakeStartPoint,
easy ? endPoint : fakeEndPoint,
points
);
} else {
// 使用回溯算法找出其中一条路径
routes = useDFS(fakeStartPoint, fakeEndPoint, points);
routes = useDFS(
easy ? startPoint : fakeStartPoint,
easy ? endPoint : fakeEndPoint,
points
);
}
return {
startPoint,
endPoint,
routes,
};
};
// 矩形移动事件
const onDragMove = () => {
let { startPoint, endPoint, routes } = computeRoutes();
// 如果没有计算出来路径,那么就以宽松模式再计算一次可能的点,也就是允许和元素交叉
if (routes.length <= 0) {
let res = computeRoutes(true);
routes = res.routes;
}
// 更新连线元素
updateLine(
Expand Down
18 changes: 9 additions & 9 deletions src/draw.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,15 @@ export const init = (container, onDragMove) => {
// 创建图层
layer = new Konva.Layer();

line = new Konva.Line({
points: [],
stroke: "#e6a23c",
strokeWidth: 2,
lineJoin: "round",
});

layer.add(line);

// 创建两个矩形
let rect1 = new Konva.Rect({
x: 400,
Expand Down Expand Up @@ -49,15 +58,6 @@ export const init = (container, onDragMove) => {

layer.add(rect2);

line = new Konva.Line({
points: [],
stroke: "#e6a23c",
strokeWidth: 2,
lineJoin: "round",
});

layer.add(line);

// 图层添加到舞台
stage.add(layer);

Expand Down
105 changes: 60 additions & 45 deletions src/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ let rect1,
let rect1X, rect1Y, rect1W, rect1H, rect2X, rect2Y, rect2W, rect2H;

const MIN_DISTANCE = 30;
let easyMode = false;

// 保存矩形元素
export const setRect = (r1, r2) => {
Expand All @@ -14,7 +15,7 @@ export const setRect = (r1, r2) => {
};

// 计算所有可能经过的点
export const computedProbablyPoints = (startPos, endPos) => {
export const computedProbablyPoints = (startPos, endPos, easy) => {
// 保存矩形的尺寸、位置信息
rect1X = rect1.x();
rect1Y = rect1.y();
Expand All @@ -26,44 +27,20 @@ export const computedProbablyPoints = (startPos, endPos) => {
rect2W = rect2.width();
rect2H = rect2.height();

// 起终点
switch (startPos) {
case "left":
startPoint = [rect1X, rect1Y + rect1H / 2]; // 左
break;
case "top":
startPoint = [rect1X + rect1W / 2, rect1Y]; // 上
break;
case "right":
startPoint = [rect1X + rect1W, rect1Y + rect1H / 2]; // 右
break;
case "bottom":
startPoint = [rect1X + rect1W / 2, rect1Y + rect1H]; // 下
break;
default:
break;
}
// 设置起终点坐标
setStartEndPos(startPos, endPos);

switch (endPos) {
case "left":
endPoint = [rect2X, rect2Y + rect2H / 2]; // 左
break;
case "top":
endPoint = [rect2X + rect2W / 2, rect2Y]; // 上
break;
case "right":
endPoint = [rect2X + rect2W, rect2Y + rect2H / 2]; // 右
break;
case "bottom":
endPoint = [rect2X + rect2W / 2, rect2Y + rect2H]; // 下
break;
default:
break;
}
// 是否是宽松模式
easyMode = easy;

// 保存所有可能经过的点
let points = [];

// 宽松模式则把真正的起点和终点加入点列表中
if (easy) {
points.push(startPoint, endPoint);
}

// 伪起点:经过起点且垂直于起点所在边的线与包围框线的交点
let fakeStartPoint = findStartNextOrEndPrePoint(rect1, startPoint);
points.push(fakeStartPoint);
Expand Down Expand Up @@ -141,6 +118,44 @@ export const computedProbablyPoints = (startPos, endPos) => {
};
};

// 设置起终点坐标
export const setStartEndPos = (startPos, endPos) => {
// 起终点
switch (startPos) {
case "left":
startPoint = [rect1X, rect1Y + rect1H / 2]; // 左
break;
case "top":
startPoint = [rect1X + rect1W / 2, rect1Y]; // 上
break;
case "right":
startPoint = [rect1X + rect1W, rect1Y + rect1H / 2]; // 右
break;
case "bottom":
startPoint = [rect1X + rect1W / 2, rect1Y + rect1H]; // 下
break;
default:
break;
}

switch (endPos) {
case "left":
endPoint = [rect2X, rect2Y + rect2H / 2]; // 左
break;
case "top":
endPoint = [rect2X + rect2W / 2, rect2Y]; // 上
break;
case "right":
endPoint = [rect2X + rect2W, rect2Y + rect2H / 2]; // 右
break;
case "bottom":
endPoint = [rect2X + rect2W / 2, rect2Y + rect2H]; // 下
break;
default:
break;
}
};

// 检查一个点是否在一条线段上
export const checkPointIsInSegment = (point, seg) => {
if (point[0] === seg[0][0]) {
Expand Down Expand Up @@ -255,14 +270,14 @@ export const getNextPoints = (point, points) => {

// 找出水平或垂直方向上最近的点
export const getNextPoint = (x, y, list, dir) => {
let index = dir === "x" ? 0 : 1;// 求水平方向上最近的点,那么它们y坐标都是相同的,要比较x坐标,反之亦然
let index = dir === "x" ? 0 : 1; // 求水平方向上最近的点,那么它们y坐标都是相同的,要比较x坐标,反之亦然
let value = dir === "x" ? x : y;
let nextLeftTopPoint = null;
let nextRIghtBottomPoint = null;
for (let i = 0; i < list.length; i++) {
let cur = list[i];
// 检查当前点和目标点的连线是否穿过起终点元素
if (checkLineThroughElements([x, y], cur)) {
// 检查当前点和目标点的连线是否穿过起终点元素,宽松模式下直接跳过该检测
if (!easyMode && checkLineThroughElements([x, y], cur)) {
continue;
}
// 左侧或上方最近的点
Expand Down Expand Up @@ -304,10 +319,10 @@ export const checkLineThroughElements = (a, b) => {
for (let i = 0; i < rects.length; i++) {
let rect = rects[i];
if (
minY >= rect.y() &&
minY <= rect.y() + rect.height() &&
minX <= rect.x() + rect.width() &&
maxX >= rect.x()
minY > rect.y() - MIN_DISTANCE &&
minY < rect.y() + rect.height() + MIN_DISTANCE &&
minX < rect.x() + rect.width() + MIN_DISTANCE &&
maxX > rect.x() - MIN_DISTANCE
) {
return true;
}
Expand All @@ -317,10 +332,10 @@ export const checkLineThroughElements = (a, b) => {
for (let i = 0; i < rects.length; i++) {
let rect = rects[i];
if (
minX >= rect.x() &&
minX <= rect.x() + rect.width() &&
minY <= rect.y() + rect.height() &&
maxY >= rect.y()
minX > rect.x() - MIN_DISTANCE &&
minX < rect.x() + rect.width() + MIN_DISTANCE &&
minY < rect.y() + rect.height() + MIN_DISTANCE &&
maxY > rect.y() - MIN_DISTANCE
) {
return true;
}
Expand Down

0 comments on commit a7c1e38

Please sign in to comment.