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

客户想到的是用 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>
/*
**声明 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.至于三角函数我就不介绍了,百度一大把。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
# js
# 框选图表
# 我想
# 鼠标
# 来做
# 小圆
# 的是
# 他们的
# 我就
# 让我
# 给我
# 大材小用
# 会有
# 小方块
# 有个
# 出了
# 那就
# 也没
# 不需要
# 给他
# 就不
# 每个人
相关文章:
建站之星后台管理如何实现高效配置?
css网站制作参考文献有哪些,易聊怎么注册?
建站之星在线客服如何快速接入解答?
javascript中对象的定义、使用以及对象和原型链操作小结
如何制作算命网站,怎么注册算命网站?
免费ppt制作网站,有没有值得推荐的免费PPT网站?
如何在Golang中处理模块冲突_解决依赖版本不兼容问题
网站插件制作软件免费下载,网页视频怎么下到本地插件?
哈尔滨网站建设策划,哈尔滨电工证查询网站?
如何通过老薛主机一键快速建站?
零服务器AI建站解决方案:快速部署与云端平台低成本实践
企业网站制作公司网页,推荐几家专业的天津网站制作公司?
如何制作公司的网站链接,公司想做一个网站,一般需要花多少钱?
简历在线制作网站免费,免费下载个人简历的网站是哪些?
已有域名和空间,如何快速搭建网站?
如何在建站之星绑定自定义域名?
高端建站如何打造兼具美学与转化的品牌官网?
如何在万网自助建站中设置域名及备案?
广州顶尖建站服务:企业官网建设与SEO优化一体化方案
盐城做公司网站,江苏电子版退休证办理流程?
专业网站制作企业网站,如何制作一个企业网站,建设网站的基本步骤有哪些?
如何通过VPS建站无需域名直接访问?
代刷网站制作软件,别人代刷火车票靠谱吗?
再谈Python中的字符串与字符编码(推荐)
网站制作外包价格怎么算,招聘网站上写的“外包”是什么意思?
建站主机服务器选型指南与性能优化方案解析
如何正确下载安装西数主机建站助手?
韩国网站服务器搭建指南:VPS选购、域名解析与DNS配置推荐
济南专业网站制作公司,济南信息工程学校怎么样?
香港服务器网站推广:SEO优化与外贸独立站搭建策略
学校免费自助建站系统:智能生成+拖拽设计+多端适配
建站中国必看指南:CMS建站系统+手机网站搭建核心技巧解析
大连企业网站制作公司,大连2025企业社保缴费网上缴费流程?
建站VPS配置与SEO优化指南:关键词排名提升策略
定制建站策划方案_专业建站与网站建设方案一站式指南
建站之星如何保障用户数据免受黑客入侵?
公众号网站制作网页,微信公众号怎么制作?
建站之星安装后如何配置SEO及设计样式?
网站app免费制作软件,能免费看各大网站视频的手机app?
宝塔建站助手安装配置与建站模板使用全流程解析
如何快速生成凡客建站的专业级图册?
制作网站怎么制作,*游戏网站怎么搭建?
c# 服务器GC和工作站GC的区别和设置
独立制作一个网站多少钱,建立网站需要花多少钱?
建站主机默认首页配置指南:核心功能与访问路径优化
建站之星上传入口如何快速找到?
高性能网站服务器部署指南:稳定运行与安全配置优化方案
建站之星手机一键生成:多端自适应+小程序开发快速建站指南
高配服务器限时抢购:企业级配置与回收服务一站式优惠方案
浙江网站制作公司有哪些,浙江栢塑信息技术有限公司定制网站做的怎么样?
*请认真填写需求信息,我们会在24小时内与您取得联系。