ant design实现圈选功能


Posted in Javascript onDecember 17, 2019

 Ant Design是一款十分出色的的UI设计组件,Ant Design电脑版界面美观大方,功能强劲实用,软件包含整套开发和设计资源和工具,丰富的React UI组件,能够为前端UI设计提供了新的解决方案,非常的方便实用哦

由于同事离职,公司缺人,他的工作便交接到我的手里了,我一个android开发者,以前也从来没做过web端开发啊,没办法,领导交代的任务硬着头皮也得接下来啊!拿到手上,做的第一个功能,便是存储计划,需要实现可按照天、周、月存储,并且以鼠标圈选的形式实现,接下来附上自己的实现效果图:

ant design实现圈选功能

实现流程

本来拿到这个任务的时候,自己是想用Grid实现的,但是看到官网上面的一句话,直接打消了我的念头,官网是这么说的:

也就是说用Grid每一行最多显示24个单元格,这个完全达不到我的要求,因为我每行需要显示25个单元格(每行的title+24小时),我决定还是自己用div画吧。

1.先画单元格

画单元格分成第一行和剩余的行两种:

ant design实现圈选功能

第一行组件我们定义为ColumsTitle:

循环里面的每一个div其实代表的是每一个单元格。

//标题列组件
const ColumsTitle = () => {
 const colums = [];
 for (let i = 0; i < 25; i++) {
  if (i == 0) {
   colums.push(<div key={i} className={styles["columns-title-border"]}></div>);
  } else {
   colums.push(<div key={i} className={styles["columns-border-none"]}>{i - 1}</div>);
  }
 }
 return colums;
}

剩余行组件,我们定义为Colums:

//列组件
class Colums extends PureComponent {
 render() {
  const colums = [];
  for (let i = 0; i < 25; i++) {
   if (i == 0) {
    colums.push(<div key={i} className={styles["columns-title-border"]}>{this.props.rowName}</div>);
   } else {
    colums.push(<div id={this.props.rowName + i} key={this.props.rowName + i} className={styles["columns-border"]} name="chooseDiv"></div>);
   }
  }
  return colums;
 }
}

最后一个就是整体上的组件了,我们叫做Rows:

// 行组件
const Rows = (props) => {
 const rows = [];
 var rowLength = 1;
 var rowName = "";
 if (props.saveType == "1") {
  rowLength = 2;
 } else if (props.saveType == "2") {
  rowLength = 8;
 } else if (props.saveType == "3") {
  rowLength = 32;
 }
 for (let i = 0; i < rowLength; i++) {
  rowName = formatRowName(props, i);
  if (i == 0) {
   rows.push(<Row key={i}>
    <div className={styles["columns-title-out-margin"]}><ColumsTitle/></div>
   </Row>);
  } else {
   rows.push(<Row key={i}>
    <div className={styles["columns-title-out"]}><Colums saveType={props.saveType} rowName={rowName}/>
    </div>
   </Row>);
  }
 }
 return rows;
};

我们渲染到SavePlan这个组件里面:

export default class SavePlan extends PureComponent {
 constructor(props) {
  super(props);
  this.state = {
   saveType: "1"//1 按天存储 2 按周存储 3 按月存储
  }
 }
 handleRadioChange = e => {
  this.setState({saveType: e.target.value});
 };
 onChange(value) {
  console.log('changed', value);
 }
 render() {
  return (
   <PageHeaderWrapper>
    <div>
     <h1>存储计划</h1>
     <div className={styles["title-row"]}>
      <Radio.Group defaultValue="1" size="large" onChange={this.handleRadioChange}>
       <Radio.Button value="1">天存储</Radio.Button>
       <Radio.Button value="2">周存储</Radio.Button>
       <Radio.Button value="3">月存储</Radio.Button>
      </Radio.Group>
      <div className={styles["right-div"]}>
       存储周期:<InputNumber min={1} max={10} defaultValue={3} onChange={this.onChange}/>(天)
       <div className={styles["title-row"]}>
        <Button type="primary" className={styles.btn}>确定</Button>
        <Button className={styles.btn}>取消</Button>
       </div>
      </div>
     </div>
     <Rows saveType={this.state.saveType}>
     </Rows>
    </div>
   </PageHeaderWrapper>
  );
 }
}

到这一步,我们在页面其实已经可以看到整个布局了,但是还没有添加鼠标事件,还没有圈选功能,接下来我们看鼠标事件。

2.鼠标事件

我们这里主要用到了鼠标的三个事件:onmousedown、onmousemove、onmouseup。
我们首先设定可选的单元格,标题设定为不可选:

 -webkit-user-select: none; /* 禁止 DIV 中的文本被鼠标选中 */
  -moz-user-select: none; /* 禁止 DIV 中的文本被鼠标选中 */
  -ms-user-select: none; /* 禁止 DIV 中的文本被鼠标选中 */
  user-select: none; /* 禁止 DIV 中的文本被鼠标选中 */

思路就是:获取鼠标按下时的坐标,并判断是否在可选区域内,若在那么就添加一个div(也就是我们的圈选框),图解如下:

ant design实现圈选功能

获取可选单元格数组

//可选单元格
 var fileNodes = document.getElementsByName("chooseDiv");

获取鼠标点击位置的坐标

var evt = window.event||arguments[0];
 //加上滚动距离
 var scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
 var scrollY = document.documentElement.scrollTop || document.body.scrollTop;
 var startX =evt.pageX || evt.clientX + scrollX;
 var startY =evt.pageY || evt.clientY + scrollY;

判断可选框坐标范围

//判断鼠标点击的点是否在可选框内部,主要是判断第一个可选框的左上角坐标和最后一个圈选框的右下角坐标
 if ((startX >= firstDivOffsetLeft && startY >= firstDivOffsetTop) && (startX <= lastDivOffsetLeft && startY <= lastDivOffsetTop))

判断鼠标点击在哪一个单元格里面,并获取该单元格左上角坐标

//判断鼠标点击的点在哪一个div里面,然后更改圈选框的左上角坐标为该div的左上角坐标
  for (var i = 0; i < fileNodes.length; i++) {
   if ((startX >= getOffsetLeft(fileNodes[i]) && startX <= getOffsetLeft(fileNodes[i]) + fileNodes[i].offsetWidth) && (startY >= getOffsetTop(fileNodes[i]) && startY <= getOffsetTop(fileNodes[i]) + fileNodes[i].offsetHeight)) {
    console.log("在内部");
    startX = getOffsetLeft(fileNodes[i]);
    startY = getOffsetTop(fileNodes[i]);
    break;
   } else {
    console.log("不在内部");
   }
  }

创建圈选框,并更改圈选框的左上角坐标为该单元格的左上角坐标

//创建选择框
  selDiv = document.createElement("div");
  selDiv.style.cssText = "position:absolute;width:0px;height:0px;font-size:0px;margin:0px;padding:0px;border:1px dashed #0099FF;background-color:#C3D5ED;z-index:1000;filter:alpha(opacity:60);opacity:0.6;display:none;";
  selDiv.id = "selectDiv";
  document.body.appendChild(selDiv);
  selDiv.style.left = startX + "px";
  selDiv.style.top = startY + "px";

鼠标移动过程中,改变圈选框的宽高;

evt = window.event || arguments[0];
   if (isSelect) {
    if (selDiv.style.display == "none") {
     selDiv.style.display = "";
    }
    //加上鼠标滚动距离
    var _scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
    var _scrollY = document.documentElement.scrollTop || document.body.scrollTop;
    _x = evt.pageX || evt.clientX + _scrollX;
    _y = evt.pageY || evt.clientY + _scrollY;

    selDiv.style.left = Math.min(_x, startX) + "px";
    selDiv.style.top = Math.min(_y, startY) + "px";
    selDiv.style.width = Math.abs(_x - startX) + "px";
    selDiv.style.height = Math.abs(_y - startY) + "px";

鼠标抬起的时候,计算被圈选的单元格并更改样式;

var _l = selDiv.offsetLeft, _t = selDiv.offsetTop;
  var _w = selDiv.offsetWidth, _h = selDiv.offsetHeight;

  for (var i = 0; i < selList.length; i++) {
   var sl = selList[i].offsetWidth + getOffsetLeft(selList[i]);
   var st = selList[i].offsetHeight + getOffsetTop(selList[i]);
   if (sl > _l && st > _t && getOffsetLeft(selList[i]) < _l + _w && getOffsetTop(selList[i]) < _t + _h) {
    if (selList[i].className.indexOf("seled") == -1) {
     selList[i].className = styles["columns-borderseled"];
    }
    else {
     selList[i].className = styles["columns-border"];
    }
   }
  }

其他工具方法

const getOffsetLeft = function (obj) {
 var tmp = obj.offsetLeft;
 var node = obj.offsetParent;
 while (node != null) {
  tmp += node.offsetLeft;
  node = node.offsetParent;
 }
 return tmp;
}
const getOffsetTop = function (obj) {
 var tmp = obj.offsetTop;
 var node = obj.offsetParent;
 while (node != null) {
  tmp += node.offsetTop;
  node = node.offsetParent;
 }
 return tmp;
}

总结

以上所述是小编给大家介绍的ant design实现圈选功能,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!

Javascript 相关文章推荐
Jquery乱码的一次解决过程 图解教程
Feb 20 Javascript
extjs4 treepanel动态改变行高度示例
Dec 17 Javascript
判断客户浏览器是否支持cookie的示例代码
Dec 23 Javascript
jquery获取checkbox的值并post提交
Jan 14 Javascript
Css3制作变形与动画效果
Jul 24 Javascript
EasyUi中的Combogrid 实现分页和动态搜索远程数据
Apr 01 Javascript
AngularJS基础 ng-href 指令用法
Aug 01 Javascript
javascript数据结构中栈的应用之符号平衡问题
Apr 11 Javascript
JS实现加载和读取XML文件的方法详解
Apr 24 Javascript
浅谈js的解析顺序 作用域 严格模式
Oct 23 Javascript
vue实现浏览器全屏展示功能
Nov 27 Javascript
javascript实现左右缓动动画函数
Nov 25 Javascript
15分钟学会vue项目改造成SSR(小白教程)
Dec 17 #Javascript
微信小程序获取复选框全选反选选中的值(实例代码)
Dec 17 #Javascript
微信小程序实现多选框全选与反全选及购物车中删除选中的商品功能
Dec 17 #Javascript
TypeScript高级用法的知识点汇总
Dec 17 #Javascript
微信小程序 (地址选择1)--选取搜索地点并显示效果
Dec 17 #Javascript
JS检索下拉列表框中被选项目的索引号(selectedIndex)
Dec 17 #Javascript
JS实现打字游戏
Dec 17 #Javascript
You might like
用PHP制作静态网站的模板框架(一)
2006/10/09 PHP
关于PHP定时发送服务的解决办法
2017/04/23 PHP
PHP从零开始打造自己的MVC框架之类的自动加载实现方法详解
2019/06/03 PHP
ajax 文件上传应用简单实现
2009/03/03 Javascript
jQuery中removeProp()方法用法实例
2015/01/05 Javascript
js实现鼠标移到链接文字弹出一个提示层的方法
2015/05/11 Javascript
JS实现定时自动关闭DIV层提示框的方法
2015/05/11 Javascript
JS实现带圆弧背景渐变效果的导航菜单代码
2015/10/13 Javascript
JS实现选中当前菜单后高亮显示的导航条效果
2015/10/15 Javascript
JavaScript中日期的相关操作方法总结
2015/10/24 Javascript
两种方法解决javascript url post 特殊字符转义 + &amp; #
2016/04/13 Javascript
有关JavaScript中call()和apply() 的一些理解
2016/05/20 Javascript
bootstrap实现动态进度条效果
2017/03/08 Javascript
移动端使用localResizeIMG4压缩图片
2017/04/22 Javascript
详解node HTTP请求客户端 - Request
2017/05/05 Javascript
详解webpack+angular2开发环境搭建
2017/06/28 Javascript
vue实现tab切换外加样式切换方法
2018/03/16 Javascript
[56:58]VP vs Optic 2018国际邀请赛小组赛BO2 第一场 8.16
2018/08/17 DOTA
Python3 入门教程 简单但比较不错
2009/11/29 Python
python实现在目录中查找指定文件的方法
2014/11/11 Python
浅谈Python中chr、unichr、ord字符函数之间的对比
2016/06/16 Python
使用Django和Python创建Json response的方法
2018/03/26 Python
python实现最长公共子序列
2018/05/22 Python
使用TensorFlow对图像进行随机旋转的实现示例
2020/01/20 Python
Python for循环通过序列索引迭代过程解析
2020/02/07 Python
Html5上传图片 移动端、PC端通用代码
2016/06/08 HTML / CSS
处理textarea中的换行和空格
2019/12/12 HTML / CSS
Java多态性的定义以及类型
2014/09/16 面试题
ORACLE第二个十问
2013/12/14 面试题
12月红领巾广播稿
2014/02/13 职场文书
上课睡觉检讨书300字
2014/11/18 职场文书
仓管员岗位职责
2015/02/03 职场文书
实习单位推荐信
2015/03/27 职场文书
工作收入证明范本
2015/06/12 职场文书
2021年pycharm的最新安装教程及基本使用图文详解
2021/04/03 Python
浅谈Redis主从复制以及主从复制原理
2021/05/29 Redis