0

So I got a project where the user can generate a pdf based on their input. Using the jspdf library to generate the PDF files. The thing is though, the user can upload a profile picture, and I would like to display that image with rounded corners or fully rounded (with a border-radius of 50%). Since there isn't a native function that allows this in jspdf or any other library as far as I know (pfdkit, pdfmake), I am looking for a way to modify the image before generating the pdf.

I already tried using html2canvas, and that worked fine actually. The problem with html2canvas occurs when a user is on their mobile. Since the width and height of the image are adjusted to the screen size (both of which are around 35px), taking a snapshot with html2canvas and then displaying that in a pdf with a width & height of 100px, the image obviously gets way to blurry.

So ideally, I need something to edit the original image or something before generating a PDF file with jspdf.

Any other ideas that bring me closer to a solution are also very much appreciated.

Just for clarification, simply adding a CSS property to the image won't help. jspdf just uses the image in the img tag, without any css properties.

Reinier68
  • 2,450
  • 1
  • 23
  • 47
  • dont take a snapshot of what's shown on dom, instead do resize in background on original image then use that for the pdf – Lawrence Cherone Nov 06 '19 at 18:20
  • Possible duplicate of [Javascript Rounded Corners for Images](https://stackoverflow.com/questions/2171519/javascript-rounded-corners-for-images) – sebasaenz Nov 06 '19 at 18:22
  • The screenshot is based on the DOM, so the image has to be on the screen unfortunately. I've tried just placing the image offscreen and taking snapshot. Got a blank image as a result. – Reinier68 Nov 06 '19 at 18:57
  • Possible duplicate of [Canvas drawimage with round corners](https://stackoverflow.com/questions/19585999/canvas-drawimage-with-round-corners) – Lawrence Cherone Nov 06 '19 at 19:45

3 Answers3

1

I would suggest you to add a class to the image before you generate the pdf and define the rule for that class in css:

.circle {
  border-radius: 50%;
}

Or, even you may need to force in case there's already css with some border-radius value to img tag:

.circle {
  border-radius: 50% !important;
}
Bhojendra Rauniyar
  • 83,432
  • 35
  • 168
  • 231
  • I know I can display an image with `img` tag and using `border-radius` to make the rounded corners. But when generating the pdf, it doesn't take the css into account. It just displays the whole images, unmodified. That's why I need to really modify it of some sort before generating a pdf with it. – Reinier68 Nov 06 '19 at 18:52
  • Then I must say sorry. Coz, there's no such thing that we can do with just html. – Bhojendra Rauniyar Nov 06 '19 at 18:56
  • Yeah, I thought so hehe. This was kinda a longshot. – Reinier68 Nov 06 '19 at 18:57
1

It is possible to use rounded images on jspdf, you just need to apply the rounded-ness to the image before adding it to the PDF, if your already resizing you have the context.

roundedImage taken from: Canvas drawimage with round corners

For example (wont work on SO, so no demo):

<!DOCTYPE html>
<html>
  <head>
    <title></title>
    <meta charset="UTF-8" />

    <script src="https://unpkg.com/jspdf@latest/dist/jspdf.min.js"></script>

    <style>
      * {
        margin: 0;
        padding: 0;
      }
      body {
        background: #ccc;
      }
      #pdf {
        display: block;
        position: absolute;
        bottom: 0;
        width: 100vw;
        height: 100vh;
      }
    </style>
  </head>

  <body>
    <embed id="pdf" src="#" type="application/pdf" width="100%" height="100%" />
    <script>
      function roundedImage(ctx, x, y, width, height, radius) {
        ctx.beginPath();
        ctx.moveTo(x + radius, y);
        ctx.lineTo(x + width - radius, y);
        ctx.quadraticCurveTo(x + width, y, x + width, y + radius);
        ctx.lineTo(x + width, y + height - radius);
        ctx.quadraticCurveTo(
          x + width,
          y + height,
          x + width - radius,
          y + height
        );
        ctx.lineTo(x + radius, y + height);
        ctx.quadraticCurveTo(x, y + height, x, y + height - radius);
        ctx.lineTo(x, y + radius);
        ctx.quadraticCurveTo(x, y, x + radius, y);
        ctx.closePath();
      }

      var img = new Image();
      img.src = "https://graph.facebook.com/649650002/picture?type=square";
      img.setAttribute("crossorigin", "anonymous");

      img.onload = function() {
        //
        const canvas = document.createElement("canvas");
        canvas.width = img.width;
        canvas.height = img.height;
        const ctx = canvas.getContext("2d");

        roundedImage(ctx, 0, 0, 50, 50, 5);
        ctx.clip();
        ctx.drawImage(img, 0, 0, img.width, img.height);
        ctx.restore();

        // Default export is a4 paper, portrait, using milimeters for units
        var doc = new jsPDF();

        doc.text("woop!..rounded corners.", 10, 15);
        doc.addImage(canvas.toDataURL("image/png"), "PNG", 15, 25, 30, 30);

        document.getElementById("pdf").src = doc.output(
          "dataurlstring",
          "its-a.pdf"
        );
      };
    </script>
  </body>
</html>
Lawrence Cherone
  • 46,049
  • 7
  • 62
  • 106
0

If anyone for whatever reason stumbles across this post, I managed to actually achieve my desired result. As I said the user is able to upload an image and I would like to display that image with rounded corners or with a border-radius of 50%. Anyway, before previewing (and uploading) the image to my website, the user has to crop the image using cropperjs. They can then decide for themselves if they would like to display the image with rounded corners or with a border radius of 50%. I think that gives a tremendous boost to the UX and my end result.

Reinier68
  • 2,450
  • 1
  • 23
  • 47