前端fabric.js实现二叉树可视化布局

1.下载fabric.js文件http://fabricjs.com/    

2.效果图

3.代码

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<style>
* {
	margin: 0;
	padding: 0;
}

html, body {
	height: 100%;
	width: 100%;
}

canvas {
	display: block;
}
</style>
</head>
<body>
	<div id="divcanvas">
		<canvas id="canvas" width="974" height="715"></canvas>
	</div>
</body>
<script src="fabric.min.js"></script>
<script src="jquery/jquery.min.js"></script>
<script>
	var contrydata = {
		name : "浙江省上城区上城区",
		cenNum : 19,
		color : '#D0D0D0',
		childData : [ {
			name : "杭州市",
			color : '#0C64FC',
			cenNum : 10,
			childData : [ {
				color : '#D0D0D0',
				cenNum : 2,
				name : "上城区上城区上城区上城区上城区"
			}, {
				color : '#D0D0D0',
				cenNum : 2,
				name : "下城区"
			}, {
				color : '#D0D0D0',
				cenNum : 2,
				name : "萧山区"
			}, {
				color : '#D0D0D0',
				cenNum : 2,
				name : "滨江区"
			}, {
				color : '#D0D0D0',
				cenNum : 2,
				name : "江干区"
			} ]
		}, {
			name : "宁波市上城区上城区上城区上",
			color : '#D0D0D0',
			cenNum : 4,
			childData : [ {
				color : '#D0D0D0',
				cenNum : 4,
				name : "海曙区",
				childData : [ {
					color : '#D0D0D0',
					cenNum : 2,
					name : "上城区上城区上城区上城区上城区上城区"
				}, {
					color : '#D0D0D0',
					cenNum : 2,
					name : "下城区上城区上城区上城区上城区上区上城区上区上城区上区上城区"
				}]
			} ]
		}, {
			name : "丽水市",
			color : '#D0D0D0',
			cenNum : 5,
			childData : [ {
				color : '#D0D0D0',
				cenNum : 5,
				name : "丽水一区"

			} ]
		} ]
	};
	
$(window).resize(resizeCanvas);  
   
 function resizeCanvas() {  
   		var c=document.getElementById("canvas");
        $(c).attr("width", $(window).get(0).innerWidth);  
   
       $(c).attr("height", $(window).get(0).innerHeight);  
   
        c.getContext("2d").fillRect(0, 0, $(c).width(),  $(c).height());  
   
 };  
   
 resizeCanvas(); 
 	var w_h = $(window).get(0).innerHeight;
 	var w_w = $(window).get(0).innerWidth;
 	
	var LINE_LENGTH = 30/974*w_w;//线长度
	var FONT_SIZE = 10/974*w_w;//字体大小
	var RECT_WIDTH = 100/974*w_w;
	var RECT_HEIGHT = 30/715*w_h;
	var RECT_BCOLOR_NO = '#D0D0D0';//不可选城市颜色
	var RECT_BCOLOR_YES = '#0C64FC';//可选城市颜色
	var dataposition=  [];
	window.onload = function() {
		var rootl = 150;
		var roott = 50;
		var citys = contrydata.citys;

		var canvas = new fabric.Canvas('canvas');
		drawRectAndTextGroup(canvas, rootl, roott, contrydata.color,
				contrydata.name);
		dataposition.push({left:rootl,top:roott,name:contrydata.name});	
		drawData(canvas, rootl, roott, contrydata);
		canvas.on({
			'mouse:down' : function(options) {
				console.log(options.e.clientX + "," + options.e.clientY);
				var oleft = options.e.clientX;
				var otop = options.e.clientY;
				for(var i=0;i<dataposition.length;i++){
					var dp = dataposition[i];
					if(oleft>=dp.left && oleft<=dp.left+RECT_WIDTH && otop>=dp.top&&otop<=dp.top+RECT_HEIGHT){
						alert(dp.name);
					}
				}
			}
		});

	}

	function drawData(canvas, rootleft, rootTop, rootData) {
		var childData = rootData.childData;
		if (childData == undefined || childData == null)
			return;
		var childlen = childData.length;
		var yuanheght = 0;
		
		for (var i = 0; i < childlen; i++) {
			var child = childData[i];
			var cen = child.cenNum;
			var childLeft = rootleft + LINE_LENGTH * 2 + RECT_WIDTH;
			var childTop = rootTop + yuanheght;
			yuanheght += cen * LINE_LENGTH;
			
			dataposition.push({left:childLeft,top:childTop,name:child.name});	
			
			drawRectAndTextGroup(canvas, childLeft, childTop, child.color,
					child.name);
			
			/*var r_w = RECT_WIDTH;
			if(r_w<FONT_SIZE*(tc.length)){
				r_w = FONT_SIZE*(tc.length);
			}*/

			//横线
			if (i == 0) {
				drawLateralLine(canvas, childLeft - LINE_LENGTH * 2, childTop
						+ RECT_HEIGHT / 2);
			}
			drawLateralLine(canvas, childLeft - LINE_LENGTH * 1, childTop
					+ RECT_HEIGHT / 2);

			if (i == childlen - 1) {
				for (var k = 0; k < rootData.cenNum - cen; k++)
					drawHorrentLine(canvas,
							rootleft + LINE_LENGTH + RECT_WIDTH, rootTop
									+ RECT_HEIGHT / 2 + k * LINE_LENGTH);
			}

			var cchild = child.childData;
			if (cchild != undefined && cchild != null && cchild.length > 0) {

				drawData(canvas, childLeft, childTop, child);
			}
		}
	}

	/**
	1:left
	t:top
	bcolor:方形背景颜色
	tc:文本内容
	 */
	function drawRectAndTextGroup(canvas, l, t, bcolor, tc) {
		var r_w = RECT_WIDTH;
		if(r_w<FONT_SIZE*(tc.length)){
			r_w = FONT_SIZE*(tc.length);
		}
		var rect = new fabric.Rect({
			width : r_w,
			height : RECT_HEIGHT,
			fill : bcolor,
			originX : 'center',//调整中心点的X轴坐标
			originY : 'center',//调整中心点的Y轴坐标
		});
		var text = new fabric.Text(tc, {
			hasControls : false,
			fill : "black",
			fontFamily : 'pokeText',
			fontSize : FONT_SIZE,
			originX : 'center',
			originY : 'center'

		});

		//进行组合
		var group = new fabric.Group([ rect, text ], {
			left : l,
			top : t,
			hasControls : false, //选中时是否可以放大缩小
			hasRotatingPoint : false,//选中时是否可以旋转
			hasBorders : false,//选中时是否有边框
			transparentCorners : true,
			perPixelTargetFind : true,//默认false。当设置为true,对象的检测会以像互点为基础,而不是以边界的盒模型为基础。
			selectable : true,//是否可被选中
			lockMovementX : true,//X轴是否可被移动(true为不可,因为前缀是lock)
			lockMovementY : true
		//Y轴是否可被移动(true为不可,因为前缀是lock)
		})
		
		canvas.add(group);//方块文字组合块
		
	}
	/**
	横线
	 */
	function drawLateralLine(canvas, l, t) {
		var line = new fabric.Line([ l, t, l + LINE_LENGTH, t ], {//横线
			//终止位置,线长,起始位置,top,这里是从项目中截下来的我用了变量代替,你要用的话lineheight和lineleft用自己的变量或者数字代替。如果两个终止位置和起始位置的数值一样那么这个线条会垂直,这个应该很好理解。
			fill : '#5E2300',//填充颜色
			stroke : '#5E2300',//笔触颜色
			strokeWidth : 1,//笔触宽度
			hasControls : false, //选中时是否可以放大缩小
			hasRotatingPoint : false,//选中时是否可以旋转
			hasBorders : false,//选中时是否有边框
			transparentCorners : true,
			perPixelTargetFind : true,//默认false。当设置为true,对象的检测会以像互点为基础,而不是以边界的盒模型为基础。
			selectable : true,//是否可被选中
			lockMovementX : true,//X轴是否可被移动(true为不可,因为前缀是lock)
			lockMovementY : true
		//Y轴是否可被移动(true为不可,因为前缀是lock)
		});
		canvas.add(line);
	}
	function drawHorrentLine(canvas, l, t) {
		var line = new fabric.Line([ l, t, l, t + LINE_LENGTH ], {//竖线
			//终止位置,线长,起始位置,top,这里是从项目中截下来的我用了变量代替,你要用的话lineheight和lineleft用自己的变量或者数字代替。如果两个终止位置和起始位置的数值一样那么这个线条会垂直,这个应该很好理解。
			fill : '#5E2300',//填充颜色
			stroke : '#5E2300',//笔触颜色
			strokeWidth : 1,//笔触宽度
			hasControls : false, //选中时是否可以放大缩小
			hasRotatingPoint : false,//选中时是否可以旋转
			hasBorders : false,//选中时是否有边框
			transparentCorners : true,
			perPixelTargetFind : true,//默认false。当设置为true,对象的检测会以像互点为基础,而不是以边界的盒模型为基础。
			selectable : true,//是否可被选中
			lockMovementX : true,//X轴是否可被移动(true为不可,因为前缀是lock)
			lockMovementY : true
		//Y轴是否可被移动(true为不可,因为前缀是lock)
		});
		canvas.add(line);
	}
</script>

</html>



  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值