leeoniya / uPlot

📈 A small, fast chart for time series, lines, areas, ohlc & bars
MIT License
8.48k stars 370 forks source link

How to have scrollable and smaller font in legends? #909

Closed selvavm closed 4 months ago

selvavm commented 4 months ago

Hi,

I came to know recently while digging in Grafana source code about uplot and it is blazing fast. Thanks for the contribution.

I am creating a new grafana panel similar to XYChart but with sync enabled. I was not sure how to override the original XYChart so I am using uplot-react

Below is my options,

let series = [
    {
      label: "t",
      value: (u: any, v: any) => v == null ? "-" : v+"s",
    },
    {
      label: "CPU 1",
      values: (u, sidx, idx) => {
        if (idx==null)
          return {Sname: 'To be filled dynamically', Min: '--', Max: '--', Mean: '--', Std_dev: '--', Value: '--'};
        return {Sname: 'To be filled dynamically', Min: idx, Max: idx, Mean: idx, Std_dev: idx, Value: idx};
      },
      stroke: "red",
    },
    {
      label: "CPU 2",
      values: (u, sidx, idx) => {
        if (idx==null)
          return {Sname: 'To be filled dynamically', Min: '--', Max: '--', Mean: '--', Std_dev: '--', Value: '--'};
        return {Sname: 'To be filled dynamically', Min: idx, Max: idx, Mean: idx, Std_dev: idx, Value: idx};
      },
      stroke: "blue",
    },
  ]
  const brushOpts = {
    width: width,
    height: height*0.7,
    legend: {
        show: true
    },
    cursor: {
        y: false,
        points: {
            show: false,
        },
        drag: {
            setScale: false,
            x: true, 
            y: false,
        },
        sync: {
            key: 'moo',
            setSeries: true,
        },
    },
    scales: {
        x: {
            time: false,
        },
    },
    series: series,
    hooks: {
      init: [
        (u: any) => {
          u.over.ondblclick = e => {
            console.log("Fetching data for full range");

            u.setData(data);
          }
        }
      ],
      setSelect: [
        (u: any) => {
          if (u.select.width > 0) {
            let min = u.posToVal(u.select.left, 'x');
            let max = u.posToVal(u.select.left + u.select.width, 'x');

            // zoom to selection
            u.setScale('x', {min, max});

            // reset selection
            u.setSelect({width: 0, height: 0}, false);
          }
        }
      ],
    }
  }

I wanted to have tooltip similar to Grafana so I tried the cursor-tooltip but it does not show the pop-up.

Anyway, I settled with showing the legends as a scrollable table as seen in Grafana. How can I acheive it? Also, I want the font to be smaller (Grafana style) such that there is more space for the chart. How can I achieve this?

uplot_custom_panel

leeoniya commented 4 months ago

hey @selvavm ,

grafana does not use uPlot's legend, it creates its own from the dataframe fields and is rendered by the panel code into VizLayout container.

you may want to do the same thing if you want similar behavior and styling. example:

https://github.com/grafana/grafana/blob/a5957ba5557e92940db7f19ea5fe77b26ee7c75b/public/app/plugins/panel/histogram/Histogram.tsx#L348-L354

you could instead try to figure out how to portal uPlot's legend into the VizLayout legend area by using the uPlot's legend.mount callback option and moving the uPlot legend into that portal. u can also restyle uPlot's legend using CSS. all the elements are class-tagged.

https://github.com/leeoniya/uPlot/blob/88c3d2baa1d0cbeaff5dca9e2094b48591d0fd84/dist/uPlot.d.ts#L285-L286