skip to Main Content

I’m working on a feature that converts DOM content into a PDF using the mpdf/mpdf library from Composer/Packagist, and it generally works great. However, part of the DOM content is generated using C3.js to create charts. I convert the C3.js SVG to a PNG by drawing it onto a canvas so that it appears in the PDF file.

The conversion works, but the resulting chart has a black background, which makes the legends unreadable and doesn’t look good.

Chart with black background

Here’s the code I’m using to create the canvas:

document.getElementById('generatePDF').addEventListener('click', function(event) {
    event.preventDefault();

    // Récupérer le contenu HTML (données de la campagne)
    const campaignContent = document.querySelector('.container--campaigns').innerHTML;

    // Convertir le graphique C3.js en image base64
    const svg = document.querySelector('#chart svg');
    const svgData = new XMLSerializer().serializeToString(svg);
    
    // Créer une image base64 à partir du SVG
    const canvas = document.createElement('canvas');
    const ctx = canvas.getContext('2d');
    const img = new Image();

    const svgBase64 = 'data:image/svg+xml;base64,' + btoa(encodeURIComponent(svgData).replace(/%([0-9A-F]{2})/g, function(match, p1) {
        return String.fromCharCode(parseInt(p1, 16));
    }));
    
    img.onload = function() {
        canvas.width = svg.clientWidth;
        canvas.height = svg.clientHeight;
        ctx.drawImage(img, 0, 0);
        const chartImageBase64 = canvas.toDataURL('image/png');

        // Remplir les champs cachés avec les données récupérées
        document.getElementById('htmlContent').value = campaignContent;
        document.getElementById('chartImage').value = chartImageBase64;

        // Soumettre le formulaire
        document.getElementById('formPDF').submit();
    };

    img.src = svgBase64;  // Convertir le SVG en image
});

I’ve tried adding a rect element for a background, applying styles to the #chart svg via JS, and even setting the background in PHP with mPDF, but nothing seems to work.

Any ideas on how to fix this?

Thanks so much for your help!

2

Answers


  1. Chosen as BEST ANSWER

    I did many tests and I checked every c3.js CSS class on my original SVG. I found out that some elements add a style="fill-opacity: 0;". When I turned fill-opacity to 1 and a black background appeared. I did some tests on this elements and it worked. Thanks a lot to every of you that took time to answer, you're awesome guys !

    Exemple solution :

    const gRect = document.querySelector('.c3-event-rects');
    
    gRect.style.opacity = '1';
    gRect.style.fillOpacity = '1';
    gRect.style.fill = 'white';
    

  2. This is the transparent part, probably. Sometimes appear green. So let’s change all that is transparent into white, please.

    document.getElementById('generatePDF').addEventListener('click', function(event) {
      event.preventDefault();
    
      // Récupérer le contenu HTML (données de la campagne)
      const campaignContent = document.querySelector('.container--campaigns').innerHTML;
    
      // Convertir le graphique C3.js en image base64
      const svg = document.querySelector('#chart svg');
      const svgData = new XMLSerializer().serializeToString(svg);
    
      // Créer une image base64 à partir du SVG
      const canvas = document.createElement('canvas');
      const ctx = canvas.getContext('2d');
      const img = new Image();
    
      const svgBase64 = 'data:image/svg+xml;base64,' + btoa(encodeURIComponent(svgData).replace(/%([0-9A-F]{2})/g, function(match, p1) {
        return String.fromCharCode(parseInt(p1, 16));
      }));
    
      img.onload = function() {
        canvas.width = svg.clientWidth;
        canvas.height = svg.clientHeight;
        ctx.drawImage(img, 0, 0);
    
        // lets change all alpha 0 to alpha rgba(255, 255, 255, 255)
        const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
        const data = imageData.data;
        for (let i = 0; i < data.length; i += 4) {
          if (data[i + 3] == 0) {
            data[i] = 255; 
            data[i + 1] = 255; 
            data[i + 2] = 255; 
            data[i + 3] = 255; 
          }
        }
        ctx.putImageData(imageData, 0, 0);
        
        // your code continues
        const chartImageBase64 = canvas.toDataURL('image/png');
    
        // Remplir les champs cachés avec les données récupérées
        document.getElementById('htmlContent').value = campaignContent;
        document.getElementById('chartImage').value = chartImageBase64;
    
        // Soumettre le formulaire
        document.getElementById('formPDF').submit();
      };
    
      img.src = svgBase64; // Convertir le SVG en image
    });
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search