Vetrivel M
Vetrivel M

Reputation: 1

Render Image update when I click legend chartjs

In ChartJs I want to custamize the bar chart.I'm placed the images in empty places if i click on the legend that images cannot be hide. I made a attendance bar chart if person is absent that place will show absent image & alslo if person is working hours place in that place(bar chart in stacked). Finally I want if absent label or Leave label legend click that image will hide.this ref for my bar chart.my issue if i click legend hide`.

if i click on legend remove that image

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Chart Js</title>
    <link rel="stylesheet" href="chart.css">
    <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/chartjs-plugin-datalabels/2.2.0/chartjs-plugin-datalabels.min.js" integrity="sha512-JPcRR8yFa8mmCsfrw4TNte1ZvF1e3+1SdGMslZvmrzDYxS69J7J49vkFL8u6u8PlPJK+H3voElBtUCzaXj+6ig==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
    <script src="https://unpkg.com/chart.js-plugin-labels-dv/dist/chartjs-plugin-labels.min.js"></script>
</head>
<body>
    <section class="container">
      <div class="sub_container">
        <div className="trans_header">
          <div className="payment_onetxt">
              <p className="box_txtone">Chart.js — Bar Chart</p>
          </div>
          <div className="payment_onetxt trans_selectbox">
              <select id="selected_box" >
              </select>
          </div>
      </div>
        <div>
          <canvas id="barChart"></canvas>
        </div>
    </div> 
    <div class="sub_container">
        <h2>Chart.js — Doughnut Chart</h2>
        <div>
          <canvas id="donutChart"></canvas>
        </div>
    </div> 
    </section>


    <script>

//select tag handle & options create
const today = new Date();
const monthNames = Array.from({ length: 12 }).map((_, i) => new Date(today.getFullYear(), i).toLocaleString('default', { month: 'long' }));
const selectElement = document.getElementById('selected_box');
let selectValue=new Date().getMonth();
const options = monthNames.map((month, index) => {
    return `<option value="${index}" ${index === selectValue ? 'selected' : ''}>${month}</option>`;
});

let handleMonthChange=(event)=>{
const selectedMonthIndex = event.target.value; 
barChart.data.labels=getCurrentMonthDates(Number(selectedMonthIndex));
barChart.update()
}
selectElement.innerHTML = options;
selectElement.addEventListener('change', handleMonthChange);


//get month Data
let getCurrentMonthDates=(currentMonth)=>{
  const todays = new Date();
  const currentYear = todays.getFullYear();
  // const currentMonth = todays.getMonth();

  // Get the number of days in the current month
  const daysInMonth = new Date(currentYear, currentMonth + 1, 0).getDate();

  // Create an acurrentMonthrray to store the dates
  const dates = [];

  // Loop through each day in the month
  for (let day = 1; day <= daysInMonth; day++) {
    // Format the date as 'M/D/YYYY'
    const formattedDate ="Day"+day
    dates.push(formattedDate);
  }

  return dates;
}
const currentMonth = new Date().getMonth();

let currentMonthDates = getCurrentMonthDates(currentMonth);

let barChartDatas={
  Xlabel :currentMonthDates,
  Ylabel :["Above 8 Hours","Below 8 Hours","Over Time","Leave","Early Entry","Late","Absent","Early Out"],
  bgs    :["blue","indianred","#2196f3","pink","purple","yellow","orange",'grey'],
  attendanceDatas:{
    "Working Hours":[0, 6, 9, 8, 7, 6, 7, 8, 9, 9, 9, 0, 9, 0, 6, 7, 9, 6, 9, 9, 0, 7, 9, 9, 6, 8, 9, 6, 5, 9, 6],
    "Over Time":[0, 2, 1, 0, 0, 0, 0, 4, 2, 1, 2, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 1, 0, 0,2],
    "Leave":[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'l', 0, 0, 0, 0, 0, 0, 'l', 0, 0, 0, 0, 0, 0, 0, 0, 0],
    "Early Entry":[0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    "Late": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    "Absent":['a', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'a', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0],
    "Early Out":[0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,1],
  }
}

let initialState={
  absent:false,
  leave:false,
}

let showImages = () => {
  const numDates = barChartDatas?.Xlabel?.length || 0; 
  const leaveData = barChartDatas?.attendanceDatas?.["Leave"];
  const absentData = barChartDatas?.attendanceDatas?.["Absent"];

  const imageData = Array.from({ length: numDates }, (_, index) => {
    const isAbsent = absentData?.[index] === 'a';
    const isLeave = leaveData?.[index] === 'l';

    // Check if the respective legend item is visible in legendItems array

    return isAbsent
      ? { src: "ab1.png", width: 30, height: 100 }
      : isLeave
      ? { src: "https://cdn-icons-png.flaticon.com/128/422/422930.png", width: 30, height: 30 }
      : null;
  });
  

  return imageData;
};

console.log(showImages())


const userImg = new Image();
userImg.src = "user.png";
const barAvatar = {
  id: "barAvatar",
  afterDraw(chart, args, options) {
    const { ctx, chartArea: { top, bottom }, scales: { x, y } } = chart;
    ctx.save();

    chart.data.datasets.forEach((dataset, datasetIndex) => {
      // Check if data is an array
      if (Array.isArray(dataset.data)) {
        dataset.data.forEach((datapoint, index) => {
          // Check if value is above 0, null, or a number
          if (typeof datapoint === 'number' && !isNaN(datapoint) && datapoint > 0) {
            ctx.drawImage(userImg, 
                          x.getPixelForValue(index) - 10, 
                          chart.getDatasetMeta(7).data[index].y - 20, 
                          18, 18);
          }
        });
      }
    });

    ctx.restore();
  }
};



// Define an empty array to store datasets dynamically
let datasets = [];


// Filter data for "Above 8 Hours" and "Below 8 Hours" based on "Working Hours"
let workingHoursData = barChartDatas?.attendanceDatas["Working Hours"];
let above8HoursData = workingHoursData.map((hours, index) => (hours > 8 ? hours : 0));
let below8HoursData = workingHoursData.map((hours, index) => (hours <= 8 ? hours : 0));

// Create datasets for "Above 8 Hours" and "Below 8 Hours"
datasets.push({
  label: "Above 8 Hours",
  data: above8HoursData,
  backgroundColor:barChartDatas?.bgs[0], // Use the first color for "Above 8 Hours"
});

datasets.push({
  label: "Below 8 Hours",
  data: below8HoursData,
  backgroundColor: barChartDatas?.bgs[1], // Use the second color for "Below 8 Hours"
});
barChartDatas?.Ylabel.slice(2).forEach((label, index) => {
  datasets.push({
    label: label,
    data: barChartDatas?.attendanceDatas[label],
    backgroundColor: barChartDatas?.bgs[index + 2]})
  })


var ctx = document.getElementById("barChart").getContext('2d');
var barChart = new Chart(ctx, {
    type: 'bar',
    data: {
      labels: barChartDatas?.Xlabel,
      datasets:datasets
    } ,
    options: {
        plugins: {
          datalabels: {
            color: 'black',
            rotation:-90,
             align: 'end',
             anchor: 'end',
            display: function(context) {
              return context.dataset.data[context.dataIndex] > 0;
            },
            font: {
              weight: 'bold',
            },
            formatter: function(value, context) {
              const datasetLabel = context.dataset?.label.toLowerCase().replace(/\s/g, '')
              switch(datasetLabel) {
                  case 'absent':
                  return 'Absent';
                  case 'leave':
                  return 'Leave';
                  default:
                  return '';  
              }
            },
          },
          legend: {
            display: true,
            onClick :async(e, legendItem, legend)=>{
              const index = legendItem.datasetIndex;
              const ci = legend.chart;
            //   const legendItemCh= legendItem?.text.toLowerCase().replace(/\s/g, '');
            //   const isVisible=ci.isDatasetVisible(index);

              if (ci.isDatasetVisible(index)) {
                  ci.hide(index);
                  legendItem.hidden = true;
              } else {
                  ci.show(index);
                  legendItem.hidden = false;
              }

          },          
            labels: {
              usePointStyle: true,
              pointStyle: 'circle'
            }
          },
          labels: {
            render: "image",
            textMargin: 0,
            images: showImages(),
            usePointStyle: true,
            useLineStyle: true,
          },
        },
        // Core options
        aspectRatio: 5 / 3,
        layout: {
          padding: {
            top: 24,
            right: 16,
            bottom: 0,
            left: 8
          }
        },
        elements: {
          line: {
            fill: false
          },
          point: {
            hoverRadius: 7,
            radius: 5
          }
        },
        scales: {
          x: {
            stacked: true
          },
          y: {
            stacked: true,
            beginAtZero: true,
                min: 0,
                max: 20,
                ticks: {
                    stepSize: 2,
                },
          }
          
        }
      },
      plugins: [ChartDataLabels,barAvatar],

  });

  

  
     
  </script>
      
      
```

Upvotes: 0

Views: 66

Answers (0)

Related Questions