ChartJS 在React图表中缩放和平移js-2

xkftehaa  于 2022-11-07  发布在  Chart.js
关注(0)|答案(5)|浏览(250)

我最近使用react-chartjs-2(https://github.com/jerairrest/react-chartjs-2)实现了图表显示
我想启用缩放和平移功能,以便在触摸屏上更加方便用户使用。为了实现此功能,我安装了 react-hammerjschartjs-plugin-zoom

import {Chart, Line} from 'react-chartjs-2';
import Hammer from 'react-hammerjs';
import zoom from 'chartjs-plugin-zoom'

我注册了插件

componentWillMount(){
    Chart.plugins.register(zoom)
}

render方法如下所示:

render(){
    return <Line data={data} options={options} />
}

平移和缩放选项:

pan:{
    enabled=true,
    mode:'x'
},
zoom:{
    enabled:true,
    drag:true,
    mode:'xy'
}

我想这是正确的方法来实现。不幸的是,上面的实现没有工作。我将非常感激,如果你们中的一些人已经实现了缩放和平移使用react-chartjs-2插件,请分享如果你是如何实现这些功能。或者你可以指出我的代码上面的问题。

nx7onnlm

nx7onnlm1#

要将缩放与平移功能添加到基于react-chartjs-2得图表组件中,您可以执行以下步骤:

步骤1:您需要安装chartjs-plugin-zoom

$ npm install chartjs-plugin-zoom

步骤2:在图表组件中导入chartjs-plugin-zoom

import 'chartjs-plugin-zoom';

步骤3:在ChartJS组件选项中启用缩放与平移

zoom: {
          enabled: true,
          mode: 'x',
        },
        pan: {
          enabled: true,
          mode: 'x',
        },

就是这样。现在您的图表组件应该如下所示:

import React from 'react';
import { Line } from 'react-chartjs-2';
import 'chartjs-plugin-zoom';

export default function TimelineChart({ dailyDataSets }) {
  const lineChart = dailyDataSets[0] ? (
    <Line
      data={{
        labels: dailyDataSets.map(({ date }) => date),
        datasets: [
          {
            data: dailyDataSets.map((data) => data.attr1),
            label: 'First data set',
            borderColor: 'red',
            fill: true,
          },
          {
            data: dailyDataSets.map((data) => data.attr2),
            label: 'Second data set',
            borderColor: 'green',
            fill: true,
          },
        ],
      }}
      options={{
        title: { display: true, text: 'My Chart' },
        zoom: {
          enabled: true,
          mode: 'x',
        },
        pan: {
          enabled: true,
          mode: 'x',
        },
      }}
    />
  ) : null;

  return <div>{lineChart}</div>;
}

备注:
1.您不必显式安装hammerjs,因为安装chartjs-plugin-zoom时会自动将其包含为依赖项,请参见以下内容:

$ npm ls
...
├─┬ chartjs-plugin-zoom@0.7.7
│ └── hammerjs@2.0.8
...

1.例如,一种缩放方法(至少对于Mac)是,您可以将鼠标指针移动到图表区域中,然后向下或向上滚动鼠标。放大后,您可以在向左或向右拖动的同时保持鼠标单击。

wkftcu5l

wkftcu5l2#

enabled属性的pan对象下存在语法错误。

您错误地将=而不是:
替换为:

pan:{
  enabled=true,
  ...
},

具有:

pan:{
  enabled:true,
  ...
},

并且也正如@君斌所建议的:
安装hammerjs为:

npm install hammerjs --save

在您的组件中,将其导入为:

import Hammer from "hammerjs";
v440hwme

v440hwme3#

您导入了错误的锤子,它应该来自“hammerjs”;

o4tp2gmn

o4tp2gmn4#

您需要添加import 'chartjs-plugin-zoom';,然后将缩放选项添加到options.plugins.zoom中,例如:

const options = {
  plugins: {
    zoom: {
      pan: {
        enabled: true,
        mode: 'x',
      },
      zoom: {
        enabled: true,
        drag: true,
        mode: 'xy'
      }
    }
  }
};
8cdiaqws

8cdiaqws5#

我尝试在NextJS项目中这样做。但是到目前为止还没有成功。我使用的是一个时间序列图,其中包含德语和英语的日期-fns/locale,并且不断收到以下错误:

Cannot convert a Symbol value to a string
TypeError: Cannot convert a Symbol value to a string at TypedRegistry.register (webpack-internal:///./node_modules/chart.js/dist/chart.esm.js:4802:50) at Registry._exec (webpack-internal:///./node_modules/chart.js/dist/chart.esm.js:4927:21) at eval (webpack-internal:///./node_modules/chart.js/dist/chart.esm.js:4919:16) at each (webpack-internal:///./node_modules/chart.js/dist/chunks/helpers.segment.js:233:10) at eval (webpack-internal:///./node_modules/chart.js/dist/chart.esm.js:4917:70) at Array.forEach (<anonymous>) at Registry._each (webpack-internal:///./node_modules/chart.js/dist/chart.esm.js:4912:15) at Registry.add (webpack-internal:///./node_modules/chart.js/dist/chart.esm.js:4870:10) at Function.value [as register] (webpack-internal:///./node_modules/chart.js/dist/chart.esm.js:6192:16) at eval (webpack-internal:///./components/Charts/PortfolioPriceLineDual.jsx:39:45) at Module../components/Charts/PortfolioPriceLineDual.jsx (https://dev.domain.de/_next/static/chunks/components_Charts_PortfolioPriceLineDual_jsx.js:7758:1) at Module.options.factory (https://dev.domain.de/_next/static/chunks/webpack.js?ts=1653499440538:655:31) at __webpack_require__ (https://dev.domain.de/_next/static/chunks/webpack.js?ts=1653499440538:37:33) at Function.fn (https://dev.domain.de/_next/static/chunks/webpack.js?ts=1653499440538:310:21)

我的组件:

import { Line } from 'react-chartjs-2'

import 'chartjs-adapter-date-fns'
import { de, enGB, ja } from 'date-fns/locale'

import dynamic from 'next/dynamic'
import 'chart.js/auto'
import { useRouter } from 'next/router'
import { Chart } from 'chart.js'

// import zoomPlugin from 'chartjs-plugin-zoom';
const zoomPlugin = dynamic(() => import('chartjs-plugin-zoom'), {
  ssr: false,
})
Chart.register(zoomPlugin);

const PortfolioPriceLineDual = ({
  title,
  data,
  unit,
  axesOptions,
  showLegend = true,
}) => {
  const totalDuration = 5000
  const delayBetweenPoints = totalDuration / data.datasets[0].data.length
  // const animation =
  const { locale } = useRouter()
  let format
  switch (locale) {
    case 'de-DE':
      format = de
      break
    case 'en-US':
      format = enGB

      break
    case 'ja-JP':
      format = ja

      break
    default:
      break
  }

  return (
    <Line
      data={data}
      options={{
        responsive: true,
        // maintainAspectRatio: true,
        // aspectRatio: 16 / 9,
        resizeDelay: 5,
        animation: {
          x: {
            type: 'number',
            easing: 'linear',
            duration: delayBetweenPoints,
            from: NaN, // the point is initially skipped
            delay: (ctx) => {
              if (ctx.type !== 'data' || ctx.xStarted) {
                return 0
              }
              ctx.xStarted = true
              return ctx.index * delayBetweenPoints
            },
          },
          y: {
            type: 'number',
            easing: 'linear',
            duration: delayBetweenPoints,
            from: (ctx) => {
              return ctx.index === 0
                ? ctx.chart.scales.y.getPixelForValue(100)
                : ctx.chart
                    .getDatasetMeta(ctx.datasetIndex)
                    .data[ctx.index - 1].getProps(['y'], true).y
            },
            delay: (ctx) => {
              if (ctx.type !== 'data' || ctx.yStarted) {
                return 0
              }
              ctx.yStarted = true
              return ctx.index * delayBetweenPoints
            },
          },
          y1: {
            type: 'number',
            easing: 'linear',
            duration: delayBetweenPoints,
            from: (ctx) => {
              return ctx.index === 0
                ? ctx.chart.scales.y.getPixelForValue(100)
                : ctx.chart
                    .getDatasetMeta(ctx.datasetIndex)
                    .data[ctx.index - 1].getProps(['y'], true).y
            },
            delay: (ctx) => {
              if (ctx.type !== 'data' || ctx.yStarted) {
                return 0
              }
              ctx.yStarted = true
              return ctx.index * delayBetweenPoints
            },
          },
        },
        interaction: {
          mode: 'index',
          intersect: false,
        },
        scales: {
          x: {
            type: 'time',

            time: {
              unit: 'year',
              displayFormats: {
                quarter: 'yyyy',
              },
              tooltipFormat: 'MMMM yyyy',
            },
            adapters: {
              date: {
                locale: format,
              },
            },
            ticks: {
              align: 'start',
              color: '#122a42',
              font: {
                size: 14,
                weight: 'bold',
              },
            },
            grid: {
              display: true,
              drawBorder: false,
              drawOnChartArea: true,
              drawTicks: true,
            },
          },
          y: {
            type: 'logarithmic',

            grid: {
              display: true,
              drawBorder: false,
              drawOnChartArea: true,
              drawTicks: true,
            },
            ticks: {
              color: '#122a42',
              align: 'end',
              font: {
                size: 10,
                weight: 'normal',
              },
              // Include a dollar sign in the ticks
              // stepSize: 1000,
              callback: function (value) {
                // callback: function (value, index, ticks) {
                return `${new Intl.NumberFormat(locale, axesOptions).format(
                  value
                )}`
              },
            },
          },
          y1: {
            type: 'linear',
            display: true,
            position: 'right',

            // grid line settings
            grid: {
              drawOnChartArea: false, // only want the grid lines for one axis to show up
            },
            ticks: {
              color: '#122a42',
              align: 'end',
              font: {
                size: 10,
                weight: 'normal',
              },
              // Include a dollar sign in the ticks
              // stepSize: 1000,
              callback: function (value) {
                // callback: function (value, index, ticks) {
                return `${new Intl.NumberFormat(locale, axesOptions).format(
                  value
                )}`
              },
            },
          },
        },
        zoom: {
          enabled: true,
          mode: 'x',
        },
        pan: {
          enabled: true,
          mode: 'x',
        },
        plugins: {
          zoom: {
            enabled: true,
            mode: 'x',
          },
          pan: {
            enabled: true,
            mode: 'x',
          },
          // zoom: {
          //   zoom: {
          //     wheel: {
          //       enabled: true,
          //     },
          //     pinch: {
          //       enabled: true,
          //     },
          //     mode: 'x',
          //   },
          // },
          title: {
            display: true,
            color: '#151C30',
            font: {
              size: 26,
              weight: 'bold',
              style: 'normal',
            },
            padding: {
              bottom: 10,
            },
            text: `${title}`,
          },
          tooltip: {
            enabled: true,
            backgroundColor: '#122a42',
            itemSort: function (a, b) {
              return b.raw - a.raw
            },
            callbacks: {
              label: function (context) {
                let label = context.dataset.label || ''

                if (label) {
                  label += ': '
                }
                if (context.parsed.y !== null) {
                  label += `${new Intl.NumberFormat(locale, axesOptions).format(
                    context.parsed.y
                  )} ${unit}`
                }
                return label
              },
            },
          },
          legend: {
            position: 'bottom',
            labels: {
              // This more specific font property overrides the global property
              color: '#151C30',
              font: {
                size: 12,
                weight: 'light',
              },
            },
          },
        },
      }}
    />
  )
}

export default PortfolioPriceLineDual

相关问题