cytoscape
Version:
Graph theory (a.k.a. network) library for analysis and visualisation
219 lines (159 loc) • 5.78 kB
JavaScript
import * as math from '../../../math';
let CRp = {};
CRp.drawElement = function( context, ele, shiftToOriginWithBb, showLabel, showOverlay, showOpacity ){
let r = this;
if( ele.isNode() ){
r.drawNode( context, ele, shiftToOriginWithBb, showLabel, showOverlay, showOpacity );
} else {
r.drawEdge( context, ele, shiftToOriginWithBb, showLabel, showOverlay, showOpacity );
}
};
CRp.drawElementOverlay = function( context, ele ){
let r = this;
if( ele.isNode() ){
r.drawNodeOverlay( context, ele );
} else {
r.drawEdgeOverlay( context, ele );
}
};
CRp.drawElementUnderlay = function( context, ele ){
let r = this;
if( ele.isNode() ){
r.drawNodeUnderlay( context, ele );
} else {
r.drawEdgeUnderlay( context, ele );
}
};
CRp.drawCachedElementPortion = function( context, ele, eleTxrCache, pxRatio, lvl, reason, getRotation, getOpacity ){
let r = this;
let bb = eleTxrCache.getBoundingBox(ele);
if( bb.w === 0 || bb.h === 0 ){ return; } // ignore zero size case
let eleCache = eleTxrCache.getElement( ele, bb, pxRatio, lvl, reason );
if( eleCache != null ){
let opacity = getOpacity(r, ele);
if( opacity === 0 ){ return; }
let theta = getRotation(r, ele);
let { x1, y1, w, h } = bb;
let x, y, sx, sy, smooth;
if( theta !== 0 ){
let rotPt = eleTxrCache.getRotationPoint(ele);
sx = rotPt.x;
sy = rotPt.y;
context.translate(sx, sy);
context.rotate(theta);
smooth = r.getImgSmoothing(context);
if( !smooth ){ r.setImgSmoothing(context, true); }
let off = eleTxrCache.getRotationOffset(ele);
x = off.x;
y = off.y;
} else {
x = x1;
y = y1;
}
let oldGlobalAlpha;
if( opacity !== 1 ){
oldGlobalAlpha = context.globalAlpha;
context.globalAlpha = oldGlobalAlpha * opacity;
}
context.drawImage( eleCache.texture.canvas, eleCache.x, 0, eleCache.width, eleCache.height, x, y, w, h );
if( opacity !== 1 ){
context.globalAlpha = oldGlobalAlpha;
}
if( theta !== 0 ){
context.rotate(-theta);
context.translate(-sx, -sy);
if( !smooth ){ r.setImgSmoothing(context, false); }
}
} else {
eleTxrCache.drawElement( context, ele ); // direct draw fallback
}
};
const getZeroRotation = () => 0;
const getLabelRotation = (r, ele) => r.getTextAngle(ele, null);
const getSourceLabelRotation = (r, ele) => r.getTextAngle(ele, 'source');
const getTargetLabelRotation = (r, ele) => r.getTextAngle(ele, 'target');
const getOpacity = (r, ele) => ele.effectiveOpacity();
const getTextOpacity = (e, ele) => ele.pstyle('text-opacity').pfValue * ele.effectiveOpacity();
CRp.drawCachedElement = function( context, ele, pxRatio, extent, lvl, requestHighQuality ){
let r = this;
let { eleTxrCache, lblTxrCache, slbTxrCache, tlbTxrCache } = r.data;
let bb = ele.boundingBox();
let reason = requestHighQuality === true ? eleTxrCache.reasons.highQuality : null;
if( bb.w === 0 || bb.h === 0 || !ele.visible() ){ return; }
if( !extent || math.boundingBoxesIntersect( bb, extent ) ){
let isEdge = ele.isEdge();
let badLine = ele.element()._private.rscratch.badLine;
r.drawElementUnderlay( context, ele );
r.drawCachedElementPortion( context, ele, eleTxrCache, pxRatio, lvl, reason, getZeroRotation, getOpacity );
if( !isEdge || !badLine ){
r.drawCachedElementPortion( context, ele, lblTxrCache, pxRatio, lvl, reason, getLabelRotation, getTextOpacity );
}
if( isEdge && !badLine ){
r.drawCachedElementPortion( context, ele, slbTxrCache, pxRatio, lvl, reason, getSourceLabelRotation, getTextOpacity );
r.drawCachedElementPortion( context, ele, tlbTxrCache, pxRatio, lvl, reason, getTargetLabelRotation, getTextOpacity );
}
r.drawElementOverlay( context, ele );
}
};
CRp.drawElements = function( context, eles ){
let r = this;
for( let i = 0; i < eles.length; i++ ){
let ele = eles[ i ];
r.drawElement( context, ele );
}
};
CRp.drawCachedElements = function( context, eles, pxRatio, extent ){
let r = this;
for( let i = 0; i < eles.length; i++ ){
let ele = eles[ i ];
r.drawCachedElement( context, ele, pxRatio, extent );
}
};
CRp.drawCachedNodes = function( context, eles, pxRatio, extent ){
let r = this;
for( let i = 0; i < eles.length; i++ ){
let ele = eles[ i ];
if( !ele.isNode() ){ continue; }
r.drawCachedElement( context, ele, pxRatio, extent );
}
};
CRp.drawLayeredElements = function( context, eles, pxRatio, extent ){
let r = this;
let layers = r.data.lyrTxrCache.getLayers( eles, pxRatio );
if( layers ){
for( let i = 0; i < layers.length; i++ ){
let layer = layers[i];
let bb = layer.bb;
if( bb.w === 0 || bb.h === 0 ){ continue; }
context.drawImage( layer.canvas, bb.x1, bb.y1, bb.w, bb.h );
}
} else { // fall back on plain caching if no layers
r.drawCachedElements( context, eles, pxRatio, extent );
}
};
if( process.env.NODE_ENV !== 'production' ){
CRp.drawDebugPoints = function( context, eles ){
let draw = function( x, y, color ){
context.fillStyle = color;
context.fillRect( x - 1, y - 1, 3, 3 );
};
for( let i = 0; i < eles.length; i++ ){
let ele = eles[i];
let rs = ele._private.rscratch;
if( ele.isNode() ){
let p = ele.position();
draw( rs.labelX, rs.labelY, 'red' );
draw( p.x, p.y, 'magenta' );
} else {
let pts = rs.allpts;
for( let j = 0; j + 1 < pts.length; j += 2 ){
let x = pts[ j ];
let y = pts[ j + 1 ];
draw( x, y, 'cyan' );
}
draw( rs.midX, rs.midY, 'yellow' );
}
}
};
}
export default CRp;