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 相关文章推荐
HTML 自动伸缩的表格Table js实现
Apr 01 Javascript
JS 无法通过W3C验证的处理方法
Mar 09 Javascript
Javascript数组的排序 sort()方法和reverse()方法
Jun 04 Javascript
js倒计时小程序
Nov 05 Javascript
jQuery模拟黑客帝国矩阵效果实例
Jun 28 Javascript
JavaScript实现动态添加,删除行的方法实例详解
Jul 02 Javascript
通过vue-cli来学习修改Webpack多环境配置和发布问题
Dec 22 Javascript
jQuery实现右侧抽屉式在线客服功能
Dec 25 jQuery
浅谈Angular HttpClient简单入门
May 04 Javascript
vue.js父子组件通信动态绑定的实例
Sep 28 Javascript
深入学习JavaScript 高阶函数
Jun 11 Javascript
angula中使用iframe点击后不执行变更检测的问题
May 10 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最常用的ini函数分析 针对PHP.ini配置文件
2010/04/22 PHP
第4章 数据处理-php数组的处理-郑阿奇
2011/07/04 PHP
基于php在各种web服务器的运行模式详解
2013/06/03 PHP
PHP中大于2038年时间戳的问题处理方案
2015/03/03 PHP
Yii2中Restful API原理实例分析
2016/07/25 PHP
Ajax+PHP实现的删除数据功能示例
2019/02/12 PHP
使用Zookeeper分布式部署PHP应用程序
2019/03/15 PHP
用window.location.href实现刷新另个框架页面
2007/03/07 Javascript
javascript陷阱 一不小心你就中招了(字符运算)
2013/11/10 Javascript
用JavaScript实现用一个DIV来包装文本元素节点
2014/09/09 Javascript
JS实现同一个网页布局滑动门和TAB选项卡实例
2015/09/23 Javascript
jQuery学习笔记之Ajax用法实例详解
2015/12/01 Javascript
js/jq仿window文件夹框选操作插件
2017/03/08 Javascript
JavaScript函数、闭包、原型、面向对象学习笔记
2018/09/06 Javascript
微信小程序用canvas画图并分享
2020/03/09 Javascript
vue print.js打印支持Echarts图表操作
2020/11/13 Javascript
跟老齐学Python之Python安装
2014/09/12 Python
Python实现Const详解
2015/01/27 Python
Python中用字符串调用函数或方法示例代码
2017/08/04 Python
Python下调用Linux的Shell命令的方法
2018/06/12 Python
python 输入一个数n,求n个数求乘或求和的实例
2018/11/13 Python
利用python numpy+matplotlib绘制股票k线图的方法
2019/06/26 Python
用Python自动清理电脑内重复文件,只要10行代码(自动脚本)
2021/01/09 Python
纯CSS3实现给头像加个光芒四射且旋转的背景动画效果
2014/05/07 HTML / CSS
DBA数据库管理员JAVA程序员架构师必看
2016/02/07 面试题
客服实习的个人自我鉴定
2013/10/20 职场文书
护理专业自荐信
2013/12/03 职场文书
行政部总经理岗位职责
2014/01/04 职场文书
二手房购房意向书范本
2014/04/01 职场文书
知识竞赛拉拉队口号
2014/06/16 职场文书
党支部活动策划方案
2014/08/18 职场文书
企业领导对照检查材料
2014/08/20 职场文书
敲诈同学钱财检讨书范文
2014/11/18 职场文书
合同权益转让协议书模板
2014/11/18 职场文书
人才市场接收函
2015/01/30 职场文书
Java实现多线程聊天室
2021/06/26 Java/Android