JavaScript制作简单的框选图表

故事背景:这几天遇到一个客户,是做会议记录的,每次会议过程中,都会有特定设备记录下讲话人的位置以角度值显示。他给我角度值,让我给他做一个图表来展示每个人的一个大概位置。

客户想到的是用 Echarts 图表来做,我首先想到的也是用 Echarts ,但是思考了他的要求以后,发现就一个简单的框选图表用 Echarts 来做是不是大材小用了,而且还要导入那么多的没用的代码。

于是我想到了用 canvas 画布来仿着做,但又考虑了一下, canvas 操作起来不顺手;究竟可不可以用普通的css结合 javascript 来把它做出来呢?此番思考验证了:任何事情一定要多动脑,才能 碰到更简单的解决问题的方式。

考虑到也许某天大家用得着,所以发布出来。注:拥有可移植性,可移到页面任何位置,效果不会改变

先看最终效果吧:

图一:

图二:

这个小东西会涉及的知识点不多,归纳一下: js的三角函数 、 CSS3的transform 、 鼠标的坐标轴XY的计算 ...啊哈,差不多大体就这三方面的知识吧,如果你都只是有过了解也没关系,因为都只用的到皮毛所以不必担心。但是如果完全没听过,那就请您再去了解一下这方面知识。

代码区域

<!doctype html>
<html>
<head>
 <meta charset="utf-8" />
 <title>仿Echarts图表</title>
 <style>
 * {
  padding:0;
  margin:0;
 }
 #getcharts {
  position:relative;
  width:510px;
  height:510px; 

 }
 #wrapcharts {
  list-style:none;
  height:500px;
  width:500px;
  border:2px solid #aaa;
  border-radius:50%;
  position:relative;
  margin:20px auto;
 }
 #wrapcharts li {
  height:10px;
  width:10px;
  diaplay:block;
  position:absolute;
  cursor:pointer;
  left:247px;
  top:2px;
  height:10px;
  width:10px;
  transition:0.2s;
  background:red;
  border-radius:50%;
 }
 #boxshadow {
  position:absolute;
  background:blue;
  opacity:0.2;
  height:0;
  width:0;
  left:0;
  top:0;
 }
 </style>
</head>
<body> 

 <ul id="wrapcharts"></ul>
 <div id="boxshadow"></div> 

<script>
 /*
 **模拟从后端取值过来的【角度】和相对应的【人名】数组
 **/
 var degArr = [25,88,252,323,33,28,30,90,290,100,300,50,180,205,220,331,195,97,102,77,62,38,32,79];
 var nameArr = ['内衣天使','小恶魔','金正恩','奥巴马','duolaA梦','午夜激情','梁静茹','刘亦菲','琪琪','大熊','小静','小屁孩','张三','李四','王五','麻六','小明','小张','丽丽','多多','瑾瑾','biubiu','Mr.boluo','Hanson'];
 /*
 **声明 getPos(param)函数: 利用三角函数定理根据传入的角度值获取对边和临边的x,y值
 **/
 function getPos(deg)
 {
 var X = Math.sin(deg*Math.PI/180)*250 + 245;
 var Y = -Math.cos(deg*Math.PI/180)*250 + 245;
 return {x:X,y:Y};
 }
 /*
 **这里不用说吧,获取页面中的ul,和ul中的li对象,以及框选时的那个任意变动大小的小方块对象
 **/
 var oWrap = document.getElementById('wrapcharts');
 var aLi = oWrap.getElementsByTagName('li');
 var oBox =document.getElementById('boxshadow');
 var allLi = '';
 var posArr = [];
 /*
 **for循环中调用getPos(param)来获取degArr数组中的所有角度对应的x,y值(就是每个角度对应的x,y坐标),并传入到一个数组中保存,方便取用
 **/
 for(var i=0;i<degArr.length; i++)
 {
 posArr.push(getPos(degArr[i]));
 }
 /*
 **for循环根据度数数组degArr的长度插入li小圆点到ul中,并将之前获取的每个点对应的x,y左边插入到行内样式
 **/
 for(var i=0; i<degArr.length; i++)
 {
 allLi += '<li style="left:'+posArr[i].x+'px;top:'+posArr[i].y+'px;" title="'+degArr[i]+'°;姓名:'+nameArr[i]+'"></li>';
 }
 oWrap.innerHTML = allLi;
 /*
 **遍历最终得到的ul中的li
 **/
 for(var i=0; i<aLi.length; i++)
 {
 aLi[i].index = i;
 /*
  **封装鼠标移入每个小圆点时的放大事件,这里用到了matrix矩阵,为的事想兼容ie9以下浏览器,但是好像出了点问题
  */
 function focusOn(_this,color, size)
 {
  _this.style.background = color;
  _this.style.WebkitTransform = 'matrix('+size+', 0, 0, '+size+', 0, 0)';
  _this.style.MozTransform = 'matrix('+size+', 0, 0, '+size+', 0, 0)';
  _this.style.transform = 'matrix('+size+', 0, 0, '+size+', 0, 0)';
  _this.style.filter="progid:DXImageTransform.Microsoft.Matrix( M11= "+size+", M12= 0, M21= 0 , M22="+size+",SizingMethod='auto expend')";
 }
 aLi[i].onmouseover = function()
 {
  //alert(this.offsetLeft);
  _this = this;
  focusOn(_this,'blue', 2);
 }
 aLi[i].onmouseout = function()
 {
  //alert(this.offsetLeft);
  _this = this;
  focusOn(_this,'red', 1); 

 }
 }
 /***框选***/
 /*
 **拖拽框选代码区域,这个我就不解释了,明白人都一眼知道什么意思,这就像是公式,
 */
 var allSelect = {};
 document.onmousedown = function(ev)
 {
 var ev = ev || window.event;
 var disX = ev.clientX;
 var disY = ev.clientY;
 var H = W = clientleft = clienttop = clientright = clientbottom = 0;
 oBox.style.cssText = 'left:'+disX+'px;top:'+disY+'px;';
 //console.log(disX+';'+disY);
 function again(f)
 {
  for(var i=0; i<posArr.length; i++)
  {
  if(posArr[i].x > clientleft && posArr[i].y > clienttop && (posArr[i].x + 10) < clientright && (posArr[i].y +10) < clientbottom)
  {
   //console.log(clientleft+';'+ clienttop +';'+ clientright +';' + clientbottom);
   if(f){allSelect[i] = i;}else{
   aLi[i].style.background = 'blue';
   }
  } else
  {
   aLi[i].style.background = 'red';
  }
  } 

 } 

 document.onmousemove = function(ev)
 {
  var ev = ev || window.event;
  /*
  **当鼠标向四个方向拖拉的时候进行方向判断,并相应的改变小方块的left,top以及width,height
  **其实我这里有个问题,那就是,代码重复了一些,本想着合并一下,但是作者有点懒,嘿嘿,你们也可以尝试一下
  **修改后你们拿去当做你们的发布,作者不会介意的
  */
  if(ev.clientX > disX && ev.clientY > disY)
  {
  W = ev.clientX - disX;
  H = ev.clientY - disY; 

  oBox.style.width = W + 'px';
  oBox.style.height = H + 'px'; 

  clienttop = disY-oWrap.offsetTop;
  clientleft = disX-oWrap.offsetLeft; 

  }else if(ev.clientX < disX && ev.clientY < disY)
  {
  W = disX - ev.clientX;
  H = disY - ev.clientY; 

  oBox.style.top = ev.clientY + 'px';
  oBox.style.left = ev.clientX + 'px'; 

  oBox.style.width = W + 'px';
  oBox.style.height = H + 'px'; 

  clienttop = ev.clientY - oWrap.offsetTop;
  clientleft = ev.clientX - oWrap.offsetLeft; 

  }else if(ev.clientX > disX && ev.clientY < disY)
  {
  W = ev.clientX - disX;
  H = disY - ev.clientY; 

  oBox.style.top = ev.clientY + 'px'; 

  oBox.style.width = W + 'px';
  oBox.style.height = H + 'px'; 

  clienttop = ev.clientY - oWrap.offsetTop;
  clientleft = disX - oWrap.offsetLeft; 

  }else if(ev.clientX < disX && ev.clientY > disY)
  {
  W = disX - ev.clientX;
  H = ev.clientY - disY; 

  oBox.style.left = ev.clientX + 'px'; 

  oBox.style.width = W + 'px';
  oBox.style.height = H + 'px'; 

  clienttop = disY-oWrap.offsetTop;
  clientleft = ev.clientX - oWrap.offsetLeft;
  } 

  clientright = clientleft+ W;
  clientbottom = clienttop + H; 

  W = '';
  H = ''; 

  again(); 

 }
 document.onmouseup = function()
 {
  again(1); 

  document.onmouseup = document.onmousemove = null;
  oBox.style.cssText = 'height:0;width:0;';
  if(JSON.stringify(allSelect) == '{}'){return;}
  console.log(allSelect); 

  var lastSelect = [];
  for(var attr in allSelect){
  lastSelect.push(nameArr[attr]);
  }
  allSelect = {}; 

  console.log(lastSelect);
  alert('你选中的人是:\n\n'+lastSelect+'\n\n'); 

  for(var i=0; i<aLi.length; i++)
  {
  aLi[i].style.background = 'red';
  }
 }
 return false;
 }
</script>
</body>
</html> 

会用到的一些知识点拓展

注:在js中设置Transform的时候我用到的不是scale()方法,因为我想兼容ie9以下的版本所以用了矩阵变化。当然,你们也可以改为scale(),毫无影响。

1.在标准浏览器下的矩阵函数matix(a,b,c,d,e,f)、ie下的矩阵函数progid:DXImageTransform.Microsoft.Matrix( M11= 1, M12= 0, M21= 0 , M22=1,SizingMethod='auto expend')

他们的共同点:M11 == a; M12 == c; M21 == b; M22 == d

不一样的地方:ie下的矩阵函数没有 e 和 f 两个参数,在矩阵函数中 e 和 f 是用来位移的,也就是说ie下没法通过矩阵函数来实现位移[ 不过我们这里好像不需要位移,嘿嘿 ]

2.在标准浏览器下矩阵函数matrix中a,b,c,d,e,f 一一对应的的初始值为:matix(1,0,0,1,0,0)

3.通过矩阵实现缩放:

x轴缩放:a = x a c = x c e = x*e

y轴缩放:b = y b d = y d f = y*f

4.通过矩阵实现位移:[ie下没位移]

x轴位移:e = e+x

y轴位移:f = f+y

5.通过矩阵实现倾斜:

x轴倾斜:c = Math.tan(xDeg/180*Math.PI)

y轴倾斜:b = Math.tan(yDeg/180*Math.PI)

6.通过矩阵实现旋转:

a = Math.cos(deg/180*Math.PI);

b = Math.sin(deg/180*Math.PI);

c = -Math.sin(deg/180*Math.PI);

d = Math.cos(deg/180*Math.PI);

7.至于三角函数我就不介绍了,百度一大把。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • 纯JAVASCRIPT图表动画插件Highcharts Examples

    What is Highcharts? 下载地址 http://www.jb51.net/jiaoben/24363.htmlHighcharts is a charting library written in pure JavaScript, offering an easy way of adding interactive charts to your web site or web application. Highcharts currently supports line, spl

  • javaScript矢量图表库-gRaphael几行代码实现精美的条形图/饼图/点图/曲线图

    gRaphael 是一个致力于帮助开发人员在网页中绘制各种精美图表的 Javascript 库,基于强大的 Raphael 矢量图形库.你只需要编写几行简单的代码就能创建出精美的条形图.饼图.点图和曲线图. gRaphael 使用 SVG W3C 推荐标准和 VML 作为创建图形的基础,是跨浏览器的矢量图形库,目前支持的浏览器包括: Firefox 3.0+,Safari 3.0+,Chrome 5.0+,Opera 9.5+ 以及 Internet Explorer 6.0+. 使用方法:在页

  • javascript实现的柱状统计图表

    工作需要,用javascript做一个统计图表: 完成后,做个笔记,大家分享一下,互相学习.其中还有点问题,还不是很完善. 其中参考了百度空间,中管理中心,访问统计,的js统计图表.但是应用上还是有差别,因为我做的这个项目中,需要时实的绘制新的统计表格,当有数据变化的时候,就会调用绘制表格的方法.所以要考虑页面性能的问题. 下面是完成后的预览图,可以看到,绘制一个表格,耗时0.005毫秒,也就是200分之一秒.效率我还是比较满意的! 目前在firefox,chrome,IE8,正常没问题,IE6

  • javascript使用smipleChart实现简单图表

    支持 线性图 区域图 柱状图 饼图 支持多浏览器 用到的是svg  vml 复制代码 代码如下: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml">

  • 浅析jquery的js图表组件highcharts

    Highcharts是一个制作图表的纯Javascript类库, 主要特性如下: 兼容性:兼容当今所有的浏览器,包括iPhone.IE和火狐等等: 对于非商用用户免费(包括个人网站.非盈利性组织.学生团体等). 纯JS,无BS: 支持大部分的图表类型:直线图,曲线图.区域图.区域曲线图.柱状图.饼装图.散布图: 跨语言:不管是PHP..net还是Java都可以使用,它只需要三个文件:一个是 Highcharts的核心文件highcharts.js,还有a canvas emulator for

  • JSP FusionCharts Free显示图表 具体实现

    FusionCharts Free的下载地址:http://www.fusioncharts.com/goodies/fusioncharts-free/ 接下来在jsp页面中引入js 复制代码 代码如下: <script type="text/javascript" src="FusionChartsFree/JSClass/FusionCharts.js"></script> 然后写入 复制代码 代码如下: <script type

  • html+js+highcharts绘制圆饼图表的简单实例

    实例如下: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type&q

  • jQuery简单图表peity.js使用示例

    复制代码 代码如下: <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>无标题页</title> <script type="text/javascript" src="jQuery.js"></script> <script type="text/javascript" src=&q

  • 使用Chart.js图表库制作漂亮的响应式表单

    入门基础 Chart.js是一个基于HTML5的开源图表库,可以方便简洁的绘制美观的图表. 主要特性包括: 1.支持6种不同的表格类型:曲线图.柱状图.饼状图.雷达图.极坐标区域图.环图. 2.基于HTML5开发,支持所有浏览器(包括IE7/8). 3.不依赖于其他任何库,仅有4.5k大小,并且可以进行定制. Chart.js 是一个基于 HTML5 canvas 的响应式.灵活的.轻量化的图表库.库中提供了六种不同的图表类型,每种类型都带有一系列的自定义选项.如果这些还不够,你还可以创造自己的

  • JavaScript可视化图表库D3.js API中文参考

    D3库所提供的所有 API 都在 d3 命名空间下.d3 库使用语义版本命名法(semantic versioning). 你可以用 d3.version 查看当前的版本信息. d3 (核心部分) 选择集 d3.select - 从当前文档中选择一系列元素. d3.selectAll - 从当前文档中选择多项元素. selection.attr - 设置或获取指定属性. selection.classed - 添加或删除选定元素的 CSS 类(CSS class). selection.styl

随机推荐