Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Line Chart Shows Scribbled/Glitched Lines #12002

Open
SalahHaciAkil opened this issue Jan 16, 2025 · 1 comment
Open

Line Chart Shows Scribbled/Glitched Lines #12002

SalahHaciAkil opened this issue Jan 16, 2025 · 1 comment

Comments

@SalahHaciAkil
Copy link

SalahHaciAkil commented Jan 16, 2025

Expected behavior

The colored area beneath the line should render smoothly and consistently, without any white spots or gaps, regardless of screen size or resolution.
The chart should maintain visual integrity across all devices, including iPad-sized screens, without artifacts or rendering issues.

Current behavior

When rendering a line chart using react-chartjs-2 (Chart.js) within a Next.js v12 application, the colored area beneath the line occasionally displays white spots, as shown in the image below. This issue is inconsistent and primarily occurs on screens with iPad-sized resolutions, making it challenging to reproduce consistently.

Image

here is how I'm rendering the graph in Next.js v12

import React, { useMemo } from 'react';
import { Line } from 'react-chartjs-2';
import {
  Chart as ChartJS,
  LineElement,
  CategoryScale,
  LinearScale,
  PointElement,
  Tooltip,
} from 'chart.js';
import { Box } from '@mui/material';
import { ValidInsightsTypes } from 'src/components/common/InsightsTable';
import { PointsByDate } from 'src/utils/interfaces/custom-queries/insights/common/CommonResponse.interfaces';

ChartJS.register(
  LineElement,
  CategoryScale,
  LinearScale,
  PointElement,
  Tooltip
);

// Create enum of the colors
const FrontInsightCardGraphColors = {
  [ValidInsightsTypes.submittedPrs]: '#167BD8',
  [ValidInsightsTypes.reviewedPrs]: '#FDB043',
  [ValidInsightsTypes.commentedPrs]: '#B895FD',
  [ValidInsightsTypes.commentsReceived]: '#B895FD',
  [ValidInsightsTypes.commitsMade]: '#22C55E',
  [ValidInsightsTypes.prSize]: '#EC4899',
  [ValidInsightsTypes.cycleTime]: '#3B82F6',
  [ValidInsightsTypes.codingTime]: '#E473E8',
  [ValidInsightsTypes.mergeTime]: '#F2D958',
  [ValidInsightsTypes.reviewTime]: '#725CEF',
  default: '#FDB043',
};

const getPointsValue = (points: any[] | undefined) =>
  points && points.length > 0 ? points : undefined;

interface FrontInsightCardGraphProps {
  insightsType: ValidInsightsTypes;
  points?: PointsByDate[];
  tooltipLabel?: string;
  // eslint-disable-next-line no-unused-vars
  pointCallback?: (value: any) => any;
}

function FrontInsightCardGraph({
  insightsType,
  points,
  tooltipLabel,
  pointCallback,
}: FrontInsightCardGraphProps) {
  const data = useMemo(
    () => ({
      labels: (
        getPointsValue(points) ?? [{ date: 'empty' }, { date: 'empty' }]
      ).map((item) => item.date),
      datasets: [
        {
          label: 'label',
          data: getPointsValue(points)?.map((item) => item.value) ?? [0, 0],
          fill: true,
          backgroundColor: `${FrontInsightCardGraphColors[insightsType]}4D`,
          borderColor: FrontInsightCardGraphColors[insightsType],
          borderWidth: 1, // Thinner line
          tension: 0.4, // Smooth curves
          pointRadius: (context) =>
            // Show only the last point
            context.dataIndex === context.dataset.data.length - 1 ? 3 : 0,
          pointHoverRadius: 3, // Disable hover effects on all points
          pointBackgroundColor: (context) =>
            // Set color for the last point
            context.dataIndex === context.dataset.data.length - 1
              ? FrontInsightCardGraphColors[insightsType]
              : 'transparent',
        },
      ],
    }),
    [points, insightsType]
  );
  const options = useMemo(
    () => ({
      responsive: true,
      maintainAspectRatio: false,
      plugins: {
        legend: {
          display: false, // Hide the legend
        },
        tooltip: {
          enabled: true,
          intersect: false,
          mode: 'nearest',
          callbacks: {
            title: (context) => {
              const labelDate =
                context[0]?.label && context[0]?.label !== 'empty'
                  ? new Date(context[0]?.label).toLocaleDateString('en-GB')
                  : '';
              return labelDate ? `Date: ${labelDate}` : ''; // Display the date from the label
            },
            label: (context) =>
              `${tooltipLabel}: ${
                pointCallback ? pointCallback(context.raw) : context.raw
              }`, // Display the value
          },
          displayColors: false, // Hide the color box
          backgroundColor: 'white',
          borderColor: '#E5E7EB', // Light gray border
          borderWidth: 1,
          titleFont: {
            size: 14,
            weight: '600', // Bold title
          },
          bodyFont: {
            size: 14,
            weight: '400', // Regular body text
          },
          titleColor: '#111827', // Darker color for the title
          bodyColor: '#6B7280', // Lighter gray for the body
          padding: 8,
          cornerRadius: 8, // Rounded corners
          boxShadow: '0px 4px 8px rgba(0, 0, 0, 0.1)', // Shadow for a floating effect
          caretPadding: 6, // Space between tooltip arrow and tooltip body
        },
      },
      scales: {
        x: {
          display: false, // Hide x-axis labels
          grid: {
            display: false, // Remove vertical grid lines
          },
        },
        y: {
          display: false, // Hide y-axis labels
          grid: {
            display: false, // Remove horizontal grid lines
          },
        },
      },
    }),
    // eslint-disable-next-line react-hooks/exhaustive-deps
    [tooltipLabel]
  );

  return (
    <Box sx={{ height: 70, width: '100%' }}>
      <Line data={data} options={options as any} />
    </Box>
  );
}

export default FrontInsightCardGraph;

Reproducible sample

it's very diffecult to reproduce the issue, but the attached image shows what I mean

chart.js version

4.3

Browser name and version

Chrome 31.0.6778.206

@rtmotiondev
Copy link

I've experienced something similar with chartjs 4.4.7

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants