Button for enable or disable zoom and pan utils using chartjs, react-chartjs-2 and chartjs-plugin-zoom

69 views Asked by At

Im trying to create a button for enable or disable zoom and pan options in my chart.

Part of my code

import { useRef, useState } from "react"
import { Line } from "react-chartjs-2"
import "chartjs-adapter-date-fns"
import zoom from "chartjs-plugin-zoom"
import { DataPicker } from "./index.js"
import { Alert, Button } from "react-bootstrap"
import { useApiSlice } from "../../../hooks/useApiSlice.js"
import { useTranslation } from "react-i18next"

import {
  Chart as ChartJS,
  LineElement,
  TimeScale,
  LinearScale,
  PointElement,
  Tooltip,
  Title,
  Legend,
} from "chart.js"

ChartJS.register(
  LineElement,
  PointElement,
  TimeScale,
  LinearScale,
  Tooltip,
  Title,
  Legend,
  zoom
)

export const Graph = () => {
  const [dataset, setDataset] = useState("1")
  
  
  // For zoom and pan utils
  const [utils, setUtils] = useState(false)
  const chartRef = useRef(null)
  
  
  
  const { logs, activeStation } = useApiSlice()
  const { name } = activeStation
  const { t } = useTranslation();

  if (logs.length === 0) {
    return (
      <Alert variant="secondary w-75 text-center" className="mt-2">
        {t("Station.logsError")}
      </Alert>
    )
  }

  const start_date = logs[logs.length - 1].created
  const end_date = logs[0].created
  const labels = logs.map((d) => d.created)

  const dataGraph = (value) => {
    setDataset(value)
  }

  let values = logs.map((d) => d.stage)
  let label = "Stage"

  switch (dataset) {
    case "1":
      if (name === "CANADA"){
        values = logs.map((d) => d.stage_dl)
      }else{
        values = logs.map((d) => d.stage)
      }
      label = "Stage"
      break

    case "2":
      values = logs.map((d) => d.voltage)
      label = "Voltage"
      break

    case "3":
      values = logs.map((d) => d.disk_usage)
      label = "Disk Usage"
      break

    case "4":
      values = logs.map((d) => d.discharge)
      label = "Discharge"
      break
  }

  const data = {
    labels,
    datasets: [
      {
        label,
        data: values,
        borderColor: "rgb(255, 99, 132)",
        backgroundColor: "rgba(255, 99, 132, 0.5)",
        borderWidth: "2",
        pointRadius: 5,
        z: 1,
      },
    ],
  }

  const options = {
    maintainAspectRatio: false,
    
    plugins: {
      zoom: {
        pan: {
          enabled: utils,
          mode: "xy",
        },
        zoom: {
          drag: {
            enabled: utils,
            modifierKey: "ctrl",
          },
          mode: "xy",
          wheel: {
            enabled: utils,
          },
          pinch: {
            enabled: utils,
          },
          limits: {
            x: {
              min: "original",
              max: "original",
            },
            y: {
              min: "original",
              max: "original",
            },
          },
        },
      },
    },

    scales: {
      x: {
        offset: true,
        type: "time",
        min: start_date,
        max: end_date,
        border: {
          width: 2,
          color: "black",
        },
        ticks: {
          maxTicksLimit: 5,
        },
      },
      y: {
        // min: 0,
        // max: 1,
        border: {
          width: 2,
          color: "black",
          z: 0,
        },
        ticks: {
          stepSize: 0.5,
        },
      },
    },
  }



  const handleResetZoom = () => {
    console.log(chartRef)
    if (chartRef && chartRef.current) {
      chartRef.current.resetZoom()
    }
  }

  const handleZoomUtils = (event) => {
    setUtils(!utils)
    chartRef.current.update()
  }

  return (
    <div className="graph-container">
      <h5 className="align-self-center graph-title"> {t("Station.graph")} </h5>
      <DataPicker dataGraph={dataGraph}></DataPicker>
      <div className="graph">
        <Line data={data} options={options} ref={chartRef}>
        </Line>
      </div>
      <div className="d-flex justify-content-center">
        <Button
          onClick={handleResetZoom}
          className="align-self-center resize-button me-3"
          size="sm"
          variant="dark"
        >
          Reset Zoom
        </Button>
        <Button 
        onClick={handleZoomUtils}
        size="sm"
        variant={utils ? "success" : "dark"}
        >
          Zoom
        </Button>
      </div>
    </div>
  )
}

and the page looks like this enter image description here

The main problem here is when click the button (called zoom), zoom options works but pan don't work in desktop view.

In the cell phone view this is worse, because nothing works, and basically I am creating this button to solve the conflicts with the scroll bar that is seen on the right of the graph.

Reset Zoom button works so fine!

Anyway, I hope someone from this community can help me. And so sorry for my english! I'm studying for improve this

0

There are 0 answers