距离提示辅助线so easy

简介: 距离提示辅助线so easy!!!距离提示辅助线so easy!!!距离提示辅助线so easy!!!距离提示辅助线so easy!!!

距离提示辅助线

位置与大小格式

{
   
x:100,
y:200,
width:300,
height:400
}

一个点到一个矩形的距离

  • 点到左边

  • 点到右边

  • 点到上边

  • 点到下边

一个矩形与另一个矩形的距离

  • 矩形 1 的左边 vs 矩形 2 的左边,矩形 2 的右边

  • 矩形 1 的右边 vs 矩形 2 的左边,矩形 2 的右边

  • 矩形 1 的上边 vs 矩形 2 的上边,矩形 2 的下边

  • 矩形 1 的下边 vs 矩形 2 的上边,矩形 2 的下边

取矩形 1 每个情况的最小值就是对应边到矩形 2 的距离

function getXDistance(props, rect) {
   
  return [
    Math.abs(rect.x - props.x),
    Math.abs(rect.x + rect.width - props.x),
    Math.abs(rect.x - (props.x + props.width)),
    Math.abs(rect.x + rect.width - (props.x + props.width))
  ];
}
function getYDistance(props, rect) {
   
  return [
    Math.abs(rect.y - props.y),
    Math.abs(rect.y + rect.height - props.y),
    Math.abs(rect.y - (props.y + props.height)),
    Math.abs(rect.y + rect.height - (props.y + props.height))
  ];
}

判断一个矩形是否在附近

参考矩形另一个矩形的距离在 nearD 范围内即在附近,绘制对应的辅助线.
当某个边重合,距离为 0 不进行绘制。

//附近距离
let nearD = 160;
export function setNearDistance(d) {
   
  nearD = d;
}
/**
 * 检查组件是否在选框范围内
 * @param {Object} props 组件位置大小数据
 * @returns {Boolean}
 */
function checkNear(props, rect) {
   
  let xD = getXDistance(props, rect);
  let yD = getYDistance(props, rect);
  if (Math.min(...xD) <= nearD || Math.min(...yD) <= nearD) {
   
    return true;
  }

  return false;
}

interactJs 拖拉拽改变大小和位置

文档地址如下:

https://interactjs.io/docs/

具体代码地址

https://github.com/xiaolidan00/distanceTipLine

策略模式获取最短距离


 const XLine = {
   
  0: (props, rect) => {
   
    return Math.min(rect.x, props.x);
  },
  1: (props, rect) => {
   
    return Math.min(rect.x + rect.width, props.x);
  },
  2: (props, rect) => {
   
    return Math.min(rect.x, props.x + props.width);
  },
  3: (props, rect) => {
   
    return Math.min(rect.x + rect.width, props.x + props.width);
  }
};

const YLine = {
   
  0: (props, rect) => {
   
    return Math.min(rect.y, props.y);
  },
  1: (props, rect) => {
   
    return Math.min(rect.y + rect.height, props.y);
  },
  2: (props, rect) => {
   
    return Math.min(rect.y, props.y + props.height);
  },
  3: (props, rect) => {
   
    return Math.min(rect.y + rect.height, props.y + props.height);
  }
};

当前矩形需要绘制包围框,包括:相对于父容器的上下边界和距离,左右边界,宽高

let posH = [
    //左距离
    {
   
      style: {
   
        left: 0,
        top: top + height * 0.5 - 16 + 'px',
        width: left + 'px'
      },
      value: left
    },
    //右距离
    {
   
      style: {
   
        right: 0,
        top: top + height * 0.5 - 16 + 'px',
        width: screenWidth - (left + width) + 'px'
      },
      value: screenWidth - (left + width)
    },
    //宽度
    {
   
      style: {
   
        left: left + 'px',
        top: top + height * 0.5 - 16 + 'px',
        width: width + 'px',
        justifyContent: 'flex-start',
        border: 'none',
        paddingLeft: '10px'
      },
      value: height
    },
    //上边界
    {
   
      style: {
   
        left: 0,
        top: top + 'px',
        width: '100%',
        borderBottom: 'dashed 1px rgb(37, 124, 245)'
      }
    },
    //下边界
    {
   
      style: {
   
        left: 0,
        top: top + height + 'px',
        width: '100%',
        borderBottom: 'dashed 1px rgb(37, 124, 245)'
      }
    }
  ];
  let posV = [
    //上距离
    {
   
      style: {
   
        left: left + width * 0.5 + 'px',
        top: 0,
        height: top + 'px'
      },
      value: top
    },
    //下距离
    {
   
      style: {
   
        left: left + width * 0.5 + 'px',
        bottom: 0,
        height: screenHeight - (top + height) + 'px'
      },
      value: screenHeight - (top + height)
    },
    //高度
    {
   
      style: {
   
        left: left + width * 0.5 + 'px',
        top: top + 'px',
        height: height + 'px',
        alignItems: 'flex-start',
        border: 'none',

        paddingTop: '10px'
      },
      value: height
    },
    //左边界
    {
   
      style: {
   
        left: left + 'px',
        top: 0,
        height: '100%',
        borderLeft: 'dashed 1px rgb(37, 124, 245)'
      }
    },
    //右边界
    {
   
      style: {
   
        left: left + width + 'px',
        top: 0,
        height: '100%',
        borderLeft: 'dashed 1px rgb(37, 124, 245)'
      }
    }
  ];

获取辅助线:遍历所有组件,对比最短距离,在范围内则加入辅助线



/**
 *
 * @param {Object} activeElement 参考元素
 * @param {Array} elmts 元素list
 * @param {DOM} el 父元素id
 * @returns {Object} {h:横向辅助线,v:纵向辅助线}
 */
export function getGuideLine(activeElement, elmts, el) {
   
  let {
    x: left, y: top, width, height } = activeElement.props;
  let container = document.querySelector(el);
  let screenWidth = container.offsetWidth;
  let screenHeight = container.offsetHeight;
  let posH...
  let posV...
  let nearLineH = [];
  let nearLineV = [];
  elmts.forEach((elmt) => {
   
    if (elmt.id != activeElement.id && checkNear(elmt.props, activeElement.props)) {
   
      //横向距离
      let xD = getXDistance(elmt.props, activeElement.props);

      let isLeft1 = false;
      let isLeft2 = false;
      for (let i = 0; i < xD.length; i++) {
   
        let d = xD[i];
        //去重
        if (i == 2 && isLeft1) {
   
          continue;
        }
        if (i == 3 && isLeft2) {
   
          continue;
        }
        if (d > 0 && d <= nearD) {
   
          let s = XLine[i](elmt.props, activeElement.props, d);
          if (i == 0) {
   
            isLeft1 = true;
          }
          if (i == 1) {
   
            isLeft2 = true;
          }
          nearLineH.push({
   
            style: {
   
              left: s + 'px',
              top: elmt.props.y + elmt.props.height * 0.5 - 16 + 'px',
              width: d + 'px'
            },
            value: d
          });
        }
      }

      let yD = getYDistance(elmt.props, activeElement.props);

      let isTop1 = false;
      let isTop2 = false;
      for (let i = 0; i < yD.length; i++) {
   
        let d = yD[i];
         //去重
        if (i == 2 && isTop1) {
   
          continue;
        }
        if (i == 3 && isTop2) {
   
          continue;
        }
        if (d > 0 && d <= nearD) {
   
          let s = YLine[i](elmt.props, activeElement.props, d);
          if (i == 0) {
   
            isTop1 = true;
          }
          if (i == 1) {
   
            isTop2 = true;
          }
          nearLineV.push({
   
            style: {
   
              left: elmt.props.x + elmt.props.width * 0.5 + 'px',
              top: s + 'px',
              height: d + 'px'
            },
            value: d
          });
        }
      }
    }
  });

  return {
   
    h: posH.concat(nearLineH),
    v: posV.concat(nearLineV)
  };
}
相关文章
|
11月前
|
小程序
小程序右上角的胶囊颜色怎么修改?
小程序右上角的胶囊颜色怎么修改?
163 0
|
5月前
VSCode如何自动换行,右侧换行间距长度,隐藏右侧代码预览(Minimap代码缩略图滚动条),比对代码差异窗口也自动换行
VSCode如何自动换行,右侧换行间距长度,隐藏右侧代码预览(Minimap代码缩略图滚动条),比对代码差异窗口也自动换行
|
4月前
|
存储 Cloud Native Linux
OpenCV鼠标操作(画红色方框截取图像)
OpenCV鼠标操作(画红色方框截取图像)
|
5月前
LabVIEW当鼠标悬停在图形曲线上时显示坐标
LabVIEW当鼠标悬停在图形曲线上时显示坐标
65 1
|
Python
在Gazebo中添加悬浮模型方法 / Gazebo中模型如何不因重力下落:修改sdf、urdf模型
在使用ros做仿真实验时,有时会需要在空间中添加一个模型文件,使之悬浮在空间中的某个坐标,但是往往会因为重力原因,模型会直接掉落在地上
596 0
|
编解码 前端开发 PHP
悬浮坐标解决方案:如何在图片获取xy鼠标位置和增加标注信息
悬浮坐标解决方案:如何在图片获取xy鼠标位置和增加标注信息
154 0
|
Windows
windows自带的比微信好用的截图工具:截取任意形状图片,标尺画直线,窗口图精准截取
windows自带的比微信好用的截图工具:截取任意形状图片,标尺画直线,窗口图精准截取
369 0
|
测试技术 Android开发 计算机视觉
|
存储
使用Dynamic Data Display控件绘图时无法删除已经画好的曲线
最近在使用Dynamic Data Display画图的时候发现,多次画图时,之前画的图无法清除,造成图像混乱。找了好久发现这样可以消除。 在调用AddLineGraph时,使用一个全局的变量来存储这个方法返回的对象(LineGraph), 点击...
920 0