123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192 |
- export default {
- data() {
- return {
- deviation: 5, // 对齐误差范围
- xLines: [],
- yLines: []
- };
- },
- methods: {
- getMax(arr) {
- return Math.max.apply(null, arr);
- },
- getMin(arr) {
- return Math.min.apply(null, arr);
- },
- getPoints(item) {
- // 权重关系:先左后右
- // 具体:左上 > 左下 > 中心 > 右上 > 右下
- return [
- { x: item.x, y: item.y },
- { x: item.x, y: item.y + item.h },
- { x: item.x + item.w / 2, y: item.y + item.h / 2 },
- { x: item.x + item.w, y: item.y },
- { x: item.x + item.w, y: item.y + item.h }
- ];
- },
- rebuild(elements, curElement, actionType = "move") {
- this.clear();
- const curPoints = this.getPoints(curElement);
- const envPoints = elements
- .filter(item => item.id !== curElement.id)
- .map(item => this.getPoints(item));
- let fitPoints = [];
- // 提取可能的辅助线
- // y线分三种:左中右
- // x线分三种:上中下
- let xMaybeLines = {},
- yMaybeLines = {};
- const yPointTypes = {
- 0: "left",
- 1: "left",
- 2: "center",
- 3: "right",
- 4: "right"
- };
- const xPointTypes = {
- 0: "top",
- 1: "bottom",
- 2: "center",
- 3: "top",
- 4: "bottom"
- };
- envPoints.forEach(points => {
- points.forEach((point, pindex) => {
- // 中心点的对齐误差值取半数误差值
- const deviation = pindex === 2 ? this.deviation / 2 : this.deviation;
- const curPoint = curPoints[pindex];
- if (
- curPoint.x <= point.x + deviation &&
- curPoint.x >= point.x - deviation
- ) {
- if (!yMaybeLines[yPointTypes[pindex]])
- yMaybeLines[yPointTypes[pindex]] = [];
- yMaybeLines[yPointTypes[pindex]].push({
- pindex,
- x: point.x,
- y: Math.min(curPoint.y, point.y),
- h: Math.abs(curPoint.y - point.y),
- offset: Math.abs(curPoint.x - point.x)
- });
- }
- if (
- curPoint.y <= point.y + deviation &&
- curPoint.y >= point.y - deviation
- ) {
- if (!xMaybeLines[xPointTypes[pindex]])
- xMaybeLines[xPointTypes[pindex]] = [];
- xMaybeLines[xPointTypes[pindex]].push({
- pindex,
- x: Math.min(curPoint.x, point.x),
- y: point.y,
- w: Math.abs(curPoint.x - point.x),
- offset: Math.abs(curPoint.y - point.y)
- });
- }
- });
- });
- // 过滤误差过大的辅助线,即取误差最小的辅助线
- let yLines = [];
- Object.values(yMaybeLines).forEach(lines => {
- lines.sort((a, b) => a.offset - b.offset);
- const validX = lines[0].x;
- const validLines = lines.filter(line => line.x === validX);
- validLines.forEach(line => {
- const pindex = line.pindex;
- if (!fitPoints[pindex]) fitPoints[pindex] = {};
- fitPoints[pindex].x = validX;
- });
- yLines = [...yLines, ...validLines];
- });
- let xLines = [];
- Object.values(xMaybeLines).forEach(lines => {
- lines.sort((a, b) => a.offset - b.offset);
- const validY = lines[0].y;
- const validLines = lines.filter(line => line.y === validY);
- validLines.forEach(line => {
- const pindex = line.pindex;
- if (!fitPoints[pindex]) fitPoints[pindex] = {};
- fitPoints[pindex].y = validY;
- });
- xLines = [...xLines, ...validLines];
- });
- // 合并辅助线
- let yLinesMap = {};
- yLines.forEach(line => {
- if (!yLinesMap[line.x]) yLinesMap[line.x] = [];
- yLinesMap[line.x].push(line);
- });
- this.yLines = Object.values(yLinesMap).map(lines => {
- const lowH = this.getMax(lines.map(l => l.y + l.h));
- const topY = this.getMin(lines.map(l => l.y));
- return {
- left: lines[0].x + "px",
- top: topY + "px",
- height: lowH - topY + "px"
- };
- });
- let xLinesMap = {};
- xLines.forEach(line => {
- if (!xLinesMap[line.y]) xLinesMap[line.y] = [];
- xLinesMap[line.y].push(line);
- });
- this.xLines = Object.values(xLinesMap).map(lines => {
- const rightW = this.getMax(lines.map(l => l.x + l.w));
- const leftX = this.getMin(lines.map(l => l.x));
- return {
- left: leftX + "px",
- top: lines[0].y + "px",
- width: rightW - leftX + "px"
- };
- });
- // 计算自动贴合后的坐标点
- if (actionType === "move") {
- // 移动模式时,算偏移量
- // 按照getPoints中设置的点顺序权重进行计算
- // 只要获得结果,便停止计算
- let xOffset = null,
- yOffset = null;
- curPoints.forEach((point, pindex) => {
- const fitPoint = fitPoints[pindex] || {};
- if (xOffset === null && fitPoint.x) {
- xOffset = fitPoint.x - point.x;
- }
- if (yOffset === null && fitPoint.y) {
- yOffset = fitPoint.y - point.y;
- }
- });
- return {
- x: curElement.x + xOffset,
- y: curElement.y + yOffset,
- w: curElement.w,
- h: curElement.h
- };
- } else {
- // 变形模式时,算贴合点
- const newPoints = curPoints.map((point, pindex) => {
- const fitPoint = fitPoints[pindex] || {};
- return {
- x: Object.prototype.hasOwnProperty.call(fitPoint, "x")
- ? fitPoint.x
- : point.x,
- y: Object.prototype.hasOwnProperty.call(fitPoint, "y")
- ? fitPoint.y
- : point.y
- };
- });
- return {
- x: newPoints[0].x,
- y: newPoints[0].y,
- w: newPoints[4].x - newPoints[0].x,
- h: newPoints[4].y - newPoints[0].y
- };
- }
- },
- clear() {
- this.xLines = [];
- this.yLines = [];
- }
- }
- };
|