1、写在前面:关于双边框形状,在mxgraph中有双边框椭圆形(doubleEllipse),我的双边框长方形就是据此拓展的。
2、该形状的用途:这个图形也是很有必要的,它可用在BPMN中的事务子流程。
3、关键拓展代码:
extension.js
/** * 新增表单样式doubleRectangle * **/ function mxDoubleRectangle(bounds, fill, stroke, strokewidth){ this.bounds = bounds; this.fill = fill; this.stroke = stroke; this.strokewidth = (strokewidth != null) ? strokewidth: 1; } mxDoubleRectangle.prototype = new mxShape(); mxDoubleRectangle.prototype.constructor = mxDoubleRectangle; mxDoubleRectangle.prototype.createVml = function() { this.node = document.createElement('v:group'); var name = (this.isRounded) ? 'v:roundrect': 'v:rect'; this.background = document.createElement(name); this.configureVmlShape(this.background); this.node.appendChild(this.background); // this.label = this.background; this.isShadow = false; this.fill = null; this.foreground = document.createElement(name); this.configureVmlShape(this.foreground); this.node.appendChild(this.foreground); this.stroke = null; this.configureVmlShape(this.node); return this.node; }; mxDoubleRectangle.prototype.createSvg = function() { var g = this.createSvgGroup('rect'); this.foreground = document.createElementNS(mxConstants.NS_SVG, 'rect'); this.foreground.setAttribute('shape-rendering', 'optimizeSpeed'); this.foreground.setAttribute('fill', 'none'); g.appendChild(this.foreground); return g; }; mxDoubleRectangle.prototype.redrawSvg = function(node) { if (this.innerNode != null) { this.updateSvgShape(this.innerNode); if (this.shadowNode != null) { this.updateSvgShape(this.shadowNode); } } else { this.updateSvgShape(this.node); } this.updateSvgGlassPane(); this.updateSvgNode(this.foreground, 8); }; mxDoubleRectangle.prototype.redrawVml = function() { this.node.style.visibility = 'hidden'; this.updateVmlShape(this.node); this.updateVmlGlassPane(); this.node.style.visibility = 'hidden'; this.background.style.visibility = 'hidden'; this.updateVmlShape(this.background); this.updateVmlGlassPane(); this.background.style.visibility = 'visible'; this.foreground.style.visibility = 'hidden'; this.updateVmlShape(this.foreground); this.updateVmlGlassPane(); this.foreground.style.visibility = 'visible'; var inset = 8; var w = Math.floor(this.bounds.width); var h = Math.floor(this.bounds.height); var x = Math.floor(this.bounds.x); var y = Math.floor(this.bounds.y); this.background.style.top = inset/2 + 'px'; this.background.style.left = inset/2 + 'px'; this.background.style.width = Math.max(0, w - inset) + 'px'; this.background.style.height = Math.max(0, h - inset) + 'px'; }; mxDoubleRectangle.prototype.updateSvgNode = function(node, inset) { inset = (inset != null) ? inset: 0; if (node != null) { var strokeWidth = Math.max(1, this.strokewidth * this.scale); if (this.crisp) { node.setAttribute('shape-rendering', 'crispEdges'); } else { node.removeAttribute('shape-rendering'); } if (this.style != null && this.style[mxConstants.STYLE_SMOOTH]) { var pts = this.points; var n = pts.length; if (n > 3) { var points = 'M ' + pts[0].x + ' ' + pts[0].y + ' '; points += ' Q ' + pts[1].x + ' ' + pts[1].y + ' ' + ' ' + pts[2].x + ' ' + pts[2].y; for (var i = 3; i < n; i++) { points += ' T ' + pts[i].x + ' ' + pts[i].y; } node.setAttribute('d', points); } } if (this.isDashed) { var phase = Math.max(1, Math.floor(3 * this.scale)); node.setAttribute('stroke-dasharray', phase + ',' + phase); } if (this.isRounded) { var w = this.bounds.width-inset; var h = this.bounds.height-inset; var r = Math.min(w * mxConstants.RECTANGLE_ROUNDING_FACTOR, h * mxConstants.RECTANGLE_ROUNDING_FACTOR); node.setAttribute('rx', r); node.setAttribute('ry', r); } node.setAttribute('stroke',this.stroke); node.setAttribute('stroke-width', strokeWidth); node.setAttribute('x', this.bounds.x +inset/2); node.setAttribute('y', this.bounds.y +inset/2); node.setAttribute('width', Math.max(0, this.bounds.width - inset)); node.setAttribute('height', Math.max(0, this.bounds.height - inset)); } }; mxDoubleRectangle.prototype.configureVmlShape = function(node) { node.style.position = 'absolute'; var color = this.stroke; if (color != null && color != mxConstants.NONE) { node.setAttribute('stroked', 'true'); node.setAttribute('strokecolor', color); } else { node.setAttribute('stroked', 'false'); } color = this.fill; node.style.background = ''; if (color != null && color != mxConstants.NONE) { if (this.fillNode == null) { this.fillNode = document.createElement('v:fill'); node.appendChild(this.fillNode); } this.updateVmlFill(this.fillNode, color, this.gradient, this.gradientDirection, this.opacity); } else { node.setAttribute('filled', 'false'); if (this.points == null) { this.configureTransparentBackground(node); } } if ((this.isDashed || this.opacity != null) && this.strokeNode == null) { this.strokeNode = document.createElement('v:stroke'); node.appendChild(this.strokeNode); } if (this.strokeNode != null) { if (this.strokeNode != null) { if (this.isDashed) { var phase = Math.max(1, Math.floor(3 * this.scale)); var pat = phase + ' ' + phase; if (this.strokeNode.getAttribute('dashstyle') != pat) { this.strokeNode.setAttribute('dashstyle', pat); } } else if (this.strokeNode.getAttribute('dashstyle') != 'solid') { this.strokeNode.setAttribute('dashstyle', 'solid'); } } if (this.opacity != null) { this.strokeNode.setAttribute('opacity', this.opacity + '%'); } } if (this.isShadow && this.fill != null) { if (this.shadowNode == null) { this.shadowNode = document.createElement('v:shadow'); this.shadowNode.setAttribute('on', 'true'); this.shadowNode.setAttribute('color', mxConstants.SHADOWCOLOR); node.appendChild(this.shadowNode); } } if (node.nodeName == 'roundrect') { try { node.setAttribute('arcsize', String(mxConstants.RECTANGLE_ROUNDING_FACTOR * 100) + '%'); } catch(e) {} } this.strokeNode = null; }; /** *拓展该形状输出img的绘制方法 **/ mxImageExport.prototype.initShapes = function() { this.shapes = []; //其他形状的绘制也在此定义,就是源码中的,在此只写了新增的代码 this.shapes['doubleRectangle'] = { drawShape: function(canvas, state, bounds, background) { if (background) { if (mxUtils.getValue(state.style, mxConstants.STYLE_ROUNDED, false)) { var size = Math.max(bounds.width / 10, bounds.height / 10); canvas.roundrect(bounds.x, bounds.y, bounds.width, bounds.height, size, size); } else { canvas.rect(bounds.x, bounds.y, bounds.width, bounds.height); } return true; } else { canvas.fillAndStroke(); var inset = 8; var x = bounds.x; var y = bounds.y; var w = bounds.width; var h = bounds.height; x += inset/2; y += inset/2; w -= inset; h -= inset; if (w > 0 && h > 0) { if (mxUtils.getValue(state.style, mxConstants.STYLE_ROUNDED, false)) { var size = Math.max(w / 10, h / 10); canvas.rect(x, y, w,h,size,size); }else { canvas.rect(x,y,w,h); } } canvas.stroke(); } } }; };
4、应用方法:
应用新的样式时可以在default-style.xml中写该样式:
<add as="transaction" > <add as="shape" value="doubleRectangle"/> <add as="strokeColor" value="black"/> <add as="fillColor" value="#F2F2F2"/> <add as="gradientColor" value="#F2F2F2"/> <add as="verticalAlign" value="top"/> <add as="rounded" value="0"/> </add>
这就是BPMN中事务子流程的样式定义。
然后,在graph的js中:
graph.cellRenderer.registerShape('doubleRectangle', mxDoubleRectangle); var style = graph.getStylesheet().getDefaultVertexStyle(); style[mxConstants.STYLE_SHAPE] = 'doubleRectangle';
这样就可以用这个样式啦啦~~
*************************格叽格叽**************************
终于写完了 lysh miss wanan~
1 楼
59445088
2012-04-17
格叽格叽? 楼主好幽默