jquery canvas 实现时序图|接续图|顺序图

<div id="chart" style="position: absolute;top:0px;left:0px;right: 0;bottom: 0px; min-height:300px;min-width:500px;"></div>

1.效果图

   

2、数据格式

    var posts=["item1","item2","item3","item4","item5"];//柱子元素
    var relations=[{"from":"item1","to":"item2","content":{"desc":"11223","time":"2017-09-22 16:38:12","flag":0}},{"from":"item1","to":"item2","content":{"desc":"11223","time":"2017-09-22 16:38:12","flag":0}},{"from":"item1","to":"item3","content":{"desc":"11223","time":"2017-09-22 16:38:12","flag":0}},{"from":"item4","to":"item2","content":{"desc":"11223","time":"2017-09-22 16:38:12","flag":1}}];//关联关系

3、html代码

<div id="chart" style="position: absolute;top:0px;left:0px;right: 0;bottom: 0px; min-height:300px;min-width:500px;"></div>
4、js代码

 

       var chart=new followchart("chart",posts,relations,clickfunc);

       $(window).resize(function() {
            chart.redraw();
        });

        function clickfunc(obj,type){
            console.log("obj:",obj);
            console.log("type:",type);
        }
5、不造咋上传文件。。。。
<!DOCTYPE html>
<html>
    <head>
        <style>
            .charttitle{
                color:#fff;
                text-align: center;
                position: absolute;
            }
            .charttitle:hover{
                cursor: pointer;
                background-color: #4877E1;
            }
            .chartcontent{
                position: absolute;
                background-color:#5A9BD5;
                padding: 5px;
                color: #fff;
                font-size: 10px;
            }
            .chartcontent:hover{
                cursor: pointer;
                background-color: #4877E1;
            }
            .chartcontent span{
                text-align: left;
                display: block;
            }
            .flag_0{
                color:red;
            }
            body,#chart{
                margin: 0;
                padding: 0;
            }
            .followchart_warp{
                position: relative;
                height: 100%;
                width: 100%;
            }
        </style>
    </head>
    <body>
     <div id="chart" style="position: absolute;top:0px;left:0px;right: 0;bottom: 0px; min-height:300px;min-width:500px;"></div>

     <script type="text/javascript" src="http://code.jquery.com/jquery-latest.js"></script>
    <script>
        var posts=["item1","item2","item3","item4","item5"]
        var relations=[{"from":"item1","to":"item2","content":{"desc":"11223","time":"2017-09-22 16:38:12","flag":0}},{"from":"item1","to":"item2","content":{"desc":"11223","time":"2017-09-22 16:38:12","flag":0}},{"from":"item1","to":"item3","content":{"desc":"11223","time":"2017-09-22 16:38:12","flag":0}},{"from":"item4","to":"item2","content":{"desc":"11223","time":"2017-09-22 16:38:12","flag":1}}];
        $(function(){
            var chart=new followchart("chart",posts,relations,clickfunc);

            $(window).resize(function() {
                chart.redraw();
            });
        });
        function clickfunc(obj,type){
            console.log("obj:",obj);
            console.log("type:",type);
        }
        function drawArrow(ctx, fromX, fromY, toX, toY, theta, headlen, width, color) {
            theta = typeof(theta) != 'undefined' ? theta : 30;
            headlen = typeof(theta) != 'undefined' ? headlen : 10;
            width = typeof(width) != 'undefined' ? width : 1;
            color = typeof(color) != 'color' ? color : '#5A9BD5'; // 计算各角度和对应的P2,P3坐标
            var angle = Math.atan2(fromY - toY, fromX - toX) * 180 / Math.PI,
                angle1 = (angle + theta) * Math.PI / 180,
                angle2 = (angle - theta) * Math.PI / 180,
                topX = headlen * Math.cos(angle1),
                topY = headlen * Math.sin(angle1),
                botX = headlen * Math.cos(angle2),
                botY = headlen * Math.sin(angle2);

            ctx.save();
            ctx.beginPath();
            var arrowX = fromX - topX,
                arrowY = fromY - topY;
            ctx.moveTo(arrowX, arrowY);
            ctx.moveTo(fromX, fromY);
            ctx.lineTo(toX, toY);
            arrowX = toX + topX;
            arrowY = toY + topY;
            ctx.moveTo(arrowX, arrowY);
            ctx.lineTo(toX, toY);
            arrowX = toX + botX;
            arrowY = toY + botY;
            ctx.lineTo(arrowX, arrowY);
            ctx.strokeStyle = color;
            ctx.lineWidth = width;
            ctx.stroke();
            ctx.restore();
        }
        function Rect(name,x,y,isSelected,color){
            this.name=name;
            this.x=x;
            this.y=y;
            this.isSelected=isSelected;
            this.color=color;
        }
        function RectLine(name,x,y,endx,endy,isSelected,color){
            this.name=name;
            this.x=x;
            this.y=y;
            this.endx=endx;
            this.endy=endy;
            this.isSelected=isSelected;
            this.color=color;
        }
        function LineArrow(fromname,toname,fromx,fromy,tox,toy,isSelected,color,content){
            this.fromname=fromname;
            this.toname=toname;
            this.fromx=fromx;
            this.fromy=fromy;
            this.tox=tox;
            this.toy=toy;
            this.isSelected=isSelected;
            this.color=color;
            this.content=content;
        }
        var followchart=function(elemid,posts,relations,clickbackcall){
            this.rects=[];
            this.rectLines=[];
            this.lineArrows=[];
            this.preselectedindex=null;
            this.preselectedarrowindex=null;
            this.prehoverdname="";
            this.posts=posts;
            this.relations=relations;
            this.clickbackcall=clickbackcall;
            this.rectwidth=65;
            this.rectheight=30;
            this.color="#5A9BD5";
            this.hovercolor="#4877E1";
            this.elemid=elemid
            this.elem=$("#"+elemid);
            this.height=$("#"+elemid).height()-10;
            this.width=$("#"+elemid).width();
            this.elem.html("<div class='followchart_warp'></div>");
            this.context=$("<canvas/>")
                .attr({ width: this.width, height: this.height, id: this.elemid+"_followchart" })
                .appendTo(this.elem.find(".followchart_warp")).get(0).getContext('2d');

            this.canvas=$("#"+this.elemid+"_followchart")[0];
            this.realrectwidth();
            this.addrect();
            this.addlinearrow();
            this.initchart();
            this.render();
        }
        followchart.prototype.render=function(){
            this.canvas.onmousedown = this.canvasClick.bind(this);
            this.canvas.onmousemove = this.canvasHover.bind(this);
            this.elem.on("click",".charttitle",this.canvasClick.bind(this))
        }
        followchart.prototype.initchart=function(){
            this.context.clearRect(0, 0, this.width, this.height);
            this.elem.find(".charttitle").remove();
            this.elem.find(".chartcontent").remove();
            this.context.fillStyle=this.color;
            this.context.strokeStyle =this.color;
            this.drawrect();
            this.drawrectLine();
            this.drawarrow();
        }
        followchart.prototype.realrectwidth=function(){
            var areawidth=this.width/this.posts.length;
            if(areawidth<=75){
                if(areawidth>45) this.rectwidth=35;
                else this.rectwidth=1;
            }
        }
        followchart.prototype.addrect=function(){
            this.rects=[];
            this.rectLines=[];
            for(var i=0;i<this.posts.length;i++){
                var post=this.posts[i];
                var starty=15;
                var startx=Math.round(this.width/this.posts.length*i+this.width/this.posts.length/2-this.rectwidth/2);
                var linestartx=Math.round(startx+this.rectwidth/2);
                var linestarty=Math.round(starty+this.rectheight);
                var lineendx=linestartx;
                var lineendy=Math.round(this.height-starty);
                var rect=new Rect(post,startx,starty,false,this.color);
                var rectline=new RectLine(post,linestartx,linestarty,lineendx,lineendy,false,this.color);
                this.rects.push(rect);
                this.rectLines.push(rectline);
            }

        }
        followchart.prototype.addlinearrow=function(){
            this.lineArrows=[];
            for(var i=0;i<this.relations.length;i++){
                var relation=this.relations[i];
                var fromname=relation.from;
                var toname=relation.to;
                var content=relation.content;
                var fromx=0,fromy=0,tox=0,toy=0;
                for(var j=0;j<this.rectLines.length;j++){
                    var rectline=this.rectLines[j];

                    if(rectline.name==fromname){
                        fromx=rectline.x;
                    }
                    if(rectline.name==toname){
                        tox=rectline.x;
                    }
                }
                fromy=Math.round((this.height-30-this.rectheight)/this.relations.length*i
                    +(this.height-30-this.rectheight)/this.relations.length/2)+15+this.rectheight;
                toy=fromy;
                var color=this.color;
                if(content.flag==0) color="red";
                var arrow=new LineArrow(fromname,toname,fromx,fromy,tox,toy,false,color,content);
                this.lineArrows.push(arrow);
            }
        }

        followchart.prototype.drawrect=function(){
            for(var i=0;i<this.rects.length;i++){
                var rect=this.rects[i];
                this.context.fillStyle=rect.color;
                this.context.fillRect(rect.x,rect.y,this.rectwidth,this.rectheight);
                this.context.stroke();
                if(rect.isSelected){
                    this.context.lineWidth = 1;//边框宽度
                    this.context.strokeStyle = "#00f";//边框颜色
                    this.context.strokeRect(rect.x,rect.y,this.rectwidth,this.rectheight);
                }

                this.drawtitle(rect.x,rect.y,this.rectwidth,this.rectheight,this.posts[i])


            }
        }
        followchart.prototype.drawrectLine=function(){
            for(var i=0;i<this.rectLines.length;i++){
                var rectline=this.rectLines[i];
                this.context.beginPath()
                this.context.moveTo(rectline.x,rectline.y);
                this.context.lineTo(rectline.endx,rectline.endy);
                this.context.lineWidth = 1;
                this.context.strokeStyle =rectline.color;
                if(rectline.isSelected){
                    this.context.lineWidth = 2;
                    this.context.strokeStyle =this.hovercolor;
                }

                this.context.stroke();
                this.context.closePath();
            }

        }

        followchart.prototype.drawtitle=function(x,y,width,height,title){
            this.elem.append("<div class=\"charttitle\" style=\"left:"+x+"px;top:"+y+"px;width:"+width+"px;height:"+height+"px;line-height:"+height+"px;\">"+title+"</div>");
        }
        followchart.prototype.drawarrow=function(){
            for(var i=0;i<this.lineArrows.length;i++){
                var arrow=this.lineArrows[i];
                drawArrow(this.context,arrow.fromx,arrow.fromy,arrow.tox,arrow.toy,30,10,3,arrow.color);

                var startx=arrow.tox<arrow.fromx?arrow.tox:arrow.fromx;
                var contentx=Math.abs(arrow.tox-arrow.fromx)/2+startx;
                if((contentx-40)>startx){
                    contentx=contentx-40;
                }else{
                    contentx=startx;
                }
                this.drawcontent(contentx,arrow.fromy-50,arrow.content);
            }
        }
        followchart.prototype.drawcontent=function(x,y,content){
            var html="<div class=\"chartcontent\" style=\"left:"+x+"px;top:"+y+"px; \">";
            var str = JSON.stringify(content);
            var objKey = JSON.parse(str);
            var propertys = Object.keys(objKey);
            for(var i=0;i<propertys.length;i++){
                html+="<span";
                if(propertys[i]=="flag"){
                    html+=" class=\"flag_"+content[propertys[i]]+"\""
                }
                html+=">"+content[propertys[i]]+"</span>"
            }

            html+="</div>"
            this.elem.append(html);
        }
        followchart.prototype.canvasClick=function(e){
            var clickX = e.pageX - this.elem[0].offsetLeft;
            var clickY = e.pageY - this.elem[0].offsetTop;
            var i=0,hasfind=false,findarrow=false,selectindex=0;
            for( i=0;i<this.rects.length;i++){
                var rect=this.rects[i];
                if(clickX>=rect.x&&clickX<=(rect.x+this.rectwidth)&&clickY>=rect.y&&clickY<=(rect.y+this.rectheight)){
                    rect.isSelected=true;
                    this.rectLines[i].isSelected=true;
                    hasfind=true;
                    selectindex=i;
                    if(this.preselectedindex!=selectindex)this.setunselect(this.preselectedindex);
                    this.preselectedindex=selectindex;
                    break;
                }
            }
            if(!hasfind){
                for( i=0;i<this.rectLines.length;i++){
                    var rectLine=this.rectLines[i];
                    if(clickX>=(rectLine.x-1)&&clickX<=(rectLine.x+1)&&clickY>=rectLine.y&&clickY<=rectLine.endy){
                        rectLine.isSelected=true;
                        this.rects[i].isSelected=true;
                        hasfind=true;
                        selectindex=i;
                        if(this.preselectedindex!=selectindex)this.setunselect(this.preselectedindex);
                        this.preselectedindex=selectindex;
                        break;
                    }
                }
            }
            if(!hasfind){
                for( i=0;i<this.lineArrows.length;i++){
                    var arrow=this.lineArrows[i];
                    var minx=arrow.tox<arrow.fromx?arrow.tox:arrow.fromx;
                    var max=arrow.tox>arrow.fromx?arrow.tox:arrow.fromx;
                    if(clickX>=minx&&clickX<=max&&clickY>=(arrow.fromy-3)&&clickY<=(arrow.toy+3)){
                        arrow.isSelected=true;
                        findarrow=true;
                        selectindex=i;
                        if(this.preselectedarrowindex!=null&&this.preselectedarrowindex!=selectindex)
                            this.relations[this.preselectedarrowindex].isSelected=false;
                        this.preselectedarrowindex=selectindex;
                        break;
                    }
                }
            }
            if(hasfind){
                if(typeof(this.clickbackcall)=="function"){
                    this.clickbackcall(this.posts[selectindex],"item");
                }
            }
            if(findarrow){
                if(typeof(this.clickbackcall)=="function"){
                    this.clickbackcall(this.relations[selectindex],"relation");
                }
            }
            this.initchart();
        }
        followchart.prototype.setunselect=function(index){
            if(index!=null){
                this.rectLines[index].isSelected=false;
                this.rects[index].isSelected=false;
            }
        }
        followchart.prototype.canvasHover=function(e){
            var clickX = e.pageX - this.elem[0].offsetLeft;
            var clickY = e.pageY - this.elem[0].offsetTop;
            this.setunhover(this.rects);
            this.setunhover(this.rectLines);
            this.setunhover(this.lineArrows);
            var i=0,hasfind=false,selectname="";
            for( i=0;i<this.rects.length;i++){
                var rect=this.rects[i];
                if(clickX>=rect.x&&clickX<=(rect.x+this.rectwidth)&&clickY>=rect.y&&clickY<=(rect.y+this.rectheight)){
                    rect.isSelected.color=this.hovercolor;
                    this.rectLines[i].color=this.hovercolor;
                    hasfind=true;
                    selectname=rect.name;
                    break;
                }
            }
            if(!hasfind){
                for( i=0;i<this.rectLines.length;i++){
                    var rectLine=this.rectLines[i];
                    if(clickX>=(rectLine.x-1)&&clickX<=(rectLine.x+1)&&clickY>=(rectLine.y-1)&&clickY<=rectLine.endy){
                        rectLine.color=this.hovercolor;
                        this.rects[i].color=this.hovercolor;
                        hasfind=true;
                        selectname=rect.name;
                        break;
                    }
                }
            }
            if(!hasfind){
                for( i=0;i<this.lineArrows.length;i++){
                    var arrow=this.lineArrows[i];
                    var minx=arrow.tox<arrow.fromx?arrow.tox:arrow.fromx;
                    var max=arrow.tox>arrow.fromx?arrow.tox:arrow.fromx;
                    if(clickX>=minx&&clickX<=max&&clickY>=(arrow.fromy-3)&&clickY<=(arrow.toy+3)){
                        arrow.color=this.hovercolor;
                        if(arrow.content.flag==0){
                            arrow.color="red";
                        }
                        hasfind=true;
                        selectname=arrow.fromname+"-"+arrow.toname;
                        break;
                    }
                }
            }
            if(selectname!=this.prehoverdname){

                if(selectname==""){
                    this.elem.css("cursor","default")
                }else{
                    this.elem.css("cursor","pointer")
                }
                this.prehoverdname=selectname;
                this.initchart();
            }

        }
        followchart.prototype.setunhover=function(objs){
            for(var i=0;i<objs.length;i++){
                objs[i].color=this.color;
                if(objs[i].content!=undefined&&objs[i].content.flag==0){
                    objs[i].color="red";
                }
            }
        }
        followchart.prototype.redraw=function(){
            this.elem.find(".followchart_warp").empty();
            this.height=this.elem.height()-10;
            this.width=this.elem.width();
            this.context=$("<canvas/>")
                .attr({ width: this.width, height: this.height, id: this.elemid+"_followchart" })
                .appendTo(this.elem.find(".followchart_warp")).get(0).getContext('2d');

            this.canvas=$("#"+this.elemid+"_followchart")[0];
            this.realrectwidth();
            this.realrectwidth();
            this.addrect();
            this.addlinearrow();
            this.initchart();
            this.render();
        }
    </script>
    </body>
</html>

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值