今天被领导要求用js绘制2D机柜用于向客户展示客户资产以及管理设备,虽然我是后端,既然被分配到这个任务那就得做好。
首先上网查了下资料,网上目前现有的2D绘制机柜的示例不多,产品的话大概也就那么几款例如TWaver以及Hightopo,TWaver想要下载示例及js需要非免费邮箱,虽然可以通过查看网页源码规避掉这个限制,等待他们反馈实在没耐心;Hightopo则联系过客服需要付费使用,这也很大程度上限制了使用场景而目前我们项目的需求仅是展示机柜的信息而已,因此决定自己用js绘制机柜。
绘制的第一步当然是绘制机柜框框,这个很简单,写个div然后将边框设置下就好了:
.parentBlock {
width: 300px;
border: solid 18px;
margin: 0 auto;
background-color: dimgrey
}
<div class="parentBlock">
</div>
这里将背景设置成灰色显得真实些:

为了辨别机柜,这里在机柜上面再加一个机柜title:
.titleBlock {
width: 300px;
height: 10px;
border: solid 18px;
margin: 0 auto;
background-color: black;
}
<div class="titleBlock" align="center">
<font color="white" style="font-weight: bold">测试机柜</font>
</div>
这样样式为:

这样一个机柜的雏形就有了,现在需要往机柜中放入机柜的单元:
.innerContentBlock {
width: 100%;
height: 100%;
background-color: dimgrey
}
.areaBlock {
width: 280px;
height: 12px;
margin: 0 auto;
margin-top: 3px;
background-color: black;
text-align: center;
}
.blockFont {
line-height: 12px;
color: white;
font-size: 10px
}
<div class="innerContentBlock">
<div class="areaBlock" align="center"><div class="blockFont">5</div></div>
<div class="areaBlock" align="center"><div class="blockFont">4</div></div>
<div class="areaBlock" align="center"><div class="blockFont">3</div></div>
<div class="areaBlock" align="center"><div class="blockFont">2</div></div>
<div class="areaBlock" align="center"><div class="blockFont">1</div></div>
<div class="areaBlock" align="center"><div class="blockFont">5</div></div>
<div class="areaBlock" align="center"><div class="blockFont">4</div></div>
<div class="areaBlock" align="center"><div class="blockFont">3</div></div>
<div class="areaBlock" align="center"><div class="blockFont">2</div></div>
<div class="areaBlock" align="center"><div class="blockFont">1</div></div>
<div class="areaBlock" align="center"><div class="blockFont">5</div></div>
<div class="areaBlock" align="center"><div class="blockFont">4</div></div>
<div class="areaBlock" align="center"><div class="blockFont">3</div></div>
<div class="areaBlock" align="center"><div class="blockFont">2</div></div>
<div class="areaBlock" align="center"><div class="blockFont">1</div></div>
<div class="areaBlock" align="center"><div class="blockFont">5</div></div>
<div class="areaBlock" align="center"><div class="blockFont">4</div></div>
<div class="areaBlock" align="center"><div class="blockFont">3</div></div>
<div class="areaBlock" align="center"><div class="blockFont">2</div></div>
<div class="areaBlock" align="center"><div class="blockFont">1</div></div>
<div class="areaBlock" align="center"><div class="blockFont">5</div></div>
<div class="areaBlock" align="center"><div class="blockFont">4</div></div>
<div class="areaBlock" align="center"><div class="blockFont">3</div></div>
<div class="areaBlock" align="center"><div class="blockFont">2</div></div>
<div class="areaBlock" align="center"><div class="blockFont">1</div></div>
<div class="areaBlock" align="center"><div class="blockFont">5</div></div>
<div class="areaBlock" align="center"><div class="blockFont">4</div></div>
<div class="areaBlock" align="center"><div class="blockFont">3</div></div>
<div class="areaBlock" align="center"><div class="blockFont">2</div></div>
<div class="areaBlock" align="center" style="margin-bottom: 3px"><div class="blockFont">1</div></div>
</div>
这样基本样式如下:

这样一个基本的空机柜图就画好了,现在需要往机柜中放入设备,这里我的实现思路是将目标单元替换成带有背景图片为设备的div,样式如下:
.areaBlockWithImg {
width: 280px;
height: 12px;
margin: 0 auto;
margin-top: 3px;
background-color: black;
text-align: center;
background-image: url(img/1.jpg);
background-size: 100% 100%;
-moz-background-size: 100% 100%;
color: transparent;
}
<div class="innerContentBlock">
<div class="areaBlock" align="center"><div class="blockFont">5</div></div>
<div class="areaBlock" align="center"><div class="blockFont">4</div></div>
<div class="areaBlockWithImg" align="center"><div class="">3</div></div>
<div class="areaBlockWithImg" align="center"><div class="">2</div></div>
<div class="areaBlock" align="center"><div class="blockFont">1</div></div>
<div class="areaBlockWithImg" align="center"><div class="">5</div></div>
<div class="areaBlockWithImg" align="center"><div class="">4</div></div>
<div class="areaBlock" align="center"><div class="blockFont">3</div></div>
<div class="areaBlockWithImg" align="center"><div class="">2</div></div>
<div class="areaBlockWithImg" align="center"><div class="">1</div></div>
<div class="areaBlock" align="center"><div class="blockFont">5</div></div>
<div class="areaBlock" align="center"><div class="blockFont">4</div></div>
<div class="areaBlockWithImg" align="center"><div class="">3</div></div>
<div class="areaBlockWithImg" align="center"><div class="">2</div></div>
<div class="areaBlock" align="center"><div class="blockFont">1</div></div>
<div class="areaBlock" align="center"><div class="blockFont">5</div></div>
<div class="areaBlockWithImg" align="center"><div class="">4</div></div>
<div class="areaBlock" align="center"><div class="blockFont">3</div></div>
<div class="areaBlock" align="center"><div class="blockFont">2</div></div>
<div class="areaBlockWithImg" align="center"><div class="">1</div></div>
<div class="areaBlock" align="center"><div class="blockFont">5</div></div>
<div class="areaBlockWithImg" align="center"><div class="">4</div></div>
<div class="areaBlock" align="center"><div class="blockFont">3</div></div>
<div class="areaBlock" align="center"><div class="blockFont">2</div></div>
<div class="areaBlock" align="center"><div class="blockFont">1</div></div>
<div class="areaBlock" align="center"><div class="blockFont">5</div></div>
<div class="areaBlockWithImg" align="center"><div class="">4</div></div>
<div class="areaBlock" align="center"><div class="blockFont">3</div></div>
<div class="areaBlock" align="center"><div class="blockFont">2</div></div>
<div class="areaBlock" align="center" style="margin-bottom: 3px"><div class="blockFont">1</div></div>
</div>
绘制出的机柜图为:

现在有一点像那么样子了。有了基本的样式和示例,现在就可以写方法动态规划整个机柜图了,基本思路是,首先确定机柜共有多少个单元,然后定死单元之间的间隔和单元高度,有了这两个参数再乘以单元数量就可以知道机柜的高度也就是height。
var blockInterval = 3;//单元的间隔
var blockHeight = 12;//单元高度
var parentBlockHeight = (blockHeight + blockInterval) * unitCount + 'px';//机柜总高度
有了基本的单元及机柜高度,现在还有个问题就是有些设备会占好几个单元,这个如何处理呢?这里的思路是首先将各个设备所在的单元起始位置以及一共占用单元的个数封装入map中,然后通过循环将各个设备加上合适的高度然后循环从当前单元跳过单元所占的单元数继续循环。
//index为设备所在单元的起始位置
//length为设备所占单元的个数
//name为设备的基本信息
//type为设备类型方便插入不同的设备图片
var unitArray= new Array();
unitArray.push({index: 1, name: '11', length: 2, type: 1})
unitArray.push({index: 10, name: '22', length: 4, type: 1})
unitArray.push({index: 25, name: '23', length: 6, type: 1})
//循环将设备封装入map中以供后续函数使用
for (var i = 0; i < unitArray.length; i++) {
map[unitArray[i].index + unitArray[i].length - 1] = unitArray[i];
}
var content = "";
for (var i = unitCount; i >= 1; i--) {
if (typeof(map[i]) == 'undefined') {//循环机柜单元,若当前单元不存在设备则append基本单元模块
content += '<div class="areaBlock" align="center" data-geo=""><div class="blockFont">' + i + '</div></div>'
} else {//如果为设备则使用设备模块
var length = parseInt(map[i].length);
var height = blockHeight * (length) + blockInterval * (length - 1) + 'px';
i -= (length - 1);//这里是重点,循环要跳过当前设备所占的单元数
content += '<div class="areaBlockWithImg" align="center" style="height: ' + height + '" data-geo="">' + '台式机,dell,XSAD123' + '</div>'
}
}
这样动态绘制之后的机柜图为:

现在只要从后台获取并封装好相应的数据就可以动态显示机柜了,但是这里还有一个需求就是要当鼠标光标在设备或者单元格上时可以显示对应的设备信息。这里用Jquery UI实现
$( document ).tooltip({
position: { my: "left+50 center", at: "right center" },
items: "[data-geo]",
content: function() {
var element = $( this );
if ( element.is( "[data-geo]" ) ) {
var text = element.text().split(',');
var content = '';
if (text.length == 3) {
content += "<div>"+text[0]+"</div><div>"+text[1]+"</div><div>"+text[2]+"</div>";
}else{
content += "<div>单元 "+text[0]+" 可使用</div>";
}
return content;
}
}
});
这样实现的结果为:


到这里基本的需求都已经满足,后续如果客户还要追加拖动新增功能或者其他功能到时候会持续更新。这里贴下完整代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="css/jquery-ui.min.css">
<style>
.titleBlock {
width: 300px;
height: 10px;
border: solid 18px;
margin: 0 auto;
background-color: black;
}
.parentBlock {
width: 300px;
border: solid 18px;
margin: 0 auto;
background-color: dimgrey
}
.innerContentBlock {
width: 100%;
height: 100%;
background-color: dimgrey
}
.areaBlock {
width: 280px;
height: 12px;
margin: 0 auto;
margin-top: 3px;
background-color: black;
text-align: center;
}
.areaBlockWithImg {
width: 280px;
height: 12px;
margin: 0 auto;
margin-top: 3px;
background-color: black;
text-align: center;
background-image: url(img/1.jpg);
background-size: 100% 100%;
-moz-background-size: 100% 100%;
color: transparent;
}
.blockFont {
line-height: 12px;
color: white;
font-size: 10px
}
</style>
</head>
<body>
<div class="titleBlock" align="center">
<font color="white" style="font-weight: bold">测试机柜</font>
</div>
<div class="parentBlock">
<div class="innerContentBlock">
</div>
</div>
</body>
<script src="js/jquery-1.11.0.min.js"></script>
<script src="js/jquery-ui.min.js"></script>
<script>
$(function () {
$( document ).tooltip({
position: { my: "left+50 center", at: "right center" },
items: "[data-geo]",
content: function() {
var element = $( this );
if ( element.is( "[data-geo]" ) ) {
var text = element.text().split(',');
var content = '';
if (text.length == 3) {
content += "<div>"+text[0]+"</div><div>"+text[1]+"</div><div>"+text[2]+"</div>";
}else{
content += "<div>单元 "+text[0]+" 可使用</div>";
}
return content;
}
}
});
var array = new Array();
array.push({index: 1, name: '11', length: 2, type: 1})
array.push({index: 10, name: '22', length: 4, type: 1})
array.push({index: 25, name: '23', length: 6, type: 1})
init(40, array)
})
function init(unitCount, unitArray) {
var blockInterval = 3;//单元的间隔
var blockHeight = 12;//单元高度
var map = {};
for (var i = 0; i < unitArray.length; i++) {
map[unitArray[i].index + unitArray[i].length - 1] = unitArray[i];
}
var parentBlockHeight = (blockHeight + blockInterval) * unitCount + 'px';
$('.parentBlock').css('height', parentBlockHeight);
var content = "";
for (var i = unitCount; i >= 1; i--) {
if (typeof(map[i]) == 'undefined') {
content += '<div class="areaBlock" align="center" data-geo=""><div class="blockFont">' + i + '</div></div>'
} else {
var length = parseInt(map[i].length);
var height = blockHeight * (length) + blockInterval * (length - 1) + 'px';
i -= (length - 1);
content += '<div class="areaBlockWithImg" align="center" style="height: ' + height + '" data-geo="">' + '台式机,dell,XSAD123' + '</div>'
}
}
$('.innerContentBlock').append(content)
}
</script>
</html>
代码已上传,这里是地址。
1621

被折叠的 条评论
为什么被折叠?



