1

I'm working on a React frontend project with typescript.

Following up on this, having settled how to post a file to Facebook Graph API, I would now need to convert a javascript generated svg to a JPG/PNG file and then send it via multipart/form-data to the graph api.

The result has some variable numbers on it which depend on user inputs. That's why I need to handle the svg in javascript.

My current code does the job I need but the resulting image is imperfect on facebook. What I have so far.

The svgTemplate.ts file is the following:

export const svgTemplate = `<svg id="Livello_1" data-name="Livello 1" xmlns="http://www.w3.org/2000/svg" width="150" height="107" viewBox="0 0 150 107">
<defs>
<style>.cls-1,.cls-3,.cls-4,.cls-5{fill:#ffc000;}.cls-2{fill:#fff;}.cls-3,.cls-4,.cls-5{stroke:#fff;stroke-miterlimit:10;}.cls-3{stroke-width:0.87px;}.cls-4{stroke-width:0.79px;}.cls-5{stroke-width:0.65px;}</style>
</defs>
<title>bannerino scegli il tuo sconto</title>
<path class="cls-1" d="M136.88,2.63a10,10,0,0,1,10,10V94.37a10,10,0,0,1-10,10H13.13a10,10,0,0,1-10-10V12.63a10,10,0,0,1,10-10H136.88m0-2H13.13a12,12,0,0,0-12,12V94.37a12,12,0,0,0,12,12H136.88a12,12,0,0,0,12-12V12.63a12,12,0,0,0-12-12h0Z"/>
<path class="cls-2" d="M16.61,19.42a7.22,7.22,0,0,0,3.13.78c1.3,0,2-.54,2-1.35s-0.59-1.22-2.1-1.76c-2.08-.72-3.43-1.87-3.43-3.69,0-2.13,1.78-3.77,4.73-3.77a7.66,7.66,0,0,1,3.19.63l-0.63,2.28a6,6,0,0,0-2.62-.59c-1.22,0-1.82.56-1.82,1.21s0.71,1.15,2.32,1.76c2.21,0.82,3.25,2,3.25,3.73,0,2.1-1.61,3.88-5,3.88A8.18,8.18,0,0,1,16,21.75Z"/>
<path class="cls-2" d="M35.71,22a8.06,8.06,0,0,1-3.21.54c-4.32,0-6.55-2.69-6.55-6.25,0-4.27,3-6.64,6.83-6.64a7.37,7.37,0,0,1,3.08.56l-0.57,2.24A6.11,6.11,0,0,0,32.9,12a3.76,3.76,0,0,0-4,4.14,3.73,3.73,0,0,0,4,4.08,7.08,7.08,0,0,0,2.36-.41Z"/>
<path class="cls-2" d="M45,17h-4.6v3h5.14v2.32h-8V9.83h7.72v2.32H40.39v2.6H45V17Z"/>
<path class="cls-2" d="M57.89,21.75a14,14,0,0,1-4.17.71,7,7,0,0,1-5.08-1.69,6,6,0,0,1-1.76-4.55c0-4.16,3-6.53,7.14-6.53a8.62,8.62,0,0,1,3.47.61l-0.59,2.26A6.92,6.92,0,0,0,54,12a3.78,3.78,0,0,0-4.14,4A4.09,4.09,0,0,0,55.16,20V17.38H53.23V15.17h4.66v6.58Z"/><path class="cls-2" d="M60.08,9.83h2.84V20h5v2.37H60.08V9.83Z"/>
<path class="cls-2" d="M72.39,9.83v12.5H69.56V9.83h2.84Z"/>
<path class="cls-2" d="M83,9.83v12.5H80.18V9.83H83Z"/>
<path class="cls-2" d="M85.47,9.83h2.84V20h5v2.37H85.47V9.83Z"/>
<path class="cls-2" d="M102.7,12.2H99.34V9.83h9.61V12.2h-3.41V22.33H102.7V12.2Z"/>
<path class="cls-2" d="M113.26,9.83V17c0,2.15.82,3.25,2.26,3.25s2.3-1,2.3-3.25V9.83h2.82v7c0,3.86-1.95,5.69-5.21,5.69s-5-1.74-5-5.73v-7h2.84Z"/>
<path class="cls-2" d="M134.52,15.95c0,4.1-2.49,6.58-6.14,6.58s-5.88-2.8-5.88-6.36c0-3.75,2.39-6.55,6.08-6.55S134.52,12.5,134.52,15.95Zm-9,.17c0,2.45,1.15,4.17,3,4.17s3-1.82,3-4.25c0-2.25-1.08-4.17-3-4.17S125.49,13.69,125.49,16.12Z"/>
<path class="cls-2" d="M30.67,38.31a9.62,9.62,0,0,0,4.18,1c1.73,0,2.64-.72,2.64-1.8s-0.79-1.63-2.79-2.35c-2.77-1-4.57-2.5-4.57-4.92,0-2.84,2.37-5,6.3-5a10.2,10.2,0,0,1,4.25.84l-0.84,3a7.92,7.92,0,0,0-3.48-.79c-1.63,0-2.42.74-2.42,1.61,0,1.06.94,1.53,3.09,2.35,2.94,1.09,4.32,2.62,4.32,5,0,2.79-2.15,5.16-6.72,5.16a10.89,10.89,0,0,1-4.72-1Z"/>
<path class="cls-2" d="M56.12,41.72a10.74,10.74,0,0,1-4.27.72c-5.76,0-8.72-3.58-8.72-8.33,0-5.68,4.05-8.85,9.09-8.85a9.82,9.82,0,0,1,4.1.74l-0.77,3a8.14,8.14,0,0,0-3.16-.62c-3,0-5.31,1.8-5.31,5.51,0,3.34,2,5.44,5.34,5.44a9.42,9.42,0,0,0,3.14-.54Z"/>
<path class="cls-2" d="M73.09,33.69c0,5.46-3.31,8.77-8.18,8.77S57.08,38.73,57.08,34c0-5,3.19-8.72,8.1-8.72C70.3,25.26,73.09,29.09,73.09,33.69Zm-12,.22c0,3.26,1.53,5.56,4.05,5.56s4-2.42,4-5.66c0-3-1.43-5.56-4-5.56S61.06,30.67,61.06,33.91Z"/>
<path class="cls-2" d="M75.56,42.19V25.53H80l3.46,6.1a48.15,48.15,0,0,1,2.72,5.71h0.07a61.89,61.89,0,0,1-.32-6.94V25.53h3.46V42.19h-4l-3.56-6.42a61.7,61.7,0,0,1-2.89-5.88l-0.07,0c0.1,2.2.15,4.55,0.15,7.27v5H75.56Z"/>
<path class="cls-2" d="M95.83,28.69H91.35V25.53h12.8v3.16H99.61V42.19H95.83V28.69Z"/><path class="cls-2" d="M120.69,33.69c0,5.46-3.31,8.77-8.18,8.77s-7.83-3.73-7.83-8.48c0-5,3.19-8.72,8.1-8.72C117.89,25.26,120.69,29.09,120.69,33.69Zm-12,.22c0,3.26,1.53,5.56,4.05,5.56s4-2.42,4-5.66c0-3-1.43-5.56-4-5.56S108.65,30.67,108.65,33.91Z"/>
<circle class="cls-3" cx="41.36" cy="68.74" r="21.03"/>
<circle class="cls-4" cx="101.44" cy="71.84" r="19.11"/><circle class="cls-5" cx="75.01" cy="64.1" r="15.86"/>
<path class="cls-2" d="M64.72,60.11A2.57,2.57,0,0,0,67,57.43V55.79h1.53V71.07H67.17V59.24a3.23,3.23,0,0,1-2.35,1l-0.08-.15h0Z"/>
<path class="cls-2" d="M75.8,69c0,1.4-1.11,2.34-2.79,2.34s-2.75-.94-2.75-2.34v-11c0-1.4,1.07-2.34,2.75-2.34s2.79,0.94,2.79,2.34V69ZM74.46,57.84A1.24,1.24,0,0,0,73,56.77a1.19,1.19,0,0,0-1.41,1V69A1.21,1.21,0,0,0,73,70.09,1.24,1.24,0,0,0,74.46,69V57.84Z"/>
<path class="cls-2" d="M80,59.75a2.22,2.22,0,0,1,1.76.79,3.77,3.77,0,0,1,0,4.33,2.22,2.22,0,0,1-1.76.79,2.19,2.19,0,0,1-1.75-.79,3.8,3.8,0,0,1,0-4.33A2.19,2.19,0,0,1,80,59.75Zm0,5q1.27,0,1.27-2t-1.27-2q-1.26,0-1.26,2T80,64.72Zm6.73-4.78L80.89,71.07H79.83l5.85-11.13h1.06Zm-0.18,5.4a2.21,2.21,0,0,1,1.76.79,3.77,3.77,0,0,1,0,4.33,2.34,2.34,0,0,1-3.51,0,3.81,3.81,0,0,1,0-4.33A2.19,2.19,0,0,1,86.56,65.35Zm0,5q1.27,0,1.27-2t-1.27-2q-1.26,0-1.26,2T86.56,70.32Z"/>
<g id="_15" data-name="15">
<path class="cls-2" d="M92.25,68.89a2.65,2.65,0,0,0,2.44-2.73V64.49h1.62V80H94.85V68a3.48,3.48,0,0,1-2.49,1l-0.09-.16h0Z"/>
<path class="cls-2" d="M99.21,77.12V78A1.25,1.25,0,0,0,100.7,79,1.23,1.23,0,0,0,102.16,78c0-.42,0-0.87,0-1.4v-3.8c0-.53-0.62-0.89-1.58-0.89a1.19,1.19,0,0,0-1.42,1H98V64.49h1.42c0,0.56.73,0.84,1.47,0.84s1.51-.29,1.51-0.84h1.24c0,1.24-1,2-2.51,2a2,2,0,0,1-1.71-.8v4.93c0,0.11,0,.2,0,0.31s0,0.44-.11.71a1.84,1.84,0,0,1,1.71-1,2.31,2.31,0,0,1,2.6,2.33v4.76c0,1.51-1.13,2.51-2.91,2.51s-2.91-1-2.91-2.51V77.12h1.42Z"/>
<path class="cls-2" d="M107.81,68.52a2.39,2.39,0,0,1,1.86.8,3.72,3.72,0,0,1,0,4.41,2.39,2.39,0,0,1-1.86.8,2.36,2.36,0,0,1-1.85-.8,3.75,3.75,0,0,1,0-4.41A2.36,2.36,0,0,1,107.81,68.52Zm0,5.06q1.34,0,1.34-2.06t-1.34-2.06q-1.33,0-1.33,2.06T107.81,73.59Zm7.12-4.87L108.75,80h-1.13l6.19-11.33h1.12Zm-0.19,5.5a2.38,2.38,0,0,1,1.86.81,3.72,3.72,0,0,1,0,4.41,2.54,2.54,0,0,1-3.71,0,3.76,3.76,0,0,1,0-4.41A2.36,2.36,0,0,1,114.75,74.22Zm0,5.07q1.34,0,1.34-2.06t-1.34-2.06q-1.33,0-1.33,2.06T114.75,79.29Z"/>
</g>
<path class="cls-2" d="M26.28,60.67c0-1.76,1.37-2.91,3.57-2.91a3.38,3.38,0,0,1,3.62,3.54c0,2.17-1.12,4.25-2.85,6.88C29.08,70.6,28,72.44,28,74.11v1.59h5.65v1.54H26.28V74.11c0-2.19,1.07-4.25,2.83-6.88C30.65,64.82,31.69,63,31.69,61a1.68,1.68,0,0,0-1.84-1.7c-1.1,0-1.81.52-1.81,1.29v2.77H26.28V60.67Z"/>
<path class="cls-2" d="M42.71,74.58c0,1.76-1.45,2.94-3.65,2.94s-3.59-1.18-3.59-2.94V60.7c0-1.76,1.4-2.94,3.59-2.94s3.65,1.18,3.65,2.94V74.58ZM41,60.62c0-.8-0.77-1.34-1.89-1.34s-1.84.52-1.84,1.32V74.66c0,0.8.74,1.34,1.84,1.34S41,75.46,41,74.66v-14Z"/>
<path class="cls-2" d="M48.21,63a3,3,0,0,1,2.29,1,4.59,4.59,0,0,1,0,5.44,2.94,2.94,0,0,1-2.29,1,2.91,2.91,0,0,1-2.29-1,4.63,4.63,0,0,1,0-5.44A2.92,2.92,0,0,1,48.21,63Zm0,6.25q1.66,0,1.66-2.54t-1.66-2.54q-1.64,0-1.64,2.54T48.21,69.27Zm8.79-6-7.63,14H48l7.64-14H57ZM56.77,70a2.94,2.94,0,0,1,2.29,1,4.59,4.59,0,0,1,0,5.44,3.13,3.13,0,0,1-4.58,0,4.64,4.64,0,0,1,0-5.45A2.92,2.92,0,0,1,56.77,70Zm0,6.26q1.66,0,1.66-2.55t-1.66-2.54q-1.64,0-1.64,2.54T56.77,76.31Z"/>
</svg>`;

importing svg template (not modifying it for now, it's just a string)

import { svgTemplate } from "./svgTemplate";

the function doing the job is this one:

const svgToFacebook = () => {
    let svg = document.createElement("svg");
    svg.append(svgTemplate);
    let canvas = document.createElement("canvas");
    let ctx = canvas.getContext("2d");
    let svgSize = svg.getBoundingClientRect();
    canvas.style.width = svgSize.width.toString();
    canvas.style.height = svgSize.height.toString();
    let win = window.URL || window.webkitURL || window;
    let img = new Image();
    let blob = new Blob([svgTemplate], { type: "image/svg+xml" });
    let url = win.createObjectURL(blob);
    setImgUrl(url);
    img.onload = () => {
      ctx?.drawImage(img, 0, 0);
      win.revokeObjectURL(url);
      let imgURI = canvas.toDataURL("image/png");
      console.log("imgURI", imgURI);
      canvas.toBlob((blob) => {
        console.log(blob);
        if (blob !== null) {
          console.log("pngBlob", blob);
          let caption = "test upload local image from React";
          const formData = new FormData();
          formData.append("source", blob);
          formData.append("caption", caption);
          httpFacebookGraphClient(facebookToken)
            .post("/" + ldlTestFacebookGroupId + "/photos", formData, {
              headers: {
                "Content-Type": "multipart/form-data",
              },
            })
            .then((res) => {
              console.log(res.data);
            })
            .catch((err) => {
              console.log(err);
            });
        }
      }, "image/png");
    };
    img.src = url;
  };

In the jsx I've put an img tag controlled by the imgUrl state.

<img src={imgUrl} />

When I run the function, the image correctly shows on the page with this src "blob:http://localhost:3000/28851470-c496-4aaf-9f56-a4e59e992531" but on the Facebook group the result is not perfect: my svg stays on the top left corner of a white "wall" and with poor quality, as per the following screenshot.

Facebook result

if I inspect the img on Facebook I see this element:

<img height="150" width="300" alt="Nessuna descrizione della foto disponibile." class="z6erz7xo on4d8346 pytsy3co s8sjc6am myo4itp8 ekq1a7f9 mfclru0v p9wrh9lq" referrerpolicy="origin-when-cross-origin" src="https://scontent-mad1-1.xx.fbcdn.net/v/t39.30808-6/301399158_1037550966957065_186133786110416193_n.jpg?_nc_cat=108&amp;ccb=1-7&amp;_nc_sid=825194&amp;_nc_ohc=q0bIvPBoxZ0AX_p3lo5&amp;_nc_ht=scontent-mad1-1.xx&amp;oh=00_AT92CnanAQIeWn4uFwLptGKl6N9dYSB0xjDKfBsDuCEzEg&amp;oe=630A39B8">

This is what I get from the console.log(imgURI):

data:image/png;base64,
iVBORw0KGgoAAAANSUhEUgAAASwAAACWCAYAAABkW7XSAAAEYklEQVR4Xu3UAQkAAAwCwdm/
9HI83BLIOdw5AgQIRAQWySkmAQIEzmB5AgIEMgIGK1OVoAQIGCw/QIBARsBgZaoSlAABg+U
HCBDICBisTFWCEiBgsPwAAQIZAYOVqUpQAgQMlh8gQCAjYLAyVQlKgIDB8gMECGQEDFamKk
EJEDBYfoAAgYyAwcpUJSgBAgbLDxAgkBEwWJmqBCVAwGD5AQIEMgIGK1OVoAQIGCw/QIBAR
sBgZaoSlAABg+UHCBDICBisTFWCEiBgsPwAAQIZAYOVqUpQAgQMlh8gQCAjYLAyVQlKgIDB
8gMECGQEDFamKkEJEDBYfoAAgYyAwcpUJSgBAgbLDxAgkBEwWJmqBCVAwGD5AQIEMgIGK1O
VoAQIGCw/QIBARsBgZaoSlAABg+UHCBDICBisTFWCEiBgsPwAAQIZAYOVqUpQAgQMlh8gQC
AjYLAyVQlKgIDB8gMECGQEDFamKkEJEDBYfoAAgYyAwcpUJSgBAgbLDxAgkBEwWJmqBCVAw
GD5AQIEMgIGK1OVoAQIGCw/QIBARsBgZaoSlAABg+UHCBDICBisTFWCEiBgsPwAAQIZAYOV
qUpQAgQMlh8gQCAjYLAyVQlKgIDB8gMECGQEDFamKkEJEDBYfoAAgYyAwcpUJSgBAgbLDxA
gkBEwWJmqBCVAwGD5AQIEMgIGK1OVoAQIGCw/QIBARsBgZaoSlAABg+UHCBDICBisTFWCEi
BgsPwAAQIZAYOVqUpQAgQMlh8gQCAjYLAyVQlKgIDB8gMECGQEDFamKkEJEDBYfoAAgYyAw
cpUJSgBAgbLDxAgkBEwWJmqBCVAwGD5AQIEMgIGK1OVoAQIGCw/QIBARsBgZaoSlAABg+UH
CBDICBisTFWCEiBgsPwAAQIZAYOVqUpQAgQMlh8gQCAjYLAyVQlKgIDB8gMECGQEDFamKkE
JEDBYfoAAgYyAwcpUJSgBAgbLDxAgkBEwWJmqBCVAwGD5AQIEMgIGK1OVoAQIGCw/QIBARs
BgZaoSlAABg+UHCBDICBisTFWCEiBgsPwAAQIZAYOVqUpQAgQMlh8gQCAjYLAyVQlKgIDB8
gMECGQEDFamKkEJEDBYfoAAgYyAwcpUJSgBAgbLDxAgkBEwWJmqBCVAwGD5AQIEMgIGK1OV
oAQIGCw/QIBARsBgZaoSlAABg+UHCBDICBisTFWCEiBgsPwAAQIZAYOVqUpQAgQMlh8gQCA
jYLAyVQlKgIDB8gMECGQEDFamKkEJEDBYfoAAgYyAwcpUJSgBAgbLDxAgkBEwWJmqBCVAwG
D5AQIEMgIGK1OVoAQIGCw/QIBARsBgZaoSlAABg+UHCBDICBisTFWCEiBgsPwAAQIZAYOVq
UpQAgQMlh8gQCAjYLAyVQlKgIDB8gMECGQEDFamKkEJEDBYfoAAgYyAwcpUJSgBAgbLDxAg
kBEwWJmqBCVAwGD5AQIEMgIGK1OVoAQIGCw/QIBARsBgZaoSlACBB1YxAJfjJb2jAAAAAEl
FTkSuQmCC
marcob8986
  • 153
  • 4
  • 12
  • Does this answer your question? [Convert SVG to image (JPEG, PNG, etc.) in the browser](https://stackoverflow.com/questions/3975499/convert-svg-to-image-jpeg-png-etc-in-the-browser) – James Aug 23 '22 at 17:37
  • Can you explain what you mean with "the svg has some variables"? Because that's not a thing in SVG. – Mike 'Pomax' Kamermans Aug 23 '22 at 17:38
  • @James partially, I started from there...see EDIT – marcob8986 Aug 23 '22 at 18:42
  • @Mike'Pomax'Kamermans I meant the "result" has some variables, that's why I need to hanlde svg in javascript. see EDIT – marcob8986 Aug 23 '22 at 18:42
  • @RobertLongson the code was missing, now the question is complete – marcob8986 Aug 23 '22 at 18:43
  • The image URI is a data uri. It is not "a URL", it is a "URI", it's a finished asset already. So: why did you write `fetch(imgURI).....`? Can you explain what you think that code achieves? – Mike 'Pomax' Kamermans Aug 23 '22 at 18:49
  • @Mike'Pomax'Kamermans thx for your help. I'm really new to this kind of "file handling" in javascript and I'mt trying to put together a lot of pieces. I found that kind of structure in this [post](https://stackoverflow.com/questions/12168909/blob-from-dataurl) – marcob8986 Aug 23 '22 at 20:14
  • Show the content of your template when you create the SVG Blob from it. It certainly lacks something like a width/height, or it draws outside of your 300x150px canvas. Also, use `canvas.toBlob(callback, mime)` directly instead of this fetch(dataURL).blob() hack. Finally, if you want to upload a JPEG image, `"image/png"` isn't the correct value for the mime type. – Kaiido Aug 23 '22 at 22:25
  • When I said "the content of your template" I meant the actual `svgTemplate` string. Please show that in your question. Something like ` – Kaiido Aug 24 '22 at 14:33
  • @Kaiido done, shared the svg string in the question. Any help? I still haven't found a solution – marcob8986 Aug 24 '22 at 15:29
  • Try to add a `width="150" height="107"` on the root `` (I'm AFK right now, can't test myself) – Kaiido Aug 24 '22 at 15:40
  • thx @Kaiido, it now works. the results are however not perfect, the resulting image on Facebook has my svg on the top left corner of a white wall. Updated the question – marcob8986 Aug 24 '22 at 15:50
  • You need to set the size of your to the one of your loaded . – Kaiido Aug 25 '22 at 01:34

0 Answers0