UNPKG

@gmod/jbrowse

Version:

JBrowse - client-side genome browser

123 lines (111 loc) 4.14 kB
define( [ 'dojo/_base/declare', 'dojo/_base/lang', 'JBrowse/View/_FeatureDescriptionMixin' ], function( declare, lang, FeatureDescriptionMixin ) { var fontMeasurementsCache = {}; return declare( FeatureDescriptionMixin, { /** * Estimate the height and width, in pixels, of the given * feature's label text, and trim it if necessary to fit within * the track's maxFeatureGlyphExpansion limit. */ makeFeatureLabel: function( feature, fRect ) { var text = this.getFeatureLabel( feature ); if( ! text ) return null; text = ''+text; var font = this.getStyle( feature, 'textFont' ); var l = fRect ? this.makeBottomOrTopLabel( text, font, fRect ) : this.makePopupLabel( text, font ); l.fill = this.getStyle( feature, 'textColor' ); return l; }, /** * Estimate the height and width, in pixels, of the given * feature's description text, and trim it if necessary to fit * within the track's maxFeatureGlyphExpansion limit. */ makeFeatureDescriptionLabel: function( feature, fRect ) { var text = this.getFeatureDescription( feature ); if( ! text ) return null; text = ''+text; var font = this.getStyle( feature, 'text2Font' ); var l = fRect ? this.makeBottomOrTopLabel( text, font, fRect ) : this.makePopupLabel( text, font ); l.fill = this.getStyle( feature, 'text2Color' ); return l; }, /** * Makes a label that sits on the left or right side of a feature, * respecting maxFeatureGlyphExpansion. */ makeSideLabel: function( text, font, fRect ) { if( ! text ) return null; var dims = this.measureFont( font ); var excessCharacters = Math.round(( text.length * dims.w - this.track.getConf('maxFeatureGlyphExpansion') ) / dims.w ); if( excessCharacters > 0 ) text = text.slice( 0, text.length - excessCharacters - 1 ) + '…'; return { text: text, font: font, baseline: 'middle', w: dims.w * text.length, h: dims.h }; }, /** * Makes a label that lays across the bottom edge of a feature, * respecting maxFeatureGlyphExpansion. */ makeBottomOrTopLabel: function( text, font, fRect ) { if( ! text ) return null; var dims = this.measureFont( font ); var excessCharacters = Math.round(( text.length * dims.w - fRect.w - this.track.getConf('maxFeatureGlyphExpansion') ) / dims.w ); if( excessCharacters > 0 ) text = text.slice( 0, text.length - excessCharacters - 1 ) + '…'; return { text: text, font: font, baseline: 'bottom', w: dims.w * text.length, h: dims.h }; }, /** * Makes a label that can be put in a popup or tooltip, * not respecting maxFeatureGlyphExpansion or the width of the fRect. */ makePopupLabel: function( text, font ) { if( ! text ) return null; var dims = this.measureFont( font ); return { text: text, font: font, w: dims.w * text.length, h: dims.h } }, /** * Return an object with average `h` and `w` of characters in the * font described by the given string. */ measureFont: function( font ) { return fontMeasurementsCache[ font ] || ( fontMeasurementsCache[font] = function() { var ctx = document.createElement('canvas').getContext('2d'); ctx.font = font; var testString = "MMMMMMMMMMMMXXXXXXXXXX1234567890-.CGCC12345"; var m = ctx.measureText( testString ); return { h: m.height || parseInt( font.match(/(\d+)px/)[1] ), w: m.width / testString.length }; }.call( this )); } }); });