mirror of
https://github.com/wanglin2/mind-map.git
synced 2026-02-28 13:57:48 +08:00
176 lines
5.1 KiB
JavaScript
176 lines
5.1 KiB
JavaScript
// 小地图类
|
||
class MiniMap {
|
||
/**
|
||
* javascript comment
|
||
* @Author: 王林25
|
||
* @Date: 2022-10-10 14:00:45
|
||
* @Desc: 构造函数
|
||
*/
|
||
constructor(opt) {
|
||
this.mindMap = opt.mindMap;
|
||
this.isMousedown = false;
|
||
this.mousedownPos = {
|
||
x: 0,
|
||
y: 0,
|
||
};
|
||
this.startViewPos = {
|
||
x: 0,
|
||
y: 0,
|
||
};
|
||
}
|
||
|
||
/**
|
||
* javascript comment
|
||
* @Author: 王林25
|
||
* @Date: 2022-10-10 14:00:43
|
||
* @Desc: 获取小地图相关数据
|
||
*/
|
||
getMiniMap() {
|
||
const svg = this.mindMap.svg;
|
||
const draw = this.mindMap.draw;
|
||
// 保存原始信息
|
||
const origWidth = svg.width();
|
||
const origHeight = svg.height();
|
||
const origTransform = draw.transform();
|
||
const elRect = this.mindMap.el.getBoundingClientRect();
|
||
// 去除放大缩小的变换效果
|
||
draw.scale(1 / origTransform.scaleX, 1 / origTransform.scaleY);
|
||
// 获取变换后的位置尺寸信息,其实是getBoundingClientRect方法的包装方法
|
||
const rect = draw.rbox();
|
||
// 将svg设置为实际内容的宽高
|
||
svg.size(rect.width, rect.height);
|
||
// 把实际内容变换
|
||
draw.translate(-rect.x + elRect.left, -rect.y + elRect.top);
|
||
// 克隆一份数据
|
||
const clone = svg.clone();
|
||
// 恢复原先的大小和变换信息
|
||
svg.size(origWidth, origHeight);
|
||
draw.transform(origTransform);
|
||
|
||
return {
|
||
svg: clone, // 思维导图图形的整体svg元素,包括:svg(画布容器)、g(实际的思维导图组)
|
||
svgHTML: clone.svg(), // svg字符串
|
||
rect: {
|
||
...rect, // 思维导图图形未缩放时的位置尺寸等信息
|
||
ratio: rect.width / rect.height, // 思维导图图形的宽高比
|
||
},
|
||
origWidth, // 画布宽度
|
||
origHeight, // 画布高度
|
||
scaleX: origTransform.scaleX, // 思维导图图形的水平缩放值
|
||
scaleY: origTransform.scaleY, // 思维导图图形的垂直缩放值
|
||
};
|
||
}
|
||
|
||
/**
|
||
* javascript comment
|
||
* @Author: 王林25
|
||
* @Date: 2022-10-10 14:05:51
|
||
* @Desc: 计算小地图的渲染数据
|
||
* boxWidth:小地图容器的宽度
|
||
* boxHeight:小地图容器的高度
|
||
*/
|
||
calculationMiniMap(boxWidth, boxHeight) {
|
||
let { svgHTML, rect, origWidth, origHeight, scaleX, scaleY } =
|
||
this.getMiniMap();
|
||
// 计算数据
|
||
let boxRatio = boxWidth / boxHeight;
|
||
let actWidth = 0;
|
||
let actHeight = 0;
|
||
if (boxRatio > rect.ratio) {
|
||
// 高度以box为准,缩放宽度
|
||
actHeight = boxHeight;
|
||
actWidth = rect.ratio * actHeight;
|
||
} else {
|
||
// 宽度以box为准,缩放高度
|
||
actWidth = boxWidth;
|
||
actHeight = actWidth / rect.ratio;
|
||
}
|
||
// svg图形的缩放及位置
|
||
let miniMapBoxScale = actWidth / rect.width;
|
||
let miniMapBoxLeft = (boxWidth - actWidth) / 2;
|
||
let miniMapBoxTop = (boxHeight - actHeight) / 2;
|
||
// 视口框大小及位置
|
||
let _rectX = rect.x - (rect.width * scaleX - rect.width) / 2;
|
||
let _rectX2 = rect.x2 + (rect.width * scaleX - rect.width) / 2;
|
||
let _rectY = rect.y - (rect.height * scaleY - rect.height) / 2;
|
||
let _rectY2 = rect.y2 + (rect.height * scaleY - rect.height) / 2;
|
||
let _rectWidth = rect.width * scaleX;
|
||
let _rectHeight = rect.height * scaleY;
|
||
let viewBoxStyle = {
|
||
left: 0,
|
||
top: 0,
|
||
right: 0,
|
||
bottom: 0,
|
||
};
|
||
viewBoxStyle.left =
|
||
Math.max(0, (-_rectX / _rectWidth) * actWidth) + miniMapBoxLeft + "px";
|
||
viewBoxStyle.right =
|
||
Math.max(0, ((_rectX2 - origWidth) / _rectWidth) * actWidth) +
|
||
miniMapBoxLeft +
|
||
"px";
|
||
|
||
viewBoxStyle.top =
|
||
Math.max(0, (-_rectY / _rectHeight) * actHeight) + miniMapBoxTop + "px";
|
||
viewBoxStyle.bottom =
|
||
Math.max(0, ((_rectY2 - origHeight) / _rectHeight) * actHeight) +
|
||
miniMapBoxTop +
|
||
"px";
|
||
return {
|
||
svgHTML, // 小地图html
|
||
viewBoxStyle, // 视图框的位置信息
|
||
miniMapBoxScale, // 视图框的缩放值
|
||
miniMapBoxLeft, // 视图框的left值
|
||
miniMapBoxTop, // 视图框的top值
|
||
};
|
||
}
|
||
|
||
/**
|
||
* javascript comment
|
||
* @Author: 王林25
|
||
* @Date: 2022-10-10 14:22:40
|
||
* @Desc: 小地图鼠标按下事件
|
||
*/
|
||
onMousedown(e) {
|
||
this.isMousedown = true;
|
||
this.mousedownPos = {
|
||
x: e.clientX,
|
||
y: e.clientY,
|
||
};
|
||
// 保存视图当前的偏移量
|
||
let transformData = this.mindMap.view.getTransformData();
|
||
this.startViewPos = {
|
||
x: transformData.state.x,
|
||
y: transformData.state.y,
|
||
};
|
||
}
|
||
|
||
/**
|
||
* javascript comment
|
||
* @Author: 王林25
|
||
* @Date: 2022-10-10 14:22:55
|
||
* @Desc: 小地图鼠标移动事件
|
||
*/
|
||
onMousemove(e, sensitivityNum = 5) {
|
||
if (!this.isMousedown) {
|
||
return;
|
||
}
|
||
let ox = e.clientX - this.mousedownPos.x;
|
||
let oy = e.clientY - this.mousedownPos.y;
|
||
// 在视图最初偏移量上累加更新量
|
||
this.mindMap.view.translateXTo(ox * sensitivityNum + this.startViewPos.x);
|
||
this.mindMap.view.translateYTo(oy * sensitivityNum + this.startViewPos.y);
|
||
}
|
||
|
||
/**
|
||
* javascript comment
|
||
* @Author: 王林25
|
||
* @Date: 2022-10-10 14:23:01
|
||
* @Desc: 小地图鼠标松开事件
|
||
*/
|
||
onMouseup() {
|
||
this.isMousedown = false;
|
||
}
|
||
}
|
||
|
||
export default MiniMap;
|