鱼骨图由日本管理大师石川馨先生所发明,故又名石川图。鱼骨图是一种发现问题“根本原因”的方法,它也可以称之为“Ishikawa”或者“因果图”。其特点是简捷实用,深入直观。它看上去有些象鱼骨,问题或缺陷(即后果)标在"鱼头"外。在鱼骨上长出鱼刺,上面按出现机会多寡列出产生生产问题的可能原因,有助于说明各个原因之间如何相互影响。

这玩意儿就体现了一个什么5w1h的管理方法,经过我将近4周的时间捣鼓。由于原先想实现的过于复杂(主要由于本人数学知识浅薄),后来放弃了原先的两个方案。一是分支斜线扩展;二是分支上下、左右扩展。

不知道写点个啥,直接上代码吧。

/*** Created by numen_huang on 2014/8/6.*/
$(function () {if (!mxClient.isBrowserSupported()) {// Displays an error message if the browser is not supported.mxUtils.error('Browser is not supported!', 200, false);}else {document.oncontextmenu = function () {return false;}var fish=new fishBone();fish.init();}
});
var fishBone=function(){};fishBone.prototype.graph=null;fishBone.prototype.init=function(){this.resetSourceCode();this.buildCanvas();this.setCanvasStyle();this.buildContextMenu();this.createFishBone();
};fishBone.prototype.resetSourceCode=function(){var _this=this;mxCellRenderer.prototype.createLabel = function(state, value) {var graph = state.view.graph;var isEdge = graph.getModel().isEdge(state.cell);if (state.style[mxConstants.STYLE_FONTSIZE] > 0 || state.style[mxConstants.STYLE_FONTSIZE] == null) {var isForceHtml = (graph.isHtmlLabel(state.cell) || (value != null && mxUtils.isNode(value))) && graph.dialect == mxConstants.DIALECT_SVG;var h='';var spacingRight=-30;var spacingLeft=1;if(state.cell.id=='fishboneHead'){h='horizontal';spacingRight=spacingLeft=0;}if(state.cell.level%2==0 && state.cell.id!='fishboneHead'){h='horizontal';if(_this.getSelfTopParent(state.cell).direction=='bottom') {spacingLeft = -25;}else{spacingLeft = 0;}}var background=state.style[mxConstants.STYLE_LABEL_BACKGROUNDCOLOR];var borderColor=state.style[mxConstants.STYLE_LABEL_BORDERCOLOR];var color=state.style[mxConstants.STYLE_FONTCOLOR];if(state.cell.level==1){background='#B3D9D9';borderColor='#005757';color='#336666';}else{background='#F3F3F3';borderColor='#005757';color='#336666';}state.text = new mxText(value, null, (state.style[mxConstants.STYLE_ALIGN] || mxConstants.ALIGN_CENTER),graph.getVerticalAlign(state),color,state.style[mxConstants.STYLE_FONTFAMILY], state.style[mxConstants.STYLE_FONTSIZE],state.style[mxConstants.STYLE_FONTSTYLE], state.style[mxConstants.STYLE_SPACING],spacingLeft, 10,spacingRight, 10, h,background, borderColor,graph.isWrapping(state.cell), graph.isLabelClipped(state.cell), state.style[mxConstants.STYLE_OVERFLOW]);state.text.opacity = state.style[mxConstants.STYLE_TEXT_OPACITY];state.text.dialect = (isForceHtml) ? mxConstants.DIALECT_STRICTHTML: state.view.graph.dialect;this.initializeLabel(state);var getState = function(evt) {var result = state;if (mxClient.IS_TOUCH) {var x = mxEvent.getClientX(evt);var y = mxEvent.getClientY(evt);var pt = mxUtils.convertPoint(graph.container, x, y);result = graph.view.getState(graph.getCellAt(pt.x, pt.y));}return result;};var md = (mxClient.IS_TOUCH) ? 'touchstart': 'mousedown';var mm = (mxClient.IS_TOUCH) ? 'touchmove': 'mousemove';var mu = (mxClient.IS_TOUCH) ? 'touchend': 'mouseup';mxEvent.addListener(state.text.node, md, mxUtils.bind(this,function(evt) {if (this.isLabelEvent(state, evt)) {graph.fireMouseEvent(mxEvent.MOUSE_DOWN, new mxMouseEvent(evt, state));}}));mxEvent.addListener(state.text.node, mm, mxUtils.bind(this,function(evt) {if (this.isLabelEvent(state, evt)) {graph.fireMouseEvent(mxEvent.MOUSE_MOVE, new mxMouseEvent(evt, getState(evt)));}}));mxEvent.addListener(state.text.node, mu, mxUtils.bind(this,function(evt) {if (this.isLabelEvent(state, evt)) {graph.fireMouseEvent(mxEvent.MOUSE_UP, new mxMouseEvent(evt, getState(evt)));}}));mxEvent.addListener(state.text.node, 'dblclick', mxUtils.bind(this,function(evt) {if (this.isLabelEvent(state, evt)) {graph.dblClick(evt, state.cell);mxEvent.consume(evt);}}));}};mxTriangle.prototype.redrawPath = function(path, x, y, w, h) {if (this.direction == mxConstants.DIRECTION_NORTH) {path.moveTo(0, h);path.lineTo(0.5 * w, 0);path.lineTo(w, h);} else if (this.direction == mxConstants.DIRECTION_SOUTH) {path.moveTo(0, 0);path.lineTo(0.5 * w, h);path.lineTo(w, 0);} else if (this.direction == mxConstants.DIRECTION_WEST) {path.moveTo(0, 0);path.lineTo(w, 0.5 * h);path.lineTo(0, h);}else if(this.direction == 'east'){path.moveTo(0, 0);path.quadTo(w, 0.25 * h,w+1,0.5*h);path.quadTo(w+1, 0.75 * h,0,h);}else{path.moveTo(0, 0);path.lineTo(w, 0.5 * h);path.lineTo(0, h);}path.close();};mxGraphSelectionModel.prototype.singleSelection = true;mxGraph.prototype.foldingEnabled=false;mxGraph.prototype.selectCellForEvent = function(cell, evt) {if(cell.id!='fishboneEnd' && cell.id!='fishboneBody' && !cell.isEdge()) {var isSelected = this.isCellSelected(cell);if (this.isToggleEvent(evt)) {if (isSelected) {this.removeSelectionCell(cell);} else {this.addSelectionCell(cell);}} else if (!isSelected || this.getSelectionCount() != 1) {this.setSelectionCell(cell);}}};mxGraph.prototype.moveCells = function(cells, dx, dy, clone, target, evt) {if(cells==null || cells.length>1){return false;}var cell=cells[0];if (dx != 0 || dy != 0 || clone || target != null) {this.getModel().beginUpdate();try {if (clone) {return false;}if(cell.level==1){var fishHead=_this.getCellById('fishboneHead');var fishBody=_this.getCellById('fishboneBody');var fishEnd=_this.getCellById('fishboneEnd');if(cell.geometry.x+dx>fishHead.geometry.x-100){cell.geometry.x+=dx;var size=cell.geometry.x-fishHead.geometry.x;fishHead.geometry.x+=size+100;fishBody.geometry.width+=size+100;}else if(cell.geometry.x+dx<fishEnd.geometry.x+fishEnd.geometry.width+100){cell.geometry.x+=dx;var size=cell.geometry.x-(fishEnd.geometry.x+fishEnd.geometry.width);fishBody.geometry.width+=Math.abs(size-100);fishEnd.geometry.x+=size-100;fishBody.geometry.x+=size-100;}else{cell.geometry.x+=dx;}}else if(cell.id=='fishboneHead'){var fishHead=_this.getCellById('fishboneHead');var fishBody=_this.getCellById('fishboneBody');var children=_this.getChildSubject(fishHead);var maxX=children.length>0?children[0].geometry.x:fishHead.geometry.x-30;for(var i=0;i<children.length;i++){if(children[i].geometry.x>maxX){maxX=children[i].geometry.x;}}var oldX=fishHead.geometry.x;fishHead.geometry.x+=dx;var size=fishHead.geometry.x-oldX;if(fishHead.geometry.x<maxX+100){fishHead.geometry.x=maxX+100;size = fishHead.geometry.x-oldX;}fishBody.geometry.width+=size;}else if(cell.id=='fishboneEnd'){var fishHead=_this.getCellById('fishboneHead');var fishBody=_this.getCellById('fishboneBody');var fishEnd=_this.getCellById('fishboneEnd');var children=_this.getChildSubject(fishHead);var minX=children.length>0?children[0].geometry.x:fishEnd.geometry.x-100;for(var i=0;i<children.length;i++){if(children[i].geometry.x<minX){minX=children[i].geometry.x;}}var oldX=fishEnd.geometry.x;fishEnd.geometry.x+=dx;var size=fishEnd.geometry.x-oldX;if(fishEnd.geometry.x>minX-100){fishEnd.geometry.x=minX-100;size=fishEnd.geometry.x-oldX;}fishBody.geometry.x=fishEnd.geometry.x+fishEnd.geometry.width;fishBody.geometry.width-=size;}else if (cell.direction == 'top' || cell.direction == 'bottom') {if(cell.parent.children.length==1){cell.geometry.x=0;cell.parent.geometry.width-=dx;cell.parent.geometry.x+=dx;if(cell.parent.geometry.width<=70){cell.parent.geometry.width=70;cell.parent.geometry.x=-70;}}else{if(cell.geometry.x==0){if(dx<0){for(var i=0;i<cell.parent.children.length;i++){if(cell.parent.children[i].id!=cell.id){cell.parent.children[i].geometry.x-=dx;}}cell.parent.geometry.width-=dx;cell.parent.geometry.x+=dx;cell.geometry.x=0;}else{if(cell.parent.children.length==1){if(cell.geometry.x+dx<cell.parent.geometry.width-70){cell.geometry.x+=dx;}else{cell.geometry.x=cell.parent.geometry.width-70;}}else{var children=cell.parent.children;var temp1=children[0];//最小y坐标的cellvar t=0;for (var i = 0; i < children.length; i++) {if (children[i].geometry.x < temp1.geometry.x) {temp1 = children[i];}if(children[i].geometry.x==0){t++;}}var temp2=null;//第二小x坐标的cellfor (var i = 0; i < children.length; i++) {if (children[i].geometry.x > cell.geometry.x && !temp2) {temp2=children[i];continue;}else if(temp2) {if (children[i].geometry.x < temp2.geometry.x && children[i].id != cell.id) {temp2 = children[i];}}}if(temp2 && t==1) {//没有超过第二小x坐标if (temp2.geometry.x - dx > 0) {for (var k = 0; k < cell.parent.children.length; k++) {if (cell.parent.children[k].id != cell.id) {cell.parent.children[k].geometry.x -= dx;}}cell.geometry.x += dx;cell.parent.geometry.width -= dx;cell.parent.geometry.x += dx;cell.geometry.x = 0;}//超过第二小x坐标else {if(cell.parent.geometry.width-temp2.geometry.x==70){for (var k = 0; k < cell.parent.children.length; k++) {cell.parent.children[k].geometry.x=0;}cell.parent.geometry.width=70;cell.parent.geometry.x=-70;}else {var size = dx - temp2.geometry.x;var pSize = cell.parent.geometry.width - temp2.geometry.x;for (var k = 0; k < cell.parent.children.length; k++) {if (cell.parent.children[k].id != temp2.id && cell.parent.children[k].id != cell.id) {cell.parent.children[k].geometry.x -= temp2.geometry.x;}}cell.parent.geometry.width -= temp2.geometry.x;cell.parent.geometry.x += temp2.geometry.x;temp2.geometry.x = 0;if(size-pSize>0){cell.geometry.x = cell.parent.geometry.width-70;}else {cell.geometry.x = size;}}}}else if(t>1){if(cell.geometry.x+dx<cell.parent.geometry.width-70){cell.geometry.x+=dx;}else{cell.geometry.x=cell.parent.geometry.width-70;}}}}}else{if(cell.geometry.x+dx<0){var size = 0-(cell.geometry.x+dx);for (var i = 0; i < cell.parent.children.length; i++) {if (cell.parent.children[i].id !=cell.id) {cell.parent.children[i].geometry.x+=size;}}cell.parent.geometry.x-=size;cell.parent.geometry.width+=size;cell.geometry.x=0;}else if(cell.geometry.x+dx==0){cell.geometry.x=0;}else if(cell.geometry.x+dx>0 && cell.geometry.x+dx<cell.parent.geometry.width-70){cell.geometry.x+=dx;}else{cell.geometry.x=cell.parent.geometry.width-70;}}}}else if(cell.direction == 'left'){var py = 0;var myCell=cell;if(cell.parent.direction=='bottom') {cell.geometry.y += dy;for (var i = 0; i < cell.parent.children.length; i++) {if (cell.parent.children[i].geometry.y > py)py = cell.parent.children[i].geometry.y;}if(py>70) {cell.parent.geometry.height = py;}else{cell.parent.geometry.height = 70;}if(cell.geometry.y<70){cell.geometry.y=70;}}else{if(cell.geometry.y==0){if(dy<0) {for (var i = 0; i < cell.parent.children.length; i++) {if (cell.parent.children[i].id != cell.id) {cell.parent.children[i].geometry.y -= dy;}}cell.parent.geometry.y += dy;cell.parent.geometry.height -= dy;}else{//只有一个子集的时候if(cell.parent.children.length==1){var fishBody=_this.getCellById('fishboneBody');//拖动超过父级label的位置if(!(cell.geometry.y==0 && cell.parent.geometry.height==70)) {if (cell.parent.geometry.height - dy < 70) {if(cell.parent.parent.id==1){cell.parent.geometry.y = fishBody.geometry.y - 68;}else{cell.parent.geometry.y = cell.parent.parent.geometry.y - 70;}cell.parent.geometry.height = 70;} else {cell.parent.geometry.height -= dy;cell.parent.geometry.y += dy;}cell.geometry.y = 0;}}else {//超过一个子集var children=cell.parent.children;var temp1=children[0];//最小y坐标的cellvar t=0;for (var i = 0; i < children.length; i++) {if (children[i].geometry.y < temp1.geometry.y) {temp1 = children[i];}if(children[i].geometry.y==0){t++;}}var temp2=null;//第二小y坐标的cellfor (var i = 0; i < children.length; i++) {if (children[i].geometry.y > temp1.geometry.y && !temp2) {temp2=children[i];continue;}else if(temp2) {if (children[i].geometry.y < temp2.geometry.y && children[i].id != temp1.id) {temp2 = children[i];}}}//当没有超过第二小y坐标时。if(temp2 && t==1) {if (cell.geometry.y + dy < temp2.geometry.y) {for (var k = 0; k < cell.parent.children.length; k++) {if (cell.parent.children[k].id != cell.id) {cell.parent.children[k].geometry.y -= dy;}}cell.parent.geometry.height -= dy;cell.parent.geometry.y += dy;cell.geometry.y = 0;}//当超过第二小y坐标时候else {cell.geometry.y += dy;var py = cell.parent.geometry.height - (cell.parent.geometry.height - temp2.geometry.y);for (var k = 0; k < cell.parent.children.length; k++) {if (cell.parent.children[k].id != temp2.id) {cell.parent.children[k].geometry.y -= py;}}cell.parent.geometry.height -= temp2.geometry.y;cell.parent.geometry.y += temp2.geometry.y;temp2.geometry.y = 0;for (var j = 0; j < cell.parent.children.length; j++) {if (cell.parent.geometry.height - cell.parent.children[j].geometry.y < 70) {cell.parent.children[j].geometry.y = cell.parent.geometry.height - 70;}}}}else if(t>1){if(cell.parent.geometry.height>70) {if (cell.parent.geometry.height - dy < 70) {cell.geometry.y = 70;} else {cell.geometry.y = dy;}}}}}}else{if(cell.geometry.y+dy>0){if(cell.parent.geometry.height-(cell.geometry.y+dy)<=70){cell.geometry.y=cell.parent.geometry.height-70;}else {cell.geometry.y += dy;}}else{for (var i = 0; i < cell.parent.children.length; i++) {if (cell.parent.children[i].id != cell.id) {cell.parent.children[i].geometry.y -= (cell.geometry.y+dy);}}cell.parent.geometry.y += (cell.geometry.y+dy);cell.parent.geometry.height -= cell.geometry.y+dy;cell.geometry.y=0;}}}}} finally {this.getModel().endUpdate();this.refresh();}}return cells;};mxGraph.prototype.dblClick = function(evt, cell) {if(cell.id!='fishboneEnd' && cell.id!='fishboneBody' && !cell.isEdge()) {var mxe = new mxEventObject(mxEvent.DOUBLE_CLICK, 'event', evt, 'cell', cell);this.fireEvent(mxe);if (this.isEnabled() && !mxEvent.isConsumed(evt) && !mxe.isConsumed() && cell != null && this.isCellEditable(cell)) {this.startEditingAtCell(cell, evt);}}};
//    mxGraph.prototype.labelChanged = function(cell, value, evt) {
//        this.model.beginUpdate();
//        var geo=cell.geometry;
//        try {
//            this.cellLabelChanged(cell, value, true);
//            this.fireEvent(new mxEventObject(mxEvent.LABEL_CHANGED, 'cell', cell, 'value', value, 'event', evt));
//            geo.height =geo.height+((value.length-5>0)? (value.length-5)*18:0);
//            cell.geometry=geo;
//            if(cell.level>1){var myEdge = cell.edges[0];var point = myEdge.geometry.points[0];point.x=0;myEdge.geometry.points=[point];
//            }
//        } finally {
//            this.model.endUpdate();
//        }
//        return cell;
//    };mxCellEditor.prototype.init = function() {this.textarea = document.createElement('input');this.textarea.className = 'mxCellEditor';this.textarea.style.position = 'absolute';this.textarea.style.overflow = 'visible';this.textarea.setAttribute('type', 'textbox');if (false) {this.textarea.style.resize = 'none';}mxEvent.addListener(this.textarea, 'blur', mxUtils.bind(this,function(evt) {this.stopEditing(!this.graph.isInvokesStopCellEditing());}));mxEvent.addListener(this.textarea, 'keydown', mxUtils.bind(this,function(evt) {if (!mxEvent.isConsumed(evt)) {if (evt.keyCode == 113 || (this.graph.isEnterStopsCellEditing() && evt.keyCode == 13 && !mxEvent.isControlDown(evt) && !mxEvent.isShiftDown(evt))) {this.graph.stopEditing(false);mxEvent.consume(evt);} else if (evt.keyCode == 27) {this.graph.stopEditing(true);mxEvent.consume(evt);} else {if (this.clearOnChange) {this.clearOnChange = false;this.textarea.value = '';}this.setModified(true);}}}));};mxGraphHandler.prototype.selectEnabled=false;
};fishBone.prototype.buildCanvas=function(){var container = document.createElement('div');container.style.position = 'absolute';container.style.overflow = 'hidden';container.style.left = '0px';container.style.top = '0px';container.style.right = '0px';container.style.bottom = '0px';document.body.appendChild(container);var node = mxUtils.load('config/keyhandler-commons.xml').getDocumentElement();this.editor = new mxEditor(node);this.editor.graph=new mxGraph(container);this.graph = this.editor.graph;var outline = document.getElementById('outlineContainer');new mxOutline(this.graph, outline);if (mxClient.IS_IE) {new mxDivResizer(container);new mxDivResizer(outline);}this.graph.clearSelection();this.graph.setEnabled(true);this.graph.setTooltips(false);this.graph.setConnectable(false);this.graph.setPanning(true);this.graph.setCellsResizable(false);
};fishBone.prototype.setCanvasStyle=function(){var graph=this.graph;var style = graph.getStylesheet().getDefaultVertexStyle();style[mxConstants.STYLE_FONTCOLOR] = 'black';style[mxConstants.STYLE_STROKECOLOR] = '#8E8E8E';style[mxConstants.STYLE_FILLCOLOR] = 'white';style[mxConstants.STYLE_ROUNDED] = true;style[mxConstants.STYLE_FONTSTYLE] = 1;style[mxConstants.STYLE_FONTFAMILY] = '微软雅黑';// Sets the default style for edgesstyle = graph.getStylesheet().getDefaultEdgeStyle();style[mxConstants.STYLE_ROUNDED] = true;style[mxConstants.STYLE_EDGE] = mxEdgeStyle.STRAIGHT;// Enables rubberband selection and key handlingvar rubberband = new mxRubberband(graph);var keyHandler = new mxKeyHandler(graph);
};fishBone.prototype.buildContextMenu=function(){var fish=this;mxPopupMenu.prototype.submenuImage = 'src/images/submenu.gif';this.graph.panningHandler.factoryMethod = function (menu, cell, evt) {if (cell != null && !cell.isEdge() && cell.id!='fishboneEnd' && cell.id!='fishboneBody') {var item= menu.addItem('插入','src/images/maximize.gif');menu.addItem('插入主题','src/images/maximize.gif', function () {fish.createSubject(cell);fish.graph.clearSelection();},item);menu.addItem('插入子主题','src/images/normalize.gif', function () {fish.createSubject(cell,true);fish.graph.clearSelection();},item);menu.addItem('删除','images/delete2.png', function () {fish.graph.removeCells([cell]);});menu.addItem('编辑','images/icons48/tab.png', function () {fish.graph.startEditingAtCell(cell);});}else{this.graph.clearSelection();};};
};fishBone.prototype.createFishBone=function(){var xml = '\<mxGraphModel>                                                                 \<root>                                                                       \<mxCell id="0"/>                                                           \<mxCell id="1" parent="0"/>                                                \<mxCell id="fishboneEnd" value="" parent="1" vertex="1" style="shape=triangle;direction=east1;fillColor=#CEFFCE;gradientColor=#93FF93;">      \<mxGeometry x="510" y="240" width="40" height="110" as="geometry"/>      \</mxCell>                                                                  \<mxCell id="fishboneBody" value="" vertex="1" parent="1" style="shape=triangle;direction=west;fillColor=#4F4F4F;">        \<mxGeometry x="550" y="290" width="800" height="10" as="geometry"/>      \</mxCell>                                                                  \<mxCell id="fishboneHead" level="0" value="需要解决的问题" vertex="1" parent="1" style="shape=triangle;direction=east;fillColor=#CEFFCE;gradientColor=#93FF93;fontSize=18;">           \<mxGeometry x="1351" y="252" width="150" height="80" as="geometry"/>     \</mxCell>\</root>                                                                      \</mxGraphModel>                                                                \';doc = mxUtils.parseXml(xml);var codec = new mxCodec(doc);//mxShape.prototype.direction = mxConstants.DIRECTION_NORTH;codec.decode(doc.documentElement, this.graph.getModel());var items=['人员','管理','过程','环境','设备','材料'];var cell=this.getCellById('fishboneHead');for(var i=0;i<items.length;i++) {this.createSubject(cell, true,items[i]);};
};fishBone.prototype.createSubject=function(cell,isSub,text){var model=this.graph.getModel();var graph=this.graph;var fish=this;var x = 0, y = 0, py = 0, px = 0;var myChild = fish.getChildSubject(cell);if(!cell.children)cell.children=[];//子主题在下方,插入子主题方向错误//子主题在右侧,插入子主题方向错误/*水平方向子主题*/var insertHorizontalSubLevel=function(){var selfTopParent = fish.getSelfTopParent(cell);if (!text)text = '分支主题' + (cell.children.length + 1);x = -70;if(selfTopParent.direction=='bottom') {if (cell.children.length == 0) {y = 70;} else {y += cell.geometry.height+70;}var myCell = graph.insertVertex(cell, null, text, x, y, 70, 1, 'shape=line;verticalAlign=top;align=right;strokeWidth=1;strokeColor=#BB3D00;');myCell.level = cell.level + 1;myCell.direction = 'left';myCell.geometry.x -= 70;if (myCell.parent.parent.direction == 'left') {myCell.parent.parent.geometry.height = 1;}var resize = function (cell) {if (cell.parent.direction == 'bottom' && cell.parent.level > 1) {if (cell.parent.parent.children.length > 1 && cell.parent.children.length == 1 && cell.parent.geometry.x > 0) {for (var k = 0; k < cell.parent.parent.children.length; k++) {if (cell.parent.parent.children[k].geometry.x >= cell.parent.geometry.x && cell.parent.children.length == 1) {cell.parent.parent.children[k].geometry.x += 50;cell.parent.parent.geometry.x -= 50;cell.parent.parent.geometry.width += 50;}}}cell.parent.geometry.height = cell.parent.children[cell.parent.children.length - 1].geometry.y;} else {cell.parent.geometry.height = 1;}if (cell.parent.level != 1) {resize(cell.parent);} else {cell.parent.geometry.height = cell.parent.children[cell.parent.children.length - 1].geometry.y;}};resize(myCell);}else{y = 0;for(var i=0;i<cell.children.length;i++){cell.children[i].geometry.y+=70;}if(cell.children.length>0) {cell.geometry.height += 70;cell.geometry.y -= 70;}var myCell = graph.insertVertex(cell, null, text, x, y, 70, 1, 'shape=line;verticalAlign=top;align=right;strokeWidth=1;strokeColor=#BB3D00;');myCell.level = cell.level + 1;myCell.direction = 'left';myCell.geometry.x -= 70;if (myCell.parent.parent.direction == 'left') {myCell.parent.parent.geometry.height = 1;}var resize = function (cell) {if(cell.direction=='top' && cell.level!=1 && cell.children.length==1){for(var k=cell.parent.children.length-1;k>=0;k--){if(cell.parent.children[k].geometry.x>=cell.geometry.x){cell.parent.children[k].geometry.x+=cell.children[0].geometry.width;}}cell.geometry.x-=myCell.geometry.width;}};resize(myCell.parent);}};/*垂直方向子主题*/var insertVerticalSubLevel=function(){var selfTopParent = fish.getSelfTopParent(cell);var leftTopParents=fish.getLeftTopParent(selfTopParent,true);if (!text)text = '分支主题'+(cell.children.length+1);if(cell.children.length==0)x=0;else {var maxX=0;for(var i=0;i<cell.children.length;i++){if(cell.children[i].geometry.x>maxX){maxX=cell.children[i].geometry.x;}}x = 50 + maxX;}var align='right';var direction='bottom';if(selfTopParent.direction=='bottom') {y = 1;}else{y=0;align='left';direction='top';}var myCell = graph.insertVertex(cell, null, text, x, y, 1, 70, 'shape=line;direction=north;verticalAlign=top;align='+align+';spacingBottom=10;strokeWidth=1;strokeColor=#BB3D00;');myCell.parentId = cell.id;myCell.level=cell.level+1;myCell.direction=direction;if(selfTopParent.direction=='bottom') {if (cell.children.length == 1) {var t = 0;for (var i = 0; i < cell.parent.children.length; i++) {if (cell.parent.children[i].id != cell.id && cell.parent.children[i].geometry.y > cell.geometry.y) {cell.parent.children[i].geometry.y += myCell.geometry.height;t++;}}if (t > 0) {selfTopParent.geometry.height += myCell.geometry.height;}};var resize = function (cell) {var parent = cell.parent;if(parent.id!=1) {if (cell.direction == 'left')cell.geometry.height = 1;if (parent.direction == 'left') {parent.geometry.height = 1;if (parent.children.length > 1 && cell.geometry.x > 0) {parent.geometry.width += 50;parent.geometry.x -= 50;}resize(parent);} else {parent.geometry.height = parent.children[parent.children.length - 1].geometry.y;if (parent.level != 1 && parent.parent.children.length > 1 && cell.parent.geometry.x > 0) {for (var k = 0; k < parent.parent.children.length; k++) {if (parent.parent.children[k].geometry.x >= parent.geometry.x)parent.parent.children[k].geometry.x += 50;}}resize(parent);}}};resize(myCell);}else{myCell.geometry.y-=70;var t=0;if (cell.children.length == 1&&cell.geometry.y>0) {for (var i = 0; i < cell.parent.children.length; i++) {if(cell.parent.children[i].geometry.y>0 && cell.parent.children[i].geometry.y>=cell.geometry.y){cell.parent.children[i].geometry.y+=cell.geometry.height;t++;}}cell.parent.geometry.height += myCell.geometry.height;cell.parent.geometry.y -= myCell.geometry.height;};var resize = function (cell) {if (cell.direction == 'left') {cell.geometry.height = 1;if(cell.children.length>1){for (var k = 0; k < cell.children.length; k++) {if (cell.children[k].geometry.x <= cell.geometry.x)cell.children[k].geometry.x += 50;}cell.geometry.x-=50;cell.geometry.width+=50;}}else {if(cell.children.length>1){for (var k = 0; k < cell.children.length; k++) {if (cell.children[k].geometry.x >= cell.geometry.x)cell.children[k].geometry.x += 50;}cell.geometry.x-=50;}}};resize(myCell.parent);}};var insertTopLevel=function(){var direction='bottom';if(myChild.length%2==0){direction='top';}model.beginUpdate();x = cell.geometry.x - (myChild.length / 2 * 100) - (myChild.length + 1) * 30;if(myChild.length>0) {x = myChild[0].geometry.x;for (var t = 0; t < myChild.length; t++) {if (myChild[t].geometry.x < x) {x = myChild[t].geometry.x;}}}x-=100;if (myChild.length % 2 == 0) {y = cell.geometry.y - 30;} else {y = cell.geometry.y + 45;}if (!text)text = '分支主题';var vAlign='top';var dir='north';var align='right';if (myChild.length % 2 == 0) {vAlign='bottom';dir='south';align='left';}var myCell = graph.insertVertex(graph.getDefaultParent(), null, text, x, y, 1, 70, 'shape=line;align='+align+';verticalAlign='+vAlign+';direction='+dir+';verticalLabelPosition=middle;fontSize=18;strokeWidth=1;strokeColor=#8C8C00;');myCell.parentId = cell.id;myCell.level=cell.level+1;myCell.direction=direction;model.endUpdate();graph.clearSelection();};var insert=function(){if(cell.level==0){insertTopLevel();}else{if(isSub){insertSubLevel();}else{insertSameLevel();}}};var insertSameLevel=function(){if(cell.level){if(cell.level==1){cell=fish.getCellById('fishboneHead');myChild = fish.getChildSubject(cell);insertTopLevel();}else{cell=cell.parent;myChild = cell.children;insertSubLevel();}}else{cell=cell.parent;myChild = cell.children;insertTopLevel();}};var insertSubLevel=function(){switch (cell.direction){case 'left':insertVerticalSubLevel();break;case 'top':case 'bottom':insertHorizontalSubLevel();break;}graph.refresh();};insert();
};fishBone.prototype.getChildSubject=function(cell){var allCells=this.graph.model.root.children[0].children;var children=[];for(var i=0;i<allCells.length;i++){if(allCells[i].parentId==cell.id){children.push(allCells[i]);}}return children;
};fishBone.prototype.getCellById=function(id){var allCells=this.graph.model.root.children[0].children;for(var i=0;i<allCells.length;i++){if(allCells[i].id==id){return allCells[i];}}return null;
};/** 获取当前主题的1级主题* */
fishBone.prototype.getSelfTopParent=function(cell){if(cell.level==1){return cell;}else{if(cell.parent.level==1){return cell.parent;}else{return this.getSelfTopParent(cell.parent);}}
};
/** 获取左侧所有1级主题* */
fishBone.prototype.getLeftTopParent=function(selfParentCell,isBottom){var allCells=this.graph.model.root.children[0].children;var arr=[];for(var i=0;i<allCells.length;i++){if(isBottom){if(allCells[i].level==1 && allCells[i].direction=='bottom' && allCells[i].geometry.x<selfParentCell.geometry.x){arr.push(allCells[i]);}}else{}}return arr;
};
/** 获取除自己以外的1级主题* */
fishBone.prototype.getOtherTopParentCell=function(selfParentCell){var allCells=this.graph.model.root.children[0].children;var allTopParentCell=[];for(var i=0;i<allCells.length;i++){if(allCells[i].level==1 && allCells[i].id!=selfParentCell.id){allTopParentCell.push(allCells[i]);}}return allTopParentCell;
}


mxGraph实现鱼骨图(因果图)相关推荐

  1. vue+gojs 绘制鱼骨图(因果图)

    最近查找js相关的鱼骨图组件,找了半天都没有合适的,自己参考gojs官网demo简单的实现了下,效果如下. 废话少说,直接上代码. 引入gojs npm install gojs --save 整合到 ...

  2. java 鱼刺图_鱼骨图问题分析法

    发表于 2017-05-02 06:00:22 by 月小升 A.整理问题型鱼骨图(各要素与特性值间不存在原因关系,而是结构构成关系) B.原因型鱼骨图(鱼头在右,特性值通常以"为什么--& ...

  3. 因果图,鱼骨图,石川图

    因果图,又称鱼骨图或石川图.问题陈述放在鱼骨的头部,作为起点,用来追溯问题来源,回推到可行动的根本原因.在问题陈述中,通常把问题描述为一个要被弥补的差距或要达到的目标.通过看问题陈述和问"为 ...

  4. 测试用例设计方法-因果图(鱼骨图)

    因果图,又叫鱼骨图 输入与输入之间的关系 异:所有输入条件中最多有一个为真,也可以一个也没有 或:所有输入条件中最少有一个为真,或者多个,或者所有 唯一:所有输入条件中,有且只有一个条件为真 要求:所 ...

  5. Mindmanager 甘特图杠上Mindmanager 鱼骨图

    2019独角兽企业重金招聘Python工程师标准>>> MindManager中文版作为一种优秀的思维导图工具,加入甘特图功能后,使其功能更加强大,应用范围更广泛.而推荐用MindM ...

  6. 鱼骨图分析法实际案例_【管理工具详解】鱼骨图分析法

    第一部分 鱼骨头分析法 一.鱼骨图分析法的由来 鱼骨图是由日本管理大师石川馨先生所发明出来的,故又名石川图.鱼骨图是一种发现问题"根本原因"的方法,它也可以称之为"Ish ...

  7. 鱼骨图分析法实际案例_让你头脑更精明的十种思考法:鱼骨图

    鱼骨图又名特性因素图是由日本管理大师石川馨先生所发展出来的,故又名石川图.鱼骨图是一种发现问题"根本原因"的方法,它也可以称之为"因果图".鱼骨图原本用于质量管 ...

  8. 鱼骨图分析法实际案例_会用“鱼骨图”的项目经理无难题

    项目经理在遇到一些瓶颈问题时,如何突破这些难题? 答案就是鱼骨图!项目经理,广州深圳PMP培训,PMP认证考试培训机构,圣略PMP培训考试 1.鱼骨图分析法介绍 鱼骨图的由来及含义 鱼骨图是由日本管理 ...

  9. 软考知识点梳理--鱼骨图

    因果图,又称鱼骨图或石川图.问题陈述放在鱼骨的头部,作为起点,用来追溯问题来源,回推到可行动的根本原因.在问题陈述中,通常把问题描述为一个要被弥 补的差距或要达到的目标.通过看问题陈述和问" ...

最新文章

  1. python到底可以做什么-Python到底可以做什么?
  2. 妇女在IT安全工作人员当中的比例只有10%
  3. CISCO交换机如何删除 Vlan
  4. OCR文字识别在计算机视觉的重要性、基本技术和最新进展
  5. Netty学习总结(5)——Netty之TCP粘包/拆包问题的解决之道
  6. Docker仓库介绍和镜像加速器
  7. html5兼容QQ浏览器,【QQ浏览器5.1】发布 HTML5兼容性测试
  8. 编程珠玑java_编程珠玑第八章
  9. PS冬日圣诞水彩素材
  10. Linux配置免密码登录(原理 + 实践)
  11. 哪些地方需要使用到301转向
  12. 花生壳 linux客户端 命令
  13. Win10睡眠后自动唤醒启动的问题
  14. Mac中Chrome浏览器的快捷键
  15. 韩服游戏IP用哪里的比较稳定怎么选择服务器
  16. 逻辑回归中常用的概念: WOE、IV详解
  17. css——三角形的实现
  18. java浮点数化为整数_[Java教程]javascript浮点数转换成整数三种方法
  19. 压力传感器变送器的作用
  20. python技术介绍_Python介绍

热门文章

  1. 滑块验证码和图片验证码
  2. 数学基础_设随机变量X1,X2,…Xn相互独立,且都服从(0,θ)上的均匀分布。求U=max{X1,X2,…Xn}数学期望
  3. ImageMagick将多张图片拼接成一张图片_长图拼接app下载-长图拼接最新版下载v2.8.6...
  4. windows10连接共享打印机显示“0x0000011b”错误的解决方法
  5. 京东店铺详情页如何做关联销售?如何给图片加热点链接?
  6. spring boot 虚拟路径url中文无法访问
  7. 关于GD32的CMakeLists以及gcc部分编译选项的解释
  8. python怎么操作打印机打印文字
  9. linux18.04安装显卡驱动,Ubuntu18.04安装nvidia显卡驱动
  10. 人工智能中的Web端编程