浏览代码

Gauge: Better handling of gauge repeat title (#16886)

* Gauge: began looking at gauge title

* Gauge: title improvements

* Minor progres

* Gauge: title improvements, still needs more tweaking

* Gauge: title is starting to work ok

* Use selectThemeVariant

* Remove unused type
Torkel Ödegaard 6 年之前
父节点
当前提交
575fe7ad5a
共有 2 个文件被更改,包括 65 次插入21 次删除
  1. 61 20
      packages/grafana-ui/src/components/Gauge/Gauge.tsx
  2. 4 1
      public/vendor/flot/jquery.flot.gauge.js

+ 61 - 20
packages/grafana-ui/src/components/Gauge/Gauge.tsx

@@ -1,8 +1,8 @@
 import React, { PureComponent } from 'react';
 import $ from 'jquery';
-import { css } from 'emotion';
 import { getColorFromHexRgbOrName } from '../../utils';
-import { DisplayValue, Threshold, GrafanaThemeType, Themeable } from '../../types';
+import { DisplayValue, Threshold, Themeable } from '../../types';
+import { selectThemeVariant } from '../../themes';
 
 export interface Props extends Themeable {
   height: number;
@@ -64,13 +64,21 @@ export class Gauge extends PureComponent<Props> {
   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 autoProps = calculateGaugeAutoProps(width, height, value.title);
+    const dimension = Math.min(width, autoProps.gaugeHeight);
+
+    const backgroundColor = selectThemeVariant(
+      {
+        dark: theme.colors.dark3,
+        light: '#e6e6e6',
+      },
+      theme.type
+    );
 
     const gaugeWidthReduceRatio = showThresholdLabels ? 1.5 : 1;
-    const gaugeWidth = Math.min(dimension / 6, 60) / gaugeWidthReduceRatio;
+    const gaugeWidth = Math.min(dimension / 6, 40) / gaugeWidthReduceRatio;
     const thresholdMarkersWidth = gaugeWidth / 5;
-    const fontSize = Math.min(dimension / 5, 100) * (value.text !== null ? this.getFontScale(value.text.length) : 1);
+    const fontSize = Math.min(dimension / 5.5, 100) * (value.text !== null ? this.getFontScale(value.text.length) : 1);
     const thresholdLabelFontSize = fontSize / 2.5;
 
     const options: any = {
@@ -86,7 +94,7 @@ export class Gauge extends PureComponent<Props> {
           },
           frame: { show: false },
           label: { show: false },
-          layout: { margin: 0, thresholdWidth: 0 },
+          layout: { margin: 0, thresholdWidth: 0, vMargin: 0 },
           cell: { border: { width: 0 } },
           threshold: {
             values: this.getFormattedThresholds(),
@@ -103,14 +111,17 @@ export class Gauge extends PureComponent<Props> {
             formatter: () => {
               return value.text;
             },
-            font: { size: fontSize, family: '"Helvetica Neue", Helvetica, Arial, sans-serif' },
+            font: { size: fontSize, family: theme.typography.fontFamily.sansSerif },
           },
           show: true,
         },
       },
     };
 
-    const plotSeries = { data: [[0, value.numeric]] };
+    const plotSeries = {
+      data: [[0, value.numeric]],
+      label: value.title,
+    };
 
     try {
       $.plot(this.canvasElement, [plotSeries], options);
@@ -120,26 +131,36 @@ export class Gauge extends PureComponent<Props> {
   }
 
   render() {
-    const { height, width, value } = this.props;
+    const { width, value, height } = this.props;
+    const autoProps = calculateGaugeAutoProps(width, height, value.title);
 
     return (
       <div
         style={{
-          height: `${Math.min(height, width * 1.3)}px`,
-          width: `${Math.min(width, height * 1.3)}px`,
-          margin: 'auto',
-          marginTop: '-8px',
+          width: '100%',
+          height: '100%',
+          display: 'flex',
+          flexDirection: 'column',
+          justifyContent: 'center',
+          overflow: 'hidden',
         }}
-        ref={element => (this.canvasElement = element)}
       >
-        {value.title && (
+        <div
+          style={{ height: `${autoProps.gaugeHeight}px`, width: '100%' }}
+          ref={element => (this.canvasElement = element)}
+        />
+        {autoProps.showLabel && (
           <div
-            className={css({
+            style={{
               textAlign: 'center',
-              bottom: -8,
+              fontSize: autoProps.titleFontSize,
+              overflow: 'hidden',
+              textOverflow: 'ellipsis',
+              whiteSpace: 'nowrap',
+              position: 'relative',
               width: '100%',
-              position: 'absolute',
-            })}
+              top: '-4px',
+            }}
           >
             {value.title}
           </div>
@@ -148,3 +169,23 @@ export class Gauge extends PureComponent<Props> {
     );
   }
 }
+
+interface GaugeAutoProps {
+  titleFontSize: number;
+  gaugeHeight: number;
+  showLabel: boolean;
+}
+
+function calculateGaugeAutoProps(width: number, height: number, title: string | undefined): GaugeAutoProps {
+  const showLabel = title !== null && title !== undefined;
+  const titleFontSize = Math.min((width * 0.15) / 1.5, 20); // 20% of height * line-height, max 40px
+  const titleHeight = titleFontSize * 1.5;
+  const availableHeight = showLabel ? height - titleHeight : height;
+  const gaugeHeight = Math.min(availableHeight * 0.7, width);
+
+  return {
+    showLabel,
+    gaugeHeight,
+    titleFontSize,
+  };
+}

+ 4 - 1
public/vendor/flot/jquery.flot.gauge.js

@@ -594,6 +594,8 @@
 
             span.css("position", "absolute");
             span.css("top", y + "px");
+            span.css("white-space", "nowrap");
+
             if (textOptions.font.size) {
               span.css("font-size", textOptions.font.size + "px");
             }
@@ -935,7 +937,7 @@
                         }
                     },
                     values: [
-                      
+
                     ]
                 }
             }
@@ -951,3 +953,4 @@
     });
 
 })(jQuery);
+