//1.引入js

//画流程图

//画所有的图形:画图和画对应的箭头

function drawFlowChart(context, canvas, flowdata, initTop, initSpaceH) {

//1、判断是否有需要平均计算x的数据

flowdata.forEach(function (row) {

if (row.isAverage) {

row.data = calChartX(canvas.width, row.data, row.y);

}

});

//2、先要画完所有的图形

flowdata.forEach(function (row, rowIndex) {

row.y = row.y ? row.y : (rowIndex == 0 ? initTop + initSpaceH : initTop + initSpaceH * rowIndex);

row = drawRowChart(context, row); //画图形

});

//3、添加要指向的对象,必须要在画完所有图形之后

flowdata.forEach(function (row) {

row.data.forEach(function (item) {

if (item.arrowArr && item.arrowArr.length) {

item.arrowArr.forEach(function (mItem) {

mItem = addToObj(mItem, flowdata);

})

}

})

});

//4、给所有图形画上对应的画箭头,必须要在前两步完成之后

flowdata.forEach(function (row, rowIndex) {

row.data.forEach(function (item) {

if (item.arrowArr && item.arrowArr.length) {

drawSingleArrow(context, item);//画箭头

}

})

});

//5、给所有元素添加点击和悬浮事件

addMethod(canvas, flowdata)

}

//当一行有n个图形并且需要平均排列时用此方法计算每个图形的x

function calChartX(canvasW, data, dataY) {

var startW = 80;

var stepW = 120;

var CondW = 30;

var count = 0;

for (var i = 0; i < data.length; i++) {

if (data[i].type == 'Step') {

if (data[i].direction != undefined) {

stepW = -120;

}

count += stepW;

} else if (data[i].type == 'Start' || data[i].type == 'End') {

count += startW;

} else if (data[i].type == 'Condition') {

count += CondW;

}

}

//spaceW 计算一行中每个图形的平均间距

var spaceW = parseInt((canvasW - count) / (data.length + 1));

//计算坐标x

var prevDiv = [], curW = 0;

for (var i = 0; i < data.length; i++) {

if (data[i].type == 'Step') {

prevDiv.push(stepW);

curW = stepW / 2;

} else if (data[i].type == 'Start' || data[i].type == 'End') {

prevDiv.push(startW);

curW = startW / 2;

} else if (data[i].type == 'Condition') {

prevDiv.push(CondW);

curW = CondW / 2;

}

var preLength = 0;

for (var j = 0; j < i; j++) {

preLength += prevDiv[j];

}

var x = spaceW * (i + 1) + preLength + curW;

var y = data[i].y;

data[i]['x'] = x;

data[i]['y'] = y ? y : dataY;

}

return data;

}

//生成每列对应的图形

function drawRowChart(context, row) {

row.data.forEach(function (item, index) {

var s = null;

item.y = item.y ? item.y : row.y;

if (item.type == 'Step') {

s = new Step(context, item.x, item.y, item);

} else if (item.type == 'Condition') {

s = new Condition(context, item.x, item.y, item);

} else if (item.type == 'End') {

s = new End(context, item.x, item.y, item);

} else if (item.type == 'Start') {

s = new Start(context, item.x, item.y, item);

}

item.chartObj = s;

})

return row;

}

//绘制单个的图形

function drawSingleChart(context, item) {

var s = '';

if (item.type == 'Step') {

s = new Step(context, item.x, item.y, item);

} else if (item.type == 'Condition') {

s = new Condition(context, item.x, item.y, item);

} else if (item.type == 'End') {

s = new End(context, item.x, item.y, item);

} else if (item.type == 'Start') {

s = new Start(context, item.x, item.y, item);

}

item.chartObj = s;

return item;

}

//每个对象的坐标范围

function calRange(obj) {

var newObj = {

minX: obj.x - obj.w / 2,

maxX: obj.x + obj.w / 2,

minY: obj.y - obj.h / 2,

maxY: obj.y + obj.h / 2

}

return newObj;

}

//处理每一个箭头需要指向的对象

function addToObj(arrObj, flowData) {

flowData.forEach(function (rows) {

rows.data.forEach(function (item) {

if (item.name == arrObj.to) {

arrObj.to = item.chartObj;

}

})

})

return arrObj;

}

//话每个图形的箭头指向

function drawSingleArrow(context, data) {

var step1 = data.chartObj;

if (data.arrowArr && data.arrowArr.length) {

data.arrowArr.forEach(function (item) {

step1[item.arrow](item.to, context);

})

}

}

//清除单个图形

function repaintSingleChart(context, item) {

var range = item.chartObj.range;

//清除之前画的图形

context.clearRect(range.minX - 1, range.minY - 1, item.chartObj.w + 2, item.chartObj.h + 3);

}

//给所有图形添加事件

function addMethod(canvas, flowData) {

//给所有图形添加点击事件

canvas.onclick = function (ev) {

var ev = ev || window.event;

var ua = navigator.userAgent.toLowerCase();

var isIE = ua.indexOf("compatible") > -1 && ua.indexOf("msie") > -1 && !ua.indexOf("opera") > -1; //IE浏览器

var isEdge = ua.indexOf("Edge") > -1;

var isIE11 = ua.toLowerCase().match(/rv:([\d.]+)\) like gecko/);

var curx = (isIE || isEdge || isIE11) ? ev.offsetX : ev.layerX;

var cury = (isIE || isEdge || isIE11) ? ev.offsetY : ev.layerY;

flowData.forEach(function (row, listIndex) {

row.data.forEach(function (item) {

var range = item.chartObj.range;

if (curx >= range.minX && curx <= range.maxX && cury >= range.minY && cury <= range.maxY) {

var clickMethod = null;

if (row.method && row.method.onclick) { //如果每行定义了事件

//判断每个元素是否有单独定义事件,如果有,取改元素定义的事件,如果没有取每行定义的事件

if (item.method && item.method.onclick) {

clickMethod = item.method.onclick

} else {

clickMethod = row.method.onclick

}

} else {

if (item.method && item.method.onclick) {

clickMethod = item.method.onclick

} else {

clickMethod = null;

}

}

if (clickMethod instanceof Function) {

clickMethod(item);

}

}

})

});

};

var timer = null;

//给所有图形添加mousemove事件

canvas.onmousemove = function (ev) {

var ev = ev || window.event;

var ua = navigator.userAgent.toLowerCase();

var isIE = ua.indexOf("compatible") > -1 && ua.indexOf("msie") > -1 && !ua.indexOf("opera") > -1; //IE浏览器

var isEdge = ua.indexOf("Edge") > -1;

var isIE11 = ua.toLowerCase().match(/rv:([\d.]+)\) like gecko/);

var curx = (isIE || isEdge || isIE11) ? ev.offsetX : ev.layerX;

var cury = (isIE || isEdge || isIE11) ? ev.offsetY : ev.layerY;

clearTimeout(timer);

flowData.forEach(function (row, listIndex) {

row.data.forEach(function (item) {

var range = item.chartObj.range;

if (curx >= range.minX && curx <= range.maxX && cury >= range.minY && cury <= range.maxY) {

var clickMethod = null;

if (row.method && row.method.onmousemove) { //如果每行定义了事件

//判断每个元素是否有单独定义事件,如果有,取改元素定义的事件,如果没有取每行定义的事件

if (item.method && item.method.onmousemove) {

clickMethod = item.method.onmousemove

} else {

clickMethod = row.method.onmousemove

}

} else {

if (item.method && item.method.onmousemove) {

clickMethod = item.method.onmousemove

} else {

clickMethod = null;

}

}

if (clickMethod instanceof Function) {

timer = setTimeout(function () {

clickMethod(item);

}, 1000)

}

}

})

});

}

//给所有图形添加mouseleave事件

canvas.onmouseleave = function (ev) {

var ev = ev || window.event;

var ua = navigator.userAgent.toLowerCase();

var isIE = ua.indexOf("compatible") > -1 && ua.indexOf("msie") > -1 && !ua.indexOf("opera") > -1; //IE浏览器

var isEdge = ua.indexOf("Edge") > -1;

var isIE11 = ua.toLowerCase().match(/rv:([\d.]+)\) like gecko/);

var curx = (isIE || isEdge || isIE11) ? ev.offsetX : ev.layerX;

var cury = (isIE || isEdge || isIE11) ? ev.offsetY : ev.layerY;

clearTimeout(timer);

flowData.forEach(function (row) {

row.data.forEach(function (item) {

var range = item.chartObj.range;

if (curx >= range.minX && curx <= range.maxX && cury >= range.minY && cury <= range.maxY) {

var clickMethod = null;

if (row.method && row.method.onmouseleave) { //如果每行定义了事件

//判断每个元素是否有单独定义事件,如果有,取改元素定义的事件,如果没有取每行定义的事件

if (item.method && item.method.onmouseleave) {

clickMethod = item.method.onmouseleave

} else {

clickMethod = row.method.onmouseleave

}

} else {

if (item.method && item.method.onmouseleave) {

clickMethod = item.method.onmouseleave

} else {

clickMethod = null;

}

}

if (clickMethod instanceof Function) {

clickMethod(item);

}

}

})

});

}

}

/基本画图形start

//画圆角矩形

function drawRoundRect(context, x, y, w, h, item, radius) {

radius = radius || 20;

context.beginPath();

context.arc(x + radius, y + radius, radius, Math.PI, Math.PI * 3 / 2);

context.lineTo(w - radius + x, y);

context.arc(w - radius + x, radius + y, radius, Math.PI * 3 / 2, Math.PI * 2);

context.lineTo(w + x, h + y - radius);

context.arc(w - radius + x, h - radius + y, radius, 0, Math.PI * 1 / 2);

context.lineTo(radius + x, h + y);

context.arc(radius + x, h - radius + y, radius, Math.PI * 1 / 2, Math.PI);

context.closePath();

context.fillStyle = item.color ? (item.color.bgColor ? item.color.bgColor : 'rgba(91,155,213,0.5)') : 'white'; //背景颜色

context.fill();

context.lineWidth = 2;

context.strokeStyle = item.color ? (item.color.borderColor ? item.color.borderColor : '#5B9BD5') : '#5B9BD5'; //边框颜色

context.font = 'normal 12px 微软雅黑';

context.fillStyle = item.color ? (item.color.fontColor ? item.color.fontColor : '#5B9BD5') : '#5B9BD5'; //文字颜色

context.textAlign = "center";

// context.fillText(item.text, x + w / 2, y + h / 2 + 6);

// context.stroke();

if (item.direction != undefined) {

var x = x + w / 2;

var y = y + 10;

let letterSpacing = 3; // 设置字间距

for (let i = 0; i < item.text.length; i++) {

const str = item.text.slice(i, i + 1).toString();

context.save();

context.textBaseline = 'top';

context.fillText(str, x, y);

context.restore();

y += context.measureText(str).width + letterSpacing; // 计算文字宽度

}

var str = item.num;

context.save();

context.textBaseline = 'top';

context.fillText(str, x, y);

context.restore();

y += context.measureText('人').width + letterSpacing; // 计算文字宽度

var str = item.unit;

context.save();

context.textBaseline = 'top';

context.fillText(str, x, y);

context.restore();

y += context.measureText(str).width + letterSpacing; // 计算文字宽度

context.stroke();

} else {

context.fillText(item.text, x + w / 2, y + h / 2 + 6);

context.stroke();

}

}

//画菱形

function drawRhombus(context, x, y, l, h, item) {

context.beginPath();

context.moveTo(x, y + h);

context.lineTo(x - l * 2 - 40, y);

context.lineTo(x, y - h);

context.lineTo(x + l * 2 + 40, y);

context.closePath();

context.strokeStyle = item.color ? (item.color.borderColor ? item.color.borderColor : '#5B9BD5') : '#5B9BD5'; //边框颜色

context.fillStyle = item.color ? (item.color.bgColor ? item.color.bgColor : 'rgba(91,155,213,0.5)') : 'white'; //背景颜色

context.fill();

context.fillStyle = item.color ? (item.color.fontColor ? item.color.fontColor : '#5B9BD5') : '#5B9BD5'; //文字颜色

context.font = 'normal 14px 微软雅黑';

context.fillText(item.text, x, y + 3);

context.stroke();

}

//计算文本的宽高

function textSize(fontSize, fontFamily, text) {

var span = document.createElement("span");

span.className = "text";

var result = {};

result.width = span.offsetWidth;

result.height = span.offsetHeight;

span.style.visibility = "hidden";

span.style.fontSize = fontSize;

span.style.fontFamily = fontFamily;

span.style.display = "inline-block";

document.body.appendChild(span);

if (typeof span.textContent != "undefined") {

span.textContent = text;

} else {

span.innerText = text;

}

result.width = parseFloat(window.getComputedStyle(span).width) - result.width;

result.height = parseFloat(window.getComputedStyle(span).height) - result.height;

var list = document.body.getElementsByClassName('text')[0];

document.body.removeChild(list);

return result;

}

//Start 圆角矩形对象

function Start(context, x, y, item, h, w) {

this.flag = 'start';

var textStyle = textSize('14px', '微软雅黑', item.text);

w = parseInt(textStyle.width) + 30;

this.h = h || 40;

this.w = w || 2 * this.h;

this.x = x;

this.y = y;

this.text = item.text;

this.range = calRange(this);

drawRoundRect(context, x - this.w / 2, y - this.h / 2, this.w, this.h, item);

}

//End 圆角矩形对象

function End(context, x, y, item, h, w) {

this.flag = 'end';

var textStyle = textSize('14px', '微软雅黑', item.text);

w = parseInt(textStyle.width) + 30;

this.h = h || 40;

this.w = w || 2 * this.h;

this.x = x;

this.y = y;

this.text = item.text;

this.range = calRange(this);

drawRoundRect(context, x - this.w / 2, y - this.h / 2, this.w, this.h, item, 20);

}

//Step 矩形对象

function Step(context, x, y, item) {

this.flag = "step";

var textStyle = textSize('14px', '微软雅黑', item.text);

// var w = parseInt(textStyle.width) + 30;

var w = parseInt(textStyle.width) + 30;

this.h = 40;

this.w = w;

this.x = x;

this.y = y;

this.text = item.text;

this.color = item.color;

this.direction = item.direction;

this.range = calRange(this);

// context.strokeStyle= item.color ? (item.color.borderColor ? item.color.borderColor: '#5B9BD5'):'#5B9BD5' ; //边框颜色

// context.strokeRect(x - this.w / 2, y - this.h / 2, this.w, this.h);

// context.fillStyle = item.color ? (item.color.bgColor ? item.color.bgColor: 'rgba(91,155,213,0.5)'):'white' ; //背景颜色

// context.fillRect(x - this.w / 2, y - this.h / 2,this.w,this.h);

// context.fillStyle = item.color ? (item.color.fontColor ? item.color.fontColor: '#5B9BD5'):'#5B9BD5' ; //文字颜色

// context.textAlign = 'center';

// context.font = 'normal 14px 微软雅黑';

// if(item.text){context.fillText(item.text,x, y+4);}

// drawRoundRect(context, x - this.w / 2, y - this.h / 2, this.w, this.h, item, 5);

if (item.direction != undefined) {

this.w = 40;

this.h = w+20;

drawRoundRect(context, x - this.w / 2, y - this.w / 2, this.w, this.h, item, 5);

} else {

drawRoundRect(context, x - this.w / 2, y - this.h / 2, this.w, this.h, item, 5);

}

}

//Condition 菱形对象

function Condition(context, x, y, item) {

this.flag = "condition";

var textStyle = textSize('14px', '微软雅黑', item.text);

var w = parseInt(textStyle.width) / 4;

this.l = w;

this.h = 40;

this.w = w;

this.x = x;

this.y = y;

this.text = item.text;

this.range = calRange(this);

drawRhombus(context, x, y, this.l, this.h, item);

}

/基本画图形end

画箭头/

//箭头从start圆角矩形bottom——>top

Start.prototype.drawBottomToTop = function (obj, context) {

if (obj.flag == "step") {

var arrow = new Arrow(this.x, this.y + this.h / 2, obj.x, obj.y - obj.h / 2);

arrow.drawBottomToTop(context);

} else if (obj.flag == "condition") {

var arrow = new Arrow(this.x, this.y + this.h / 2, obj.x, obj.y - obj.l);

arrow.drawBottomToTop(context);

}

}

//箭头从step矩形bottom——>right

Step.prototype.drawBottomToRight = function (obj, context) {

var arrow = null;

if (obj.flag == "step") {

arrow = new Arrow(this.x, this.y + this.h / 2, obj.x + obj.w / 2, obj.y);

} else if (obj.flag == "condition") {

arrow = new Arrow(this.x, this.y + this.h / 2, obj.x + obj.l * 2 + 40, obj.y);

} else if (obj.flag == "start" || obj.flag == "end") {

arrow = new Arrow(this.x, this.y + this.h / 2, obj.x + obj.w / 2, obj.y);

}

arrow.drawBottomToRight(context);

}

//箭头从step矩形bottom——>left

Step.prototype.drawBottomToLeft = function (obj, context) {

var arrow = null;

if (obj.flag == "step") {

arrow = new Arrow(this.x, this.y + this.h / 2, obj.x - obj.w / 2, obj.y);

} else if (obj.flag == "condition") {

arrow = new Arrow(this.x, this.y + this.h / 2, obj.x - obj.l * 2 - 40, obj.y);

} else if (obj.flag == "start" || obj.flag == "end") {

arrow = new Arrow(this.x, this.y + this.h / 2, obj.x - obj.w / 2, obj.y);

}

arrow.drawBottomToRight(context);

}

//箭头从step矩形bottom——>top

Step.prototype.drawBottomToTop = function (obj, context) {

if (obj.flag == "step") {

if (obj.direction != undefined) {

var arrow = new Arrow(this.x, this.y + this.h / 2, obj.x, obj.y - obj.w / 2, obj.color.lineColor);

arrow.drawBottomToTop(context);

} else {

var arrow = new Arrow(this.x, this.y + this.h / 2, obj.x, obj.y - obj.h / 2, obj.color.lineColor);

arrow.drawBottomToTop(context);

}

} else if (obj.flag == "condition") {

var arrow = new Arrow(this.x, this.y + this.h / 2, obj.x, obj.y - obj.h);

arrow.drawBottomToTop(context);

}

}

//箭头从step矩形right——>left

Step.prototype.drawRightToLeft = function (obj, context) {

var arrow = null;

if (obj.flag == "step") {

arrow = new Arrow(this.x + this.w / 2, this.y, obj.x - obj.w / 2, obj.y);

} else if (obj.flag == "condition") {

arrow = new Arrow(this.x + this.w / 2, this.y, obj.x - obj.l * 2, obj.y);

} else if (obj.flag == "start" || obj.flag == "end") {

arrow = new Arrow(this.x + this.w / 2, this.y, obj.x - obj.w / 2, obj.y);

}

arrow.drawLeftToRightOrRightToLeft(context);

}

//箭头从Condition菱形Bottom——>top

Condition.prototype.drawBottomToTop = function (obj, context) {

if (obj.flag == "step") {

var arrow = new Arrow(this.x, this.y + this.h, obj.x, obj.y - obj.h / 2);

arrow.drawBottomToTop(context);

} else if (obj.flag == "condition") {

var arrow = new Arrow(this.x, this.y + this.l, obj.x, obj.y - obj.l);

arrow.drawBottomToTop(context);

}

}

//箭头从Condition菱形right——>top

Condition.prototype.drawRightToTop = function (obj, context) {

if (obj.flag == "step") {

var arrow = new Arrow(this.x + this.l * 2, this.y, obj.x, obj.y - obj.h / 2);

arrow.drawLeftOrRightToTop(context);

} else if (obj.flag == "condition") {

var arrow = new Arrow(this.x + this.l * 2, this.y, obj.x, obj.y - obj.l);

arrow.drawLeftOrRightToTop(context);

}

}

//箭头从Condition菱形left——>top

Condition.prototype.drawLeftToTop = function (obj, context) {

if (obj.flag == "step") {

var arrow = new Arrow(this.x - this.l * 2, this.y, obj.x, obj.y - obj.h / 2);

arrow.drawLeftOrRightToTop(context);

} else if (obj.flag == "condition") {

var arrow = new Arrow(this.x - this.l * 2, this.y, obj.x, obj.y - obj.l);

arrow.drawLeftOrRightToTop(context);

}

}

//箭头从Condition菱形right——>left

Condition.prototype.drawRightToLeft = function (obj, context) {

if (obj.flag == "step") {

var arrow = new Arrow(this.x + this.l * 2, this.y, obj.x - this.w / 2, obj.y);

arrow.drawLeftToRightOrRightToLeft(context);

} 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(context);

}

}

//箭头从Condition菱形left——>right

Condition.prototype.drawLeftToRight = function (obj, context) {

if (obj.flag == "step") {

var arrow = new Arrow(this.x - this.l * 2, this.y, obj.x + this.w / 2, obj.y);

arrow.drawLeftToRightOrRightToLeft(context);

} 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(context);

}

}

/画箭头start/

function Arrow(x1, y1, x2, y2, color) {

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 = "#5B9BD5";

this.color = color == undefined ? "#5B9BD5" : color;

}

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.drawBottomToRight = function (ctx) {

if (this.y1 != this.y2) {

this.setP1(this.x1, 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();

}

2.demo

Title

var canvas = document.getElementById("myCanvas");

var cxt = canvas.getContext('2d');

var canWidth = cxt.canvas.clientWidth;

var init = { top: 32, spaceH: 100 };

var row2 = {

y: init.top + init.spaceH,

data: [

{

type: 'Step',

text: '市委办局9999人',

name: 'step_2_1',

x: '',

y: '',

requestData: {},

color: {

bgColor: '#3D6667',

borderColor: "#4ee9a2",

fontColor: "#fff",

lineColor: '#59B6D9'

}

},

{

type: 'Step',

text: '区县级19999人',

name: 'step_2_2',

color: {

bgColor: '#3D6667',

borderColor: "#4ee9a2",

fontColor: "#fff",

lineColor: '#59B6D9'

},

arrowArr: [

{

arrow: 'drawBottomToTop',

to: 'step_3_1'

},

{

arrow: 'drawBottomToTop',

to: 'step_3_2'

},

{

arrow: 'drawBottomToTop',

to: 'step_3_3'

},

{

arrow: 'drawBottomToTop',

to: 'step_3_4'

}

]

},

{

type: 'Step',

text: '市级园区0人',

name: 'step_2_3',

color: {

bgColor: '#3D6667',

borderColor: "#4ee9a2",

fontColor: "#fff",

lineColor: '#59B6D9'

}

}

]

};

var row3 = {

y: init.top + init.spaceH * 2,

data: [

{

type: 'Step',

text: '区直属1234人',

name: 'step_3_1',

direction: 1,

// count: 1,

color: {

bgColor: '#4B4966',

borderColor: "#B75E55",

fontColor: "#fff",

lineColor: '#4ee9a2'

}

},

{

type: 'Step',

text: '乡镇街道1298人',

name: 'step_3_2',

direction: 1,

color: {

bgColor: '#4B4966',

borderColor: "#B75E55",

fontColor: "#fff",

lineColor: '#4ee9a2'

},

// count: 1.15,

},

{

type: 'Step',

text: '区委办局8752人',

name: 'step_3_3',

color: {

bgColor: '#4B4966',

borderColor: "#B75E55",

fontColor: "#fff",

lineColor: '#4ee9a2'

},

direction: 1,

// count: 0.95

},

{

type: 'Step',

text: '区县级园区9870人',

name: 'step_3_4',

color: {

bgColor: '#4B4966',

borderColor: "#B75E55",

fontColor: "#fff",

lineColor: '#4ee9a2'

},

direction: 1,

// count: 1

}

]

};

row2.data = calChartX(canWidth, row2.data, row2.y);

row3.data = calChartX(canWidth, row3.data, row3.y);

var flowData = [

{

row: 1,

y: init.top,

data: [

{

type: 'Step',

text: '网格员总人数3334人',

name: 'step_1_1',

color: {

bgColor: '#365F87',

borderColor: "#59B6D9",

fontColor: "#fff"

},

arrowArr: [

{

arrow: 'drawBottomToTop',

to: 'step_2_1'

},

{

arrow: 'drawBottomToTop',

to: 'step_2_2'

},

{

arrow: 'drawBottomToTop',

to: 'step_2_3'

}

],

x: canWidth / 2,

y: ''

}

],

method: {

onmousemove: null,

onmouseleave: null,

onclick: hoverSingleChart

}

},

{

row: 2,

y: init.top + init.spaceH,

data: row2.data,

method: {

onmousemove: null,

onmouseleave: null,

onclick: hoverSingleChart

}

},

{

row: 3,

y: init.top + init.spaceH * 2,

data: row3.data,

method: {

onmousemove: null,

onmouseleave: null,

onclick: hoverSingleChart

},

}

];

drawFlowChart(cxt, canvas, flowData, init.top, init.spaceH);

function hoverSingleChart(singleData) {

console.log(singleData);

alert('--');

}

html css画流程图,css canvas 绘制流程图(1)相关推荐

  1. word流程图擦除_word画流程图 Word中绘制流程图的正确姿势,这招大多数人不知道...

    如何在Word中绘制流程图?相信这个问题,许多人都知道,大多数人也都会.不过,还是有大多数人使用的方法却不是正确的方法.所以,今天小编就来为大家讲一下如何正确的绘制流程图.用正确的方法绘制流程图,事半 ...

  2. 流程图怎么画?如何轻松绘制流程图

    流程图画的好可以让自己的设计思路更加简洁明了,不仅是对自己对使用者来说也会更加的方便.我们在绘制流程图时很多朋友还是在使用手绘流程图,其实是利用Word,PPT或者是一些专业的流程图软件也可以实现绘制 ...

  3. html css画五角星,css画梯形,css画五角星, css画六角星 ,css画六边形

    css画梯形,css画五角星, css画六角星 ,css画六边形 css画梯形 .triangle { border-bottom: 100px solid #F36823; border-left: ...

  4. 设计流程图框架以及绘制流程图方法介绍

    流程图可以是一件事情的操作过程,可以是解决问题的方法,也可以是解决某个教学问题的解题步骤,涉及的行业有很多,使用起来也是较为方便的,流程图的搭建是由无数个流程图图形进行组合而成,那具体要怎样设计怎样绘 ...

  5. MySQL系统流程图怎么画_Word流程图怎么画?如何轻松绘制流程图

    流程图是表示生产作业前后次序的图示.不管是对于科学工作者还是设计专业毕业生来说,流程图画的好,可以让自己的设计思路简洁明了,表达的更清晰.一般绘制流程图选择Word和专业流程图绘制工具-亿图图示,本文 ...

  6. 一文读懂:程序员为什么要学会画流程图 11种流程图的绘制工具:processon,wps,draw.io, 迅捷画图等 详细说明使用processon绘制流程图 详细说明绘制流程图

    这里写目录标题 为什么要学会画流程图 11种画流程图的工具 processon wps draw.io Zen Flowchart xGraph lucidchart boardmix plantum ...

  7. Word流程图怎么画?如何轻松绘制流程图

    流程图是表示生产作业前后次序的图示.不管是对于科学工作者还是设计专业毕业生来说,流程图画的好,可以让自己的设计思路简洁明了,表达的更清晰.一般绘制流程图选择Word和专业流程图绘制工具-亿图图示,本文 ...

  8. php代码画表情包,canvas绘制表情包的示例代码

    本文介绍了canvas绘制表情包的示例代码,分享给大家,具体如下: 绘制卡通笑脸 var canvas = document.getElementById('canvas'); var context ...

  9. 使用css画太极,CSS画太极阴阳图

    引言 CSS可以画很多图形,今天我们来画一个特殊的图形--中国古代哲学的"太极图". 如果没有用CSS画过简单图形,建议先学习如何用border属性画三角形. 构思 步骤 1.在 ...

  10. android ui的绘制流程图,使用jsPlumb绘制流程图

    类似上述图例,一般在系统中审批配置中用到,今天亲身经历给大家讲述下jsplumb+jqueryUI来绘制流程图. 这个应该是官方的API: https://docs.jsplumbtoolkit.c. ...

最新文章

  1. 小shell脚本---查找目录下面包含string的文件
  2. 在ComboBox控件中使用嵌入字体。
  3. 代码组(1) 对代码组的管理
  4. 一个SQL的几种写法
  5. oracle间隔分区
  6. ARMV8/ARMV9指令集概述(翻译)
  7. Google 与 GitHub 结盟,为保护软件供应链而战!
  8. java 判断是否是昨天_java判断日期是否是今天
  9. 七种方法实现单例模式
  10. Java Web开发实战经典(基础篇)
  11. Pycharm修改镜像源并添加信任
  12. 我想请教一下我这个错误的原因以及怎么解决,求各位大佬帮忙,感激不尽。
  13. ECCV2022 Workshop | 复杂环境中的多目标跟踪和分割
  14. office2013来了
  15. 【新塘N76E003】NU-LINK脱机烧写
  16. VMware下怎么批量创建,克隆,迁移虚拟机
  17. [附源码]计算机毕业设计JAVA音乐网站
  18. 【C3】cpu_wtd_sysfs
  19. Windows与macOS水火不容?有了它一切搞定
  20. 行人重识别简介(Person ReID)

热门文章

  1. java 当前utc时间_Java获取UTC时间的方法详解
  2. 数字化转型中的五大陷阱
  3. 江苏科技报:《电子名片悄然流行,纸质名片会被淘汰吗》
  4. 自制编译器:语法分析器(二)
  5. 最高月薪20K?平均薪资近万...在华为子公司工作是什么体验?
  6. 初学python爬虫,记录一下学习过程,requests库模拟登录01
  7. 【一起入门MachineLearning】中科院机器学习-期末题库-【单选题5,7,69+多选题3+计算题9,10,11】
  8. shell命令sh、dash、bash、rbash的区别
  9. Scala语言基础详解,并在IDEA中安装Scala插件
  10. python破解zip密码