html5 canvas画流程图

<!DOCTYPE html>
<html>

    <head>
        <meta charset="utf-8" />
        <title></title>
    </head>

    <body>
        <canvas id="myCanvas" width="1200" height="800" style="border: solid 1px;"></canvas>
        <script type="text/javascript" src="js/arrow.js"></script>
        <script type="text/javascript" src="js/step.js" ></script>
        <script type="text/javascript" src="js/flow.js"></script>
    </body>

</html>
// 
//  arrow.js
//  <箭头对象>
//  
//  Created by DurantSimpson on 2016-12-08.
//  Copyright 2016 DurantSimpson. All rights reserved.
// 

/**
 * 
 * @param {Object} x1起始点横坐标
 * @param {Object} y1起始点纵坐标
 * @param {Object} x2结束点横坐标
 * @param {Object} y2结束点纵坐标
 */
function Arrow(x1, y1, x2, y2) {
    this.x1 = x1;
    this.y1 = y1;
    this.x2 = x2;
    this.y2 = y2;
    this.tmpX1 = null;
    this.tmpY1 = null;
    this.tmpX2 = null;
    this.tmpY2 = null;
    this.color = "black";

}

Arrow.prototype.setColor = function(color) {
    this.color=color;
}

/**
 * 
 * @param {Object} x1起始点横坐标
 * @param {Object} y1起始点纵坐标
 * @param {Object} x2结束点横坐标
 * @param {Object} y2结束点纵坐标
 */
Arrow.prototype.setP = function(x1, y1, x2, y2) {
    this.x1 = x1;
    this.y1 = y1;
    this.x2 = x2;
    this.y2 = y2;
}

/**
 * 第一个拐点
 */
Arrow.prototype.setP1 = function(tmpX1,tmpY1) {
    this.tmpX1=tmpX1;
    this.tmpY1=tmpY1;
}

/**
 * 第二个拐点
 */
Arrow.prototype.setP2 = function(tmpX2,tmpY2) {
    this.tmpX2=tmpX2;
    this.tmpY2=tmpY2;
}

Arrow.prototype.drawBottomToTop = function(ctx) {
    if (this.x1 != this.x2) {
        this.setP1(this.x1,(this.y1+this.y2)/2);
        this.setP2(this.x2,(this.y1+this.y2)/2);
        this.draw(ctx);
    }else{
        this.draw(ctx);
    }
}

Arrow.prototype.drawLeftOrRightToTop = function(ctx) {
        this.setP1(this.x2,this.y1);
        this.draw(ctx);
}

Arrow.prototype.drawLeftToRightOrRightToLeft = function(ctx) {
    if (this.y1 != this.y2) {
        this.setP1((this.x1+this.x2)/2,this.y1);
        this.setP2((this.x1+this.x2)/2,this.y2);
        this.draw(ctx);
    }else{
        this.draw(ctx);
    }
}

Arrow.prototype.draw = function(ctx) {
    // arbitrary styling
    ctx.strokeStyle = this.color;
    ctx.fillStyle = this.color;
    // draw the line
    ctx.beginPath();
    ctx.moveTo(this.x1, this.y1);
    if(this.tmpX1 != null && this.tmpY1 != null && this.tmpX2 != null && this.tmpY2 != null) {
        ctx.lineTo(this.tmpX1, this.tmpY1);
        ctx.closePath();
        ctx.stroke();
        ctx.beginPath();
        ctx.moveTo(this.tmpX1, this.tmpY1)
        ctx.lineTo(this.tmpX2, this.tmpY2);
        ctx.closePath();
        ctx.stroke();
        ctx.beginPath();
        ctx.moveTo(this.tmpX2, this.tmpY2);
        ctx.lineTo(this.x2, this.y2);
        ctx.closePath();
        ctx.stroke();
        var endRadians = Math.atan((this.y2 - this.tmpY2) / (this.x2 - this.tmpX2));
        endRadians += ((this.x2 >= this.tmpX2) ? 90 : -90) * Math.PI / 180;
        this.drawArrowhead(ctx, this.x2, this.y2, endRadians);
    } else if(this.tmpX1 != null && this.tmpY1 != null && this.tmpX2 == null && this.tmpY2 == null) {
        ctx.lineTo(this.tmpX1, this.tmpY1);
        ctx.closePath();
        ctx.stroke();
        ctx.beginPath();
        ctx.moveTo(this.tmpX1, this.tmpY1)
        ctx.lineTo(this.x2, this.y2);
        ctx.closePath();
        ctx.stroke();
        var endRadians = Math.atan((this.y2 - this.tmpY1) / (this.x2 - this.tmpX1));
        endRadians += ((this.x2 >= this.tmpX1) ? 90 : -90) * Math.PI / 180;
        this.drawArrowhead(ctx, this.x2, this.y2, endRadians);
    }else if(this.tmpX1 == null && this.tmpY1 == null && this.tmpX2 == null && this.tmpY2 == null){
        ctx.lineTo(this.x2, this.y2);
        ctx.closePath();
        ctx.stroke();
        var endRadians = Math.atan((this.y2 - this.y1) / (this.x2 - this.x1));
        endRadians += ((this.x2 >= this.x1) ? 90 : -90) * Math.PI / 180;
        this.drawArrowhead(ctx, this.x2, this.y2, endRadians);
    }
}

/**
 * 画箭头
 */
Arrow.prototype.drawArrowhead = function(ctx, x, y, radians) {
    ctx.save();
    ctx.beginPath();
    ctx.translate(x, y);
    ctx.rotate(radians);
    ctx.moveTo(0, 0);
    ctx.lineTo(5, 10);
    ctx.lineTo(-5, 10);
    ctx.closePath();
    ctx.restore();
    ctx.fill();
}
// 
//  step.js
//  <流程图对象>
//  
//  Created by DurantSimpson on 2016-12-08.
//  Copyright 2016 DurantSimpson. All rights reserved.
// 
function drawRoundRect(x, y, w, h) {
    var r = h / 2;
    cxt.beginPath();
    cxt.moveTo(x + r, y);
    cxt.arcTo(x + w, y, x + w, y + h, r);
    cxt.arcTo(x + w, y + h, x, y + h, r);
    cxt.arcTo(x, y + h, x, y, r);
    cxt.arcTo(x, y, x + w, y, r);
    cxt.closePath();
    cxt.stroke();
}

function drawRhombus(x, y, l) {
    cxt.beginPath();
    cxt.moveTo(x, y + l);
    cxt.lineTo(x - l * 2, y);
    cxt.lineTo(x, y - l);
    cxt.lineTo(x + l * 2, y);
    cxt.closePath();
    cxt.stroke();
}

/**
 * 圆角矩形开始对象
 * @param {Object} x
 * @param {Object} y
 */
function Start(x, y) {
    this.h = 50;
    this.w = 2 * this.h;
    this.x = x;
    this.y = y;
    drawRoundRect(x - this.w / 2, y - this.h / 2, this.w, this.h);
}

/**
 * 矩形步骤对象
 * @param {Object} x
 * @param {Object} y
 */
function Step(x, y) {
    this.flag = "step";
    this.h = 50;
    this.w = 2 * this.h;
    this.x = x;
    this.y = y;
    cxt.strokeRect(x - this.w / 2, y - this.h / 2, this.w, this.h);
}

/**
 * 菱形条件对象
 * @param {Object} x
 * @param {Object} y
 */
function Condition(x, y) {
    this.flag = "condition";
    this.l = 30;
    this.x = x;
    this.y = y;
    drawRhombus(x, y, this.l);
}

Start.prototype.drawBottomToTop = function(obj) {
    if(obj.flag == "step") {
        var arrow = new Arrow(this.x, this.y + this.h / 2, obj.x, obj.y - obj.h / 2);
        arrow.drawBottomToTop(cxt);
    } else if(obj.flag == "condition") {
        var arrow = new Arrow(this.x, this.y + this.h / 2, obj.x, obj.y - obj.l);
        arrow.drawBottomToTop(cxt);
    }
}

Step.prototype.drawBottomToTop = function(obj) {
    if(obj.flag == "step") {
        var arrow = new Arrow(this.x, this.y + this.h / 2, obj.x, obj.y - obj.h / 2);
        arrow.drawBottomToTop(cxt);
    } else if(obj.flag == "condition") {
        var arrow = new Arrow(this.x, this.y + this.h / 2, obj.x, obj.y - obj.l);
        arrow.drawBottomToTop(cxt);
    }
}

Condition.prototype.drawBottomToTop = function(obj) {
    if(obj.flag == "step") {
        var arrow = new Arrow(this.x, this.y + this.l, obj.x, obj.y - obj.h / 2);
        arrow.drawBottomToTop(cxt);
    } else if(obj.flag == "condition") {
        var arrow = new Arrow(this.x, this.y + this.l, obj.x, obj.y - obj.l);
        arrow.drawBottomToTop(cxt);
    }
}

Condition.prototype.drawRightToTop = function(obj) {
    if(obj.flag == "step") {
        var arrow = new Arrow(this.x + this.l * 2, this.y, obj.x, obj.y - obj.h / 2);
        arrow.drawLeftOrRightToTop(cxt);
    } else if(obj.flag == "condition") {
        var arrow = new Arrow(this.x + this.l * 2, this.y, obj.x, obj.y - obj.l);
        arrow.drawLeftOrRightToTop(cxt);
    }
}

Condition.prototype.drawLeftToTop = function(obj) {
    if(obj.flag == "step") {
        var arrow = new Arrow(this.x - this.l * 2, this.y, obj.x, obj.y - obj.h / 2);
        arrow.drawLeftOrRightToTop(cxt);
    } else if(obj.flag == "condition") {
        var arrow = new Arrow(this.x - this.l * 2, this.y, obj.x, obj.y - obj.l);
        arrow.drawLeftOrRightToTop(cxt);
    }
}

Condition.prototype.drawRightToLeft = function(obj) {
    if(obj.flag == "step") {
        var arrow = new Arrow(this.x + this.l * 2, this.y, obj.x - this.w / 2, obj.y);
        arrow.drawLeftToRightOrRightToLeft(cxt);
    } else if(obj.flag == "condition") {
        var arrow = new Arrow(this.x + this.l * 2, this.y, obj.x - this.l * 2, obj.y);
        arrow.drawLeftToRightOrRightToLeft(cxt);
    }
}

Condition.prototype.drawLeftToRight = function(obj) {
    if(obj.flag == "step") {
        var arrow = new Arrow(this.x - this.l * 2, this.y, obj.x + this.w / 2, obj.y);
        arrow.drawLeftToRightOrRightToLeft(cxt);
    } else if(obj.flag == "condition") {
        var arrow = new Arrow(this.x - this.l * 2, this.y, obj.x + this.l * 2, obj.y);
        arrow.drawLeftToRightOrRightToLeft(cxt);
    }
}
// 
//  flow.js
//  <主要逻辑>
//  
//  Created by DurantSimpson on 2016-12-08.
//  Copyright 2016 DurantSimpson. All rights reserved.
// 
var canvas = document.getElementById("myCanvas");
var cxt = canvas.getContext('2d');

var start = new Start(600,25);//新建开始对象
var step1 = new Step(600,105);//新建第一个步骤

start.drawBottomToTop(step1); //画箭头(从开始对象指向第一个步骤)

var condition1 = new Condition(300, 200);//新建第一个条件对象
var condition2 = new Condition(450, 200);
var condition3 = new Condition(600, 200);
var condition4 = new Condition(750, 200);
var condition5 = new Condition(900, 200);

step1.drawBottomToTop(condition1);//画箭头(从第一个步骤指向第一个条件)
step1.drawBottomToTop(condition2);
step1.drawBottomToTop(condition3);
step1.drawBottomToTop(condition4);
step1.drawBottomToTop(condition5);

var step2 = new Step(450,295);
var step3 = new Step(750,295);

condition1.drawBottomToTop(step2);
condition2.drawBottomToTop(step2);
condition3.drawBottomToTop(step2);
condition4.drawBottomToTop(step3);
condition5.drawBottomToTop(step3);

var condition6 = new Condition(300, 400);
var condition7 = new Condition(450, 400);
var condition8 = new Condition(750, 400);
var condition9 = new Condition(900, 400);
var condition10 = new Condition(450, 500);
var condition11 = new Condition(900, 500);
var condition12 = new Condition(450, 600);
var condition13 = new Condition(900, 600);

step2.drawBottomToTop(condition6);
step3.drawBottomToTop(condition9);

var step4 = new Step(300,725);
var step5 = new Step(450,725);
var step6 = new Step(600,725);
var step7 = new Step(750,725);
var step8 = new Step(900,725);

condition6.drawBottomToTop(step4);
condition6.drawRightToLeft(condition7);
condition7.drawRightToTop(step6);
condition7.drawBottomToTop(condition10);
condition8.drawBottomToTop(step7);
condition9.drawLeftToRight(condition8);
condition9.drawBottomToTop(condition11);
condition10.drawBottomToTop(condition12);
condition11.drawBottomToTop(condition13);
condition12.drawBottomToTop(step5);
condition13.drawBottomToTop(step8);

/*canvas.onclick = function(e) { //给canvas添加点击事件
    e = e || event; //获取事件对象
    //获取事件在canvas中发生的位置
    var x = e.clientX - canvas.offsetLeft;
    var y = e.clientY - canvas.offsetTop;
    //如果事件位置在矩形区域中
    alert('x:' + x + "y:" + y);
     if(x>=rect.x&&x<=rect.x+rect.w&&y>=rect.y&&y<=rect.y+rect.h){
         alert('clicked')
     }
}*/

 

posted @ 2016-12-08 18:39  DurantSimpson  Views(18296)  Comments(1Edit  收藏  举报