infect-frontend
Version:
infect fronend
88 lines (77 loc) • 3.54 kB
JSX
import React from 'react';
import { observer } from 'mobx-react';
import { computed, observable, action, when } from 'mobx';
import getVisibilityClassModifier from '../../helpers/getVisibilityClassModifier';
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);
}
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 }`;
}
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());
}
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>
);
}
}