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 相关文章推荐
实现JavaScript中继承的三种方式
Oct 16 Javascript
js 格式化时间日期函数小结
Mar 20 Javascript
jQuery温习篇 强大的JQuery选择器
Apr 24 Javascript
JavaScript中的onerror事件概述及使用
Apr 01 Javascript
Jquery实现侧边栏跟随滚动条固定(兼容IE6)
Apr 02 Javascript
关于RequireJS的简单介绍即使用方法
Oct 20 Javascript
jquery实现图片上传前本地预览
Apr 28 jQuery
Layui 设置select下拉框自动选中某项的方法
Aug 14 Javascript
关于RxJS Subject的学习笔记
Dec 05 Javascript
jQuery模仿ToDoList实现简单的待办事项列表
Dec 30 jQuery
jquery实现进度条状态展示
Mar 26 jQuery
JS highcharts实现动态曲线代码示例
Oct 16 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
人族 Terran 基本策略
2020/03/14 星际争霸
德生PL330测评
2021/03/02 无线电
PHP中文件上传的一个问题
2010/09/04 PHP
基于在生产环境中使用php性能测试工具xhprof的详解
2013/06/03 PHP
php计算两个日期相差天数的方法
2015/03/14 PHP
PHP实现过滤各种HTML标签
2015/05/17 PHP
PHP观察者模式示例【Laravel框架中有用到】
2018/06/15 PHP
jquery弹出框的用法示例(一)
2013/08/26 Javascript
javaScript 页面自动加载事件详解
2014/02/10 Javascript
Jquery自定义button按钮的几种方法
2014/06/11 Javascript
jQuery DOM删除节点操作指南
2015/03/03 Javascript
jQuery插件开发精品教程(让你的jQuery更上一个台阶)
2015/11/07 Javascript
基于JavaScript实现Json数据根据某个字段进行排序
2015/11/24 Javascript
基于javascript实现全国省市二级联动下拉选择菜单
2016/01/28 Javascript
详解Webwork中Action 调用的方法
2016/02/02 Javascript
AngularJS之依赖注入模拟实现
2016/08/19 Javascript
jQuery常用样式操作实例分析(获取、设置、追加、删除、判断等)
2016/09/08 Javascript
JS前向后瞻正则表达式定义与用法示例
2016/12/27 Javascript
简单通过settimeout看javascript的运行机制
2019/05/10 Javascript
js 获取本周、上周、本月、上月、本季度、上季度的开始结束日期
2020/02/01 Javascript
Python基于回溯法解决01背包问题实例
2017/12/06 Python
Python 绘图库 Matplotlib 入门教程
2018/04/19 Python
对python requests发送json格式数据的实例详解
2018/12/19 Python
Python中捕获键盘的方式详解
2019/03/28 Python
Python partial函数原理及用法解析
2019/12/11 Python
英国高街品牌:Miss Selfridge(塞尔弗里奇小姐)
2016/09/21 全球购物
广告语设计及教案
2014/03/21 职场文书
酒店开业庆典主持词
2014/03/21 职场文书
乡镇党员干部群众路线对照检查材料思想汇报
2014/09/28 职场文书
实习单位证明范例
2014/11/17 职场文书
布达拉宫导游词
2015/02/02 职场文书
会议室使用管理制度
2015/08/06 职场文书
生日祝酒词大全
2015/08/10 职场文书
升学宴学生致辞
2015/09/29 职场文书
500字作文之难忘的同学
2019/12/20 职场文书
浅谈css清除浮动(clearfix和clear)的用法
2023/05/21 HTML / CSS