UNPKG

infect-frontend

Version:
88 lines (77 loc) 3.54 kB
import React from 'react'; import { observer } from 'mobx-react'; import { computed, observable, action, when } from 'mobx'; import getVisibilityClassModifier from '../../helpers/getVisibilityClassModifier'; @observer export default class AntibioticLabel extends React.Component { constructor() { super(); this._wasVisible = true; } componentDidMount() { this._setupResizeListener(); } _setTextElement = (el) => { if (!el) return; this._textElement = el; this._setDimensions(); } /** * Set height of view on model; needed as height is variable (because uf the 45° angle) * and space available for the matrix is calculated depending on the space that the highest * label takes up. */ _setDimensions() { if (!this._textElement) return; const bounds = this._textElement.getBBox(); // Element has a rotation of -45deg. Those are not respected in getBBox. // When rotated by 45°, take sin(45°) * width plus the triangle below the baseline // that's a isosceles triangle. // Angle is more than 45°, use PI/3. const height = Math.ceil(bounds.width * Math.sin(Math.PI / 3) + Math.sqrt(Math.pow(bounds.height, 2)/2)); this.props.antibiotic.setDimensions(height, height); } @computed get transformation() { const rotation = 'rotate(-75)'; // Before textElement is ready, hight of antibiotics (and therefore the transformation) cannot be known. if (!this.props.matrix.greatestSubstanceClassLabelHeight) return 'translate(0, 0) ' + rotation; if (!this.props.antibiotic.visible) return `translate(${ this._previousPosition.left || 0}, ${ this._previousPosition.top || 0 }) ${ rotation }`; // We must add some of the height (60°/90°) as we rotated the label which positions it more to the left const pos = this.props.matrix.xPositions.get(this.props.antibiotic); const left = (pos ? pos.left : 0) + this._textElement.getBBox().height * 1.2; const substanceClassModifier = (this.props.matrix.maxAmountOfSubstanceClassHierarchies - this.props.antibiotic.antibiotic.getSubstanceClasses().length); const top = (this.props.matrix.antibioticLabelRowHeight || 0) + substanceClassModifier * (this.props.matrix.greatestSubstanceClassLabelHeight || 0); this._previousPosition = { left, top }; return `translate(${ left }, ${ top }) ${ rotation }`; } @computed get classModifier() { // We must also be watching transitions: If not, we only watch visible – which stays the // same when modifier should change from -was-hidden-is-visible to -was-visible-is-visible // and therefore won't call an update. this.transformation; const modifier = getVisibilityClassModifier(this.props.antibiotic.visible, this._wasVisible); this._wasVisible = this.props.antibiotic.visible; return modifier; } _setupResizeListener() { window.addEventListener('resize', () => this._setDimensions()); } @computed get highlightClass() { const activeResistance = this.props.matrix.activeResistance; if (!activeResistance) return ''; return this.props.antibiotic.antibiotic === activeResistance.resistance.antibiotic ? 'highlight' : ''; } render() { return ( <g transform={ this.transformation } style={ { visibility: this.props.matrix.defaultRadius ? 'visible' : 'hidden' } } className={ 'resistanceMatrix__antibioticLabel ' + this.classModifier }> <text dy="-9" ref={ this._setTextElement } className={ 'resistanceMatrix__antibioticLabelText ' + this.highlightClass }> {this.props.antibiotic.antibiotic.name} </text> </g> ); } }