infect-frontend
Version:
infect fronend
89 lines (75 loc) • 3.17 kB
JSX
import React from 'react';
import { observer } from 'mobx-react';
import { computed, observable, action } from 'mobx';
import getVisibilityClassModifier from '../../helpers/getVisibilityClassModifier';
export default class BacteriumLabel extends React.Component {
constructor() {
super();
this._wasVisible = true;
}
componentDidMount() {
this._setupResizeWatcher();
}
get visible() {
// Don't display bacterium when we are still measuring its width
return this.props.matrix.defaultRadius !== undefined && this.props.bacterium.visible;
}
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.visible, this._wasVisible);
this._wasVisible = this.visible;
return modifier;
}
_getPreviousPosition() {
return `translate(${ (this._previousPosition && this._previousPosition.left) || 0 },
${ (this._previousPosition && this._previousPosition.top) || 0 })`;
}
get transformation() {
// We can only position elements correctly when we know defaultRadius. Until then,
// hide the labels
if (!this.props.matrix.defaultRadius) return this._getPreviousPosition();
if (!this.visible) return this._getPreviousPosition();
// Top: top of bacterium plus radius (baseline corresponds to the center of the circles)
const pos = this.props.matrix.yPositions.get(this.props.bacterium);
// If pos is not available (because bacterium is hidden) return previous top – we don't want to move
// labels if not necessary (as they're invisible; performance)
const top = pos ? pos.top : this._previousTop;
this._previousPosition = { left: 0, top: top };
return `translate(0, ${ top })`;
}
_setTextElement(element) {
if (!element) return;
this._textElement = element;
this._setWidth();
}
_setWidth() {
this.props.bacterium.setWidth(this._textElement.getBBox().width);
}
_setupResizeWatcher() {
window.addEventListener('resize', () => this._setWidth());
}
get highlightClass() {
const activeResistance = this.props.matrix.activeResistance;
if (!activeResistance) return '';
return this.props.bacterium.bacterium === activeResistance.resistance.bacterium ? 'highlight' : '';
}
render() {
return (
<g transform={ this.transformation }
className={ 'resistanceMatrix__bacteriumLabel ' + this.classModifier }>
/* rect is only used to give the g a height so that text can be aligned middle */
/* We have to place label to the right (x) in order for text-anchor to work. */
<text x={this.props.matrix.defaultRadius} y={this.props.matrix.defaultRadius}
ref={(el) => this._setTextElement(el)} x={this.props.matrix.bacteriumLabelColumnWidth}
className={ 'resistanceMatrix__bacteriumLabelText ' + this.highlightClass }
dominantBaseline="middle" y={this.props.matrix.defaultRadius}>
{this.props.bacterium.bacterium.name}
</text>
</g>
);
}
}