| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136 |
- import React, { PureComponent } from 'react';
- import $ from 'jquery';
- import { getColorFromHexRgbOrName } from '../../utils';
- import { DisplayValue, Threshold, GrafanaThemeType, Themeable } from '../../types';
- export interface Props extends Themeable {
- height: number;
- maxValue: number;
- minValue: number;
- thresholds: Threshold[];
- showThresholdMarkers: boolean;
- showThresholdLabels: boolean;
- width: number;
- value: DisplayValue;
- }
- const FONT_SCALE = 1;
- export class Gauge extends PureComponent<Props> {
- canvasElement: any;
- static defaultProps: Partial<Props> = {
- maxValue: 100,
- minValue: 0,
- showThresholdMarkers: true,
- showThresholdLabels: false,
- thresholds: [],
- };
- componentDidMount() {
- this.draw();
- }
- componentDidUpdate() {
- this.draw();
- }
- getFormattedThresholds() {
- const { maxValue, minValue, thresholds, theme } = this.props;
- const lastThreshold = thresholds[thresholds.length - 1];
- return [
- ...thresholds.map(threshold => {
- if (threshold.index === 0) {
- return { value: minValue, color: getColorFromHexRgbOrName(threshold.color, theme.type) };
- }
- const previousThreshold = thresholds[threshold.index - 1];
- return { value: threshold.value, color: getColorFromHexRgbOrName(previousThreshold.color, theme.type) };
- }),
- { value: maxValue, color: getColorFromHexRgbOrName(lastThreshold.color, theme.type) },
- ];
- }
- getFontScale(length: number): number {
- if (length > 12) {
- return FONT_SCALE - (length * 5) / 110;
- }
- return FONT_SCALE - (length * 5) / 100;
- }
- draw() {
- const { maxValue, minValue, showThresholdLabels, showThresholdMarkers, width, height, theme, value } = this.props;
- const dimension = Math.min(width, height * 1.3);
- const backgroundColor = theme.type === GrafanaThemeType.Light ? 'rgb(230,230,230)' : theme.colors.dark3;
- const gaugeWidthReduceRatio = showThresholdLabels ? 1.5 : 1;
- const gaugeWidth = Math.min(dimension / 6, 60) / gaugeWidthReduceRatio;
- const thresholdMarkersWidth = gaugeWidth / 5;
- const fontSize = Math.min(dimension / 5, 100) * (value.text !== null ? this.getFontScale(value.text.length) : 1);
- const thresholdLabelFontSize = fontSize / 2.5;
- const options: any = {
- series: {
- gauges: {
- gauge: {
- min: minValue,
- max: maxValue,
- background: { color: backgroundColor },
- border: { color: null },
- shadow: { show: false },
- width: gaugeWidth,
- },
- frame: { show: false },
- label: { show: false },
- layout: { margin: 0, thresholdWidth: 0 },
- cell: { border: { width: 0 } },
- threshold: {
- values: this.getFormattedThresholds(),
- label: {
- show: showThresholdLabels,
- margin: thresholdMarkersWidth + 1,
- font: { size: thresholdLabelFontSize },
- },
- show: showThresholdMarkers,
- width: thresholdMarkersWidth,
- },
- value: {
- color: value.color,
- formatter: () => {
- return value.text;
- },
- font: { size: fontSize, family: '"Helvetica Neue", Helvetica, Arial, sans-serif' },
- },
- show: true,
- },
- },
- };
- const plotSeries = { data: [[0, value.numeric]] };
- try {
- $.plot(this.canvasElement, [plotSeries], options);
- } catch (err) {
- console.log('Gauge rendering error', err, options, value);
- }
- }
- render() {
- const { height, width } = this.props;
- return (
- <div
- style={{
- height: `${Math.min(height, width * 1.3)}px`,
- width: `${Math.min(width, height * 1.3)}px`,
- top: '10px',
- margin: 'auto',
- }}
- ref={element => (this.canvasElement = element)}
- />
- );
- }
- }
|