snap.svg.js learning ------ classification structure animation display

Wallimn original, welcome to reprint, original address: http://wallimn.iteye.com/blog/2373581

1. Function introduction:
The   function is very simple, it is a classification structure display package that supports cool animation effects, learn and research snap.svg .js results. Pure javascript program, can run in html5 webpage. IE8 and below browsers are not supported, and the mobile phone runs better. Depends on jQuery.

Second, the program interface:





3. Toolkit code:

function Snapcat(paper,data,options){
	this.options={
			centerX:100,
			centerY:100,
			bigRadius:70,
			smallRadius:40,
			leafClickHandler:function(json){
				alert("id="+json.id+", data="+json.data);
			},
			colors:["#fa3e3e","#fa9c3e","#fafa3e","#9cfa3e","#3efa3e","#3efa9c","#3efafa","#3e9cfa","#3e3efa","#9c3efa"]
	};
	
	if(options){
		jQuery.extend(this.options,options);
	}
	
	this.paper = paper;
	
	this.data = data;
	
	var exitPathDef = "M"+this.options.centerX+","+this.options.centerY+" Q"+this.options.centerX+" 0,0 0";
	var enterPathDef="M0 0,Q0 "+this.options.centerY+","+this.options.centerX+" "+this.options.centerY;
	//Exit path, internal variable
	this.exitPath = paper.path(exitPathDef).attr({fill:'none'});
	// make path, internal variable
	this.enterPath = paper.path(enterPathDef).attr({fill:'none'});
	
	this.getLevelColor=function(level){
		if(level>=this.options.colors.length)return "#f00";
		else return this.options.colors[level];
	};
	
	// get data by ID
	this.getDataById=function (id){
		for(var i=0; i<this.data.length; i++){
			if(this.data[i].id==id)return this.data[i];
		}
		return null;
	};
	
	
	this.getDataByPid=function(id){
		var result = [];
		for(var i=0; i<this.data.length; i++){
			if(this.data[i].pid==id)result.push(this.data[i]);
		}
		return result;
	};
	
	
	this.getLevel=function(id){
		var level = 0;
		var data = this.getDataById(id);
		if(!data)return level;
		
		while(data.pid!=0){
			level++;
			data = this.getDataById(data.pid);
		}
		return level;
	};
	
	
	
	
	//Internal private function
	function drawMainCat(cx,cy,r,id,millisec){
		var result = {};
		var data = this.getDataById(id);
		var level = this.getLevel(id);
		result.circle=this.paper.circle(cx,cy,r).attr({
			fill:this.getLevelColor(level),
			stroke:this.getLevelColor(level),
			strokeOpacity:0.75,
			r:0,
			"data-id":data.id,
			"data-pid":data.pid,
			strokeWidth:8
		});
		result.text = paper.text(cx,cy,data.label)
						.attr({"opacity":0,"data-id":data.id,"data-pid":data.pid});
		var bbox = result.text.getBBox ();
		var matrix = new Snap.Matrix();
		matrix.translate(-bbox.width/2, bbox.height/2);
		result.text.transform(matrix);
		
		if(millisec){
			result.circle.animate({r:r},millisec*9/10,mina.bounce,function(){
				result.text.animate({opacity:1},millisec/10,mina.bounce,function(){
	    		});
	    	});
		}
		else{
			result.circle.attr({r:r});
			result.text.attr({opacity:1});
		}
		
		return result;
	}

	// draw subclass
	function drawSubCat(cx,cy,r1,r2,id,timeOutMillisec,dualMillisec){
		var self = this; // used in inner functions
		// show subclasses
		var data = this.getDataByPid(id);
		var level = this.getLevel(id);
		if(!data || data.length==0)return;
        var x, y;
        var distance = r1 + r2 + 10;
        var subcircles = this.paper.group();
        var subcircle,subtext,matrix;
        var datalen = data.length;
        var result = [];
        for (var i = 0; i <datalen; i ++) {
        	x = distance*Math.sin(360*i*Math.PI/180/datalen)+this.options.centerX;
        	y = distance*Math.cos(360*i*Math.PI/180/datalen)+this.options.centerY;
        	subcircle=paper.circle(x,y,0).attr({"data-id":data[i].id,"data-pid":data[i].pid,"data-idx":i,"data-data":data[i].data});
        	subcircles.add(subcircle);
        	subtext = paper.text(x,y,data[i].label).attr({"data-id":data[i].id,"data-pid":data[i].pid,"data-data":data[i].data,opacity:0,"data-idx":i});
        	bbox = subtext.getBBox();
        	matrix = new Snap.Matrix();
        	matrix.translate(-bbox.width/2,bbox.height/2);
        	subtext.transform(matrix);
        	result.push({circle:subcircle,text:subtext});
        	
        }
        subcircles.attr({
        	fill:this.getLevelColor(level+1),
        	stroke:this.getLevelColor(level+1),
        	strokeOpacity:0.75,
        	strokeWidth:8
        });
        
        
    	if(timeOutMillisec && dualMillisec){
    		setTimeout(function(){
    			var circle,text;
    			for (var i = 0; i <datalen; i ++) {
    				Snap($("circle[data-id="+data[i].id+"]")[0]).animate({r:r2},dualMillisec*9/10,mina.bounce,function(){
    					var id = this.node.getAttribute("data-id");
    					Snap($("text[data-id="+id+"]")[0]).animate({opacity:1},dualMillisec/10,mina.bounce);
    				});
    			}
    		},timeOutMillisec);
    	}
    	else{
			for (var i = 0; i <datalen; i ++) {
				Snap($("circle[data-id="+data[i].id+"]")[0]).attr({r:r2});
				Snap($("text[data-id="+data[i].id+"]")[0]).attr({opacity:1});
			}
    	}
        
    	
    	
    	//set event
    	var clickHandler = function(){
			var idx = this.node.getAttribute("data-idx");
			var pid = this.node.getAttribute("data-pid");
			var id = this.node.getAttribute("data-id");
			var catdata = this.node.getAttribute("data-data");
			
			if(self.getDataByPid(id).length==0){
				self.options.leafClickHandler({id:id,data:catdata});
				return;
			}
			
			$("circle[data-idx!="+idx+"][data-pid="+pid+"]").remove();
			$("text[data-idx!="+idx+"][data-pid="+pid+"]").remove();
			//paper.selectAll("circle[data-id="+pid+"],text[data-id="+pid+"]").remove();
			var length = Snap.path.getTotalLength(self.exitPath);
			var circle = Snap($("circle[data-id="+pid+"]")[0]);
			var text = Snap($("text[data-id="+pid+"]")[0]);
			// remove the big circle
			Snap.animate(0,length,function(val){
				var point = Snap.path.getPointAtLength(self.exitPath,val);
				circle.attr({cx:point.x,cy:point.y});
				text.attr({x:point.x,y:point.y});
			},timeOutMillisec,mina.easeout);
			
			//After moving to the upper left corner, add an event, responsible for moving back to the big circle
			circle.click(function(){
				var id = this.node.getAttribute("data-id");
				$("circle[data-id!="+id+"]").remove();
				$("text[data-id!="+id+"]").remove();
				var length = Snap.path.getTotalLength(self.enterPath);
				var circle=Snap($('circle[data-id='+id+']')[0]);
				var text=Snap($('text[data-id='+id+']')[0]);
				//move back to the big circle
				Snap.animate(0,length,
					function(val){
	    				var point = Snap.path.getPointAtLength(self.enterPath,val);
	    				circle.attr({cx:point.x,cy:point.y});
	    				text.attr({x:point.x,y:point.y});
    				},
    				timeOutMillisec,
    				function(){
    					circle.unclick();
					});
				
				drawSubCat.bind(self)(cx,cy,r1,r2,id,timeOutMillisec,dualMillisec);
			});
			
			var subCircle = Snap($("circle[data-id="+id+"]")[0])	;
			var subText = Snap($("text[data-id="+id+"]")[0])	;
			var subPathDef = "M"+subCircle.attr("cx")+" "+subCircle.attr("cy")+" L"+self.options.centerX+" "+self.options.centerY;
			var subPath = paper.path(subPathDef);
			length = Snap.path.getTotalLength(subPath);
			// enlarge the small circle
			Snap.animate(self.options.smallRadius,self.options.bigRadius,
					function(val){
						subCircle.attr({r:val});
					},
					dualMillisec,mina.easeout
			);
			subText.unclick();
			subCircle.unclick();
			
			// move the circle to the center
			Snap.animate(0,length,function(val){
    				var point = Snap.path.getPointAtLength(subPath,val);
    				subCircle.attr({cx:point.x,cy:point.y});
    				subText.attr({x:point.x,y:point.y});
				},
				dualMillisec,mina.easeout,
				function(){
					drawSubCat.bind(self)(cx,cy,r1,r2,id,dualMillisec,dualMillisec);
				}
			);
		};//end of click event
    	for(var i=0; i<result.length;i++){
    		result[i].text.click(clickHandler);
    		result[i].circle.click(clickHandler);
    	}//end of for
        return result;
	}
	
	this.drawCat=function(){
		var millsec = 600;
    	drawMainCat.bind(this)(this.options.centerX,this.options.centerY,this.options.bigRadius,1,millsec);
    	drawSubCat.bind(this)(this.options.centerX,this.options.centerY,this.options.bigRadius,this.options.smallRadius,1,millsec,400);
	}

}//end of Snapcat



Fourth, the application example:
<!DOCTYPE html>
<!--
	Author: wallimn, http://wallimn.iteye.com
	When: May 7, 2017
	Function: Cool classified animation display package
-->
<html lang="zh-cn">
  <head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
    <title>Cool category-wallimn</title>
    <style type="text/css">
    	html,body{
    		width:100%;
    		height:100%;
    	}
		#svg {
			margin:0;
			position:relative;
			top:50%;
			border-radius:5px;
			border:1px solid #efefef;
		}
		text{
			font-size:14px;
		}
    </style>
  </head>
  <body>
  
 
	<svg id='paper'></svg>
  
  
    <script type="text/javascript" src="js/jquery-1.11.1.min.js"></script>
	<script type="text/javascript" src="js/snap.svg-min.js"></script>
	<script type="text/javascript" src="js/snapcat.js"></script>
    
	<script type="text/javascript">
	
	    $(function(){
	    	var clientWidth=document.body.clientWidth;
	    	var clientHeight=document.body.clientHeight;
			$("#paper").css("width",clientWidth+"px").css("height",clientHeight+"px");
	    	var minsize = Math.min(clientWidth,clientHeight);
	    	var paper = Snap("#paper");
	    	//Create a circle with a bed radius of 80
	    	var centerX=clientWidth/2, centerY=clientHeight/2 ;
	    	var data = [
    			{id:1,pid:0,label:'knowledge body',data:null},
    			{id:2,pid:1,label:'Product',data:null},
    			{id:3,pid:1,label:'operation',data:null},
    			{id:4,pid:1,label:'planning',data:null},
    			{id:5,pid:1,label:'Creative',data:null},
    			{id:6,pid:1,label:'Strategy',data:null},
    			{id:9,pid:2,label:'Product-Subclass 1',data:'A001'},
    			{id:10,pid:2,label:'Product-Subclass 2',data:'A002'},
    			{id:31,pid:2,label:'Product-Subclass 3',data:'A001'},
    			{id:32,pid:2,label:'Product-Subclass 4',data:'A002'},
    			
    			{id:11,pid:3,label:'Operation-Subclass 1',data:'A003'},
    			{id:12,pid:3,label:'Operation-Subclass 2',data:'A004'},
    			{id:13,pid:3,label:'Operation-Subclass 3',data:'A005'},
    			
    			{id:14,pid:4,label:'planning-subclass 1',data:'A006'},
    			{id:15,pid:4,label:'planning-subclass 2',data:'A007'},
    			{id:16,pid:4,label:'planning-subclass 3',data:'A008'},
    			{id:17,pid:4,label:'planning-subclass 4',data:'A009'},
    			
    			{id:18,pid:5,label:'Creativity-Subclass 1',data:'A010'},
    			{id:18,pid:5,label:'Creativity-Subclass 2',data:'A011'},
    			
    			{id:20,pid:6,label:'Strategy-Subclass 1',data:'A012'},
    			{id:21,pid:6,label:'Strategy-Subclass 2',data:'A013'},
    			{id:22,pid:6,label:'Strategy-Subclass 3',data:'A014'},
    			{id:23,pid:6,label:'Strategy-Subclass 4',data:'A012'},
    			{id:24,pid:6,label:'Strategy-Subclass 5',data:'A013'},
    			{id:25,pid:6,label:'Strategy-Subclass 6',data:'A014'},
    		];	        
	    	var snapcat = new Snapcat(paper,data,{centerX:centerX,centerY:centerY});
	    	snapcat.drawCat();
	     });
	</script>
  </body>
</html>


5. Code warehouse:
  Upload the code to github.com, visit the address: https://github.com/wallimn/snapcat , and download all the programs by pressing the button.

  For mobile phone experience, please use WeChat to scan the following QR code, no attention, no registration, and no download required:


Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=326706499&siteId=291194637