当前位置: 代码迷 >> Web前端 >> mxgraph 之 自定义双方框长方形(即:doubleRectangle)
  详细解决方案

mxgraph 之 自定义双方框长方形(即:doubleRectangle)

热度:508   发布时间:2012-06-26 10:04:13.0
mxgraph 之 自定义双边框长方形(即:doubleRectangle)
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  
格叽格叽? 楼主好幽默
  相关解决方案