<!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') } }*/