۳۰ شهریور ۱۴۰۳

Techboy

اخبار و اطلاعات روز تکنولوژی

نمودارهای مجدد: مقدمه ای بر نمودارهای جاوا اسکریپت

یک کتابخانه نموداری خوب در هنگام افزودن داده های بصری به برنامه های جاوا اسکریپت تفاوت ایجاد می کند. Recharts یکی از بهترین هاست که فقط برای React ساخته شده است.

یک کتابخانه نموداری خوب در هنگام افزودن داده های بصری به برنامه های جاوا اسکریپت تفاوت ایجاد می کند. Recharts یکی از بهترین هاست که فقط برای React ساخته شده است.

اکوسیستم جاوا اسکریپت شامل بسیاری از کتابخانه‌های نمودار است، اما ایجاد یک API نمودار با ویژگی‌های کامل که در استفاده در دنیای واقعی عملکرد خوبی داشته باشد، دشوار است. این مقاله یک معرفی عملی برای یکی از موارد خوب است. Recharts یک تجسم خاص React از D3 است، چارچوبی که به خوبی بررسی شده است. برای آزمایش آن، از داده‌های قیمت و حجم برای ارزهای دیجیتال استفاده می‌کنیم.

پروژه را راه اندازی کنید

برای راه اندازی پروژه خود، از create-react-app استفاده خواهیم کرد. از قبل باید Node/NPM را نصب کرده باشید. پس از انجام، می توانید تایپ کنید: npx create-react-app crypto-charts. پس از اتمام، می توانید به فهرست /crypto-charts بروید و وابستگی مورد نیاز را با این موارد اضافه کنید: npm install recharts.

در مرحله بعد، از fetch برای بارگیری داده‌ها از API CoinGecko استفاده می‌کنیم. و سپس آن را نمایش دهید. ما صفحه‌ای مانند این خواهیم داشت:

react chart fig1

شکل ۱. نمایش ساده داده‌های ارزهای دیجیتال.

برای بارگیری و نمایش داده ها، فقط کد زیر را در فایل src/App.js پروژه قرار دهید و برنامه را با npm start اجرا کنید.


import React, { useState, useEffect } from 'react';

function App() {
  const [cryptoData, setCryptoData] = useState([]);

  useEffect(() => {
    const fetchData = async () => {
      try {
        const response = await fetch(
          `https://api.coingecko.com/api/v3/coins/bitcoin/market_chart?vs_currency=usd&days=30`,
          {
            method: 'GET',
            headers: {
              'Content-Type': 'application/json',
            },
          }
        );

        const data = await response.json();
        setCryptoData(data);
      } catch (error) {
        console.error('Error fetching data:', error);
      }
    };

    fetchData();
  }, []);

  return (
    <div className="App">
      <h1 className="chart-title">Crypto Currency Price Chart</h1>
      <div className="data-container">
        <h2>Price Data</h2>
        <pre>{JSON.stringify(cryptoData, null, 2)}</pre>
      </div>
    </div>
  );
}

export default App;

این کد عمداً بسیار ساده است، بنابراین می توانیم مطمئن شویم که API داده ها را به درستی بارگیری می کند. ما فقط آن را با JSON.stringify() به صفحه نمایش می دهیم. توجه داشته باشید که ما از نقطه پایانی bitcoin استفاده می کنیم.

یک نمودار خطی اضافه کنید

بعد، اجازه دهید داده‌های قیمت را از پاسخ به یک نمودار خطی ساده وصل کنیم، همانطور که در فهرست ۲ نشان داده شده است. من فقط بخش‌هایی از کد را نشان می‌دهم که با فهرست ۱ متفاوت است. 


import React, { useState, useEffect } from 'react';
import { LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, Legend } from 'recharts';

function App() {
  const [cryptoData, setCryptoData] = useState([]);

  useEffect(() => {
    const fetchData = async () => {
      try {
        const response = await fetch(
          `https://api.coingecko.com/api/v3/coins/bitcoin/market_chart?vs_currency=usd&days=30`,
          {
            method: 'GET',
            headers: {
              'Content-Type': 'application/json',
            },
          }
        );

        const data = await response.json();
        setCryptoData(data.prices);
      } catch (error) {
        console.error('Error fetching data:', error);
      }
    };

    fetchData();
  }); // Run effect whenever timeframe changes

  return (
    <div className="App">
      <h1 className="chart-title">Crypto Currency Price Chart</h1>
      {/* LineChart with Recharts */}
      <LineChart width={800} height={400} data={cryptoData}>
        <CartesianGrid stroke="#f5f5f5" />
        <XAxis dataKey="0" tickFormatter={(timestamp) => new Date(timestamp).toLocaleDateString()} />
        <YAxis />
        <Tooltip labelFormatter={(value) => new Date(value).toLocaleDateString()} />
        <Legend verticalAlign="top" height={36} />
        <Line type="monotone" dataKey="1" stroke="#8884d8" dot={false} />
      </LineChart>
    </div>
  );
}

export default App;

به‌روزرسانی‌های کلیدی در اینجا وارد کردن اجزای Recharts، ایجاد قلاب متغیر حالت cryptoData، تعریف نشانه‌گذاری و وصل کردن cryptoData را در آن قرار دهید. فقط در هفت خط نشانه گذاری، ما یک نمودار بسیار زیبا و کاربردی داریم. علاوه بر خود مؤلفه LineChart، که متغیر cryptoData را به عنوان پایه داده مصرف می‌کند، چندین فرزند تودرتو داریم که به تعریف طرح نمودار کمک می‌کنند، از جمله XAxis، YAxis، نکته ابزار، Legend و Line.

مؤلفه‌های XAxis و YAxis به نمودار می‌گویند که چگونه محورها را مدیریت کند. در این مورد، ما قالب‌بندی «تیک‌ها» را با یک قالب‌کننده زمان ساده انجام می‌دهیم، زیرا محور X همان مُهرهای زمانی است. ویژگی dataKey به محور می‌گوید چگونه مقدار آن را که اولین عنصر آرایه است، ۰ پیدا کند. YAxis هیچ خاصیتی ندارد و از پیش‌فرض‌ها استفاده می‌کند. قالب‌کننده Tooltip چیزی است که داده‌هایی را که هنگام حرکت ماوس روی خط مشاهده خواهید کرد، هدایت می‌کند. Legend استایل را برای افسانه و مؤلفه Line استایل را در خود خط تنظیم می کند.

اجرای کد از فهرست ۲ باید به صفحه ای مانند تصویر ۲ منجر شود.

react chart fig2

شکل ۲. افزودن نمودار خطی اصلی

افزودن یک جزء مقیاس زمانی

حالا اجازه دهید قابلیت مقیاس‌بندی تایم فریم را اضافه کنیم. Recharts این کار را با مولفه Brush بسیار آسان می کند. در فهرست ۳، می توانید تغییرات لازم برای این به روز رسانی را مشاهده کنید.


   import { LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, Legend, Brush } from 'recharts';
// … remains the same

        <Line type="monotone" dataKey="1" stroke="#8884d8" dot={false} />
        {/* Add Brush component configuration */}
        <Brush dataKey="0" height={30} stroke="#8884d8" />
      </LineChart>

// … remains the same

برای اینکه نوار لغزنده را برای تنظیم بازه زمانی تنظیم کند، فقط باید مؤلفه Brush را وارد کنیم، سپس آن را با دستورالعمل‌های استایل به نمودار اضافه کنیم. این باعث می شود که اضافه کردن یک ویژگی در غیر این صورت مشکل را بسیار آسان کند. توجه داشته باشید که نه تنها می توانید انتهای تایم فریم را اسلاید کنید، بلکه می توانید نوار تایم فریم را بکشید تا به صورت افقی روی داده ها حرکت کنید. شکل ۳ صفحه به دست آمده است.

react chart fig3

شکل ۳. نوار لغزنده بازه زمانی قابل پیمایش، کشیدن و تغییر اندازه است.

اکنون اجازه دهید یک کنترل ساده برای تغییر محدوده تاریخ‌هایی که از CoinGecko API پایین می‌آوریم، اضافه کنیم، همانطور که در فهرست ۴ نشان داده شده است. این تغییر یک منوی کشویی ساده با گزینه‌های محدوده تاریخ (۱ ماه، ۲ ماه) ارائه می‌کند. ، و غیره.). وقتی محدوده تاریخ را تغییر می دهید، تعداد روزهای نمایش داده شده در نمودار به روز می شود.


 // ...same imports...
function App() {
  const [cryptoData, setCryptoData] = useState([]);
  const [timeframe, setTimeframe] = useState(30); // Default timeframe: 30 days

  useEffect(() => {
    const fetchData = async () => {
      try {
        const response = await fetch(
          `https://api.coingecko.com/api/v3/coins/bitcoin/market_chart?vs_currency=usd&days=${timeframe}`,
          {
            method: 'GET',
            headers: {
              'Content-Type': 'application/json',
            },
          }
        );

        const data = await response.json();
        setCryptoData(data.prices);
      } catch (error) {
        console.error('Error fetching data:', error);
      }
    };

    fetchData();
  },[timeframe]); // Run effect whenever timeframe changes

  const handleTimeframeChange = (event) => {
    const newTimeframe = event.target.value;
          alert(newTimeframe);
    setTimeframe(newTimeframe);
  };

  return (
    <div className="App">
      <h1 className="chart-title">Crypto Currency Price Chart</h1>
      <div className="controls">
        <div className="timeframe-selector">
          <label>Select Timeframe: </label>
          <select value={timeframe} onChange={handleTimeframeChange}>
            <option value={7}>1 Week</option>
            <option value={30}>1 Month</option>
            <option value={90}>3 Months</option>
            <option value={180}>6 Months</option>
          </select>
        </div>
      </div>
      {/* LineChart with Recharts */}
      // … same …
      );
}

export default App;

نکته اصلی فهرست ۴ تغییر URL نقطه پایانی است که نمودار را هدایت می کند و باعث می شود نمودار آن تغییر را منعکس کند. در اینجا مراحل ایجاد این به‌روزرسانی آمده است:

  • یک متغیر حالت بازه زمانی ایجاد کنید.
  • از متغیر تایم فریم در URL واکشی استفاده کنید: days=${timeframe}.
  • متغیر تایم فریم را به عنوان متغیر وابستگی به قلاب useEffect منتقل کنید، بنابراین زمانی که تایم فریم تغییر می کند، قلاب اجرا می شود. هنگامی که fetch() با داده های جدید برمی گردد، وضعیت cryptoData تغییر می کند. اکنون نمودار خود به عنوان ویژگی داده به آن متغیر واکنش نشان می دهد. به طور خلاصه: نمودار با داده های جدید دوباره ترسیم می شود.
  • یک منوی کشویی ساده بسازید که امکان تغییر بازه زمانی را فراهم می کند.
  • یک کنترل کننده handleTimeFrameChange برای اعمال مقدار جدید در تایم فریم اضافه کنید.

افزودن نمودار نوار حجم

حالا بیایید نوع دیگری از نمودار را اضافه کنیم. نقطه پایانی CoinGecko همچنین یک فیلد data.total_volumes را با آرایه‌ای از مهرهای زمانی و حجم‌ها (یعنی مقدار دارایی‌هایی که در آن زمان منتقل می‌شوند) برمی‌گرداند. ما می توانیم از این برای ایجاد یک نمودار میله ای در همان سری زمانی که نمودار قیمت است استفاده کنیم. این به ما یک رابط کاربری شبیه به صفحه نمایش در شکل ۴ می دهد.

react chart fig4

شکل ۴. افزودن نمودار میله ای

برای انجام این کار، جزء نمودار میله‌ای جدید را به نشانه‌گذاری اضافه می‌کنیم و آن را به همان منبع داده متصل می‌کنیم، همانطور که در فهرست ۵ نشان داده شده است.


import React, { useState, useEffect } from 'react';
import { LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, Legend, Brush, BarChart, Bar } from 'recharts';

function App() {
  // … same ...

  return (
    // … same ...
        <div className="chart">
          <h2>Volume Chart</h2>
            <BarChart width={800} height={400} data={cryptoData.total_volumes}>
              <CartesianGrid stroke="#f5f5f5" />
              <XAxis dataKey="0" tickFormatter={(timestamp) => new Date(timestamp).toLocaleDateString()} />
              <YAxis />
              <Tooltip labelFormatter={(value) => new Date(value).toLocaleDateString()} />
              <Legend verticalAlign="top" height={36} />
              <Bar dataKey="1" fill="#82ca9d" />
            </BarChart>
        </div>
      </div>
    </div>
  );
}

export default App;

نمودار میله‌ای دارای همان پیکربندی نمودار خطی است. اما به جای اتصال آن به cryptoData.prices، از cryptoData.total_volumes استفاده می کنیم. Recharts استفاده از یک نمودار متفاوت را ساده کرده است. یکی دیگر از چیزهای خوب اینجا این است که هیچ یک از سیم کشی های داده تغییر نکرده است، و حتی بازشو تایم فریم روی هر دو نمودار کار می کند (زیرا آنها از یک متغیر حالت root استفاده می کنند).

زوم عمودی سفارشی

ما دیده‌ایم که چگونه می‌توان با مولفه براش بزرگ‌نمایی در مقیاس زمانی اضافه کرد، اما اگر بخواهیم در مقیاس عمودی بزرگ‌نمایی کنیم، مثلاً روی قیمت‌ها در نمودار قیمت، چه؟

Recharts یک مؤلفه داخلی برای بزرگنمایی عمودی ندارد، اما همچنان می‌توانیم آن را با کمی فینگل کردن انجام دهیم. ترفند استفاده از ویژگی دامنه YAxis است که حداقل و حداکثر مقادیر را در محور عمودی تعریف می کند. این ویژگی یک تابع را نیز می پذیرد. همانطور که در شکل ۵ نشان داده شده است، می توانیم تابع را برای استفاده از یک متغیر واکنشی ربوده و به صورت پویا مقادیر min و max را برای دستیابی به بزرگنمایی عمودی تغییر دهیم.

react chart fig5

شکل ۵. زوم عمودی با یک نوار لغزنده

در گام اول، باید یک جزء لغزنده شخص ثالث اضافه کنیم که از یک محدوده پشتیبانی می‌کند: npm i rc-slider.

سپس می‌توانیم از آن استفاده کنیم، همانطور که در فهرست ۶ نشان داده شده است.