Search code examples
javascriptphpsvgmpdf

Scale SVG with path and pass to mPdf


Hello I've got problem with SVG.

First I put SVG into HTML and by input type radio, user can scale this SVG (add style attribute with width in % values). But when I send this to mpdf (SVGs in JSON) it does not work.

Then I try to calculate size on pdf but I can't fit viewbox/size of this SVG.

So I've got SVG like this:

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" id="svg-number" width="686.280029296875px" height="540.8900146484375px" viewBox="62.619998931884766 245 686.280029296875 540.8900146484375" style="width: 28%; height: auto;"><path fill="#ffffff" id="path-svg-number" d="M277.95 252.69L277.95 785.89L171.02 785.89L171.02 347.17L62.62 347.17L62.62 271.73L277.95 252.69ZM748.90 703.86L748.90 785.89L384.89 785.89L384.89 715.94L557.37 531.01Q594.73 488.16 610.47 458.68Q626.22 429.20 626.22 403.93L626.22 403.93Q626.22 370.24 608.09 348.82Q589.97 327.39 556.64 327.39L556.64 327.39Q519.65 327.39 500.43 352.48Q481.20 377.56 481.20 419.31L481.20 419.31L377.20 419.31L376.46 417.11Q374.63 344.97 423.89 294.98Q473.14 245.00 556.64 245.00L556.64 245.00Q639.04 245.00 686.10 287.84Q733.15 330.69 733.15 402.10L733.15 402.10Q733.15 450.44 706.60 491.27Q680.05 532.10 618.90 598.39L618.90 598.39L524.05 702.03L524.78 703.86L748.90 703.86Z"></path></svg>

And I want to render it on pdf but with different size.

function getPrintSize(container) {
    let renderSize = getElementSize(container);
    let scale = getScale(); //retrun int value ex. 33

    return {
        width: (renderSize.width * 100) / scale, //ex. (159 * 100) / 24.127 = 659.013
        height: (renderSize.height * 100) / scale //ex. (125 * 100) / 24.127 = 518.092
    }
}

Then new SVG should has 659.013px x 518.092px but I can't set new correct dimensions (mPdf does not support style="width: ...". Theoretically it support partialy this tag, but in practise not).

In mPdf I try to render it like this:

...
$template .= '<td align="center" style="width: 1890px; height: 913px; vertical-align: middle">'.$data->number.'</td>';
...

Have anyone got any idea how can I scale this SVG with path?


Solution

  • In my experience pdf generators like mPdf or DOmPDF tend to struggle with relative, percentage-based values.

    Provided, your scaling calculation works as expected you could change the svg's width and height attributes directly:

    let svg = document.getElementById('svg-number')
    scaleSVG(svg, 0.05);
    
    function scaleSVG(svg, scale=1){
      let width = svg.width.baseVal.value;
      let height = svg.height.baseVal.value;
      
      /**
      * alternative
      let width = parseFloat(svg.getAttribute('width'));
      let height = parseFloat(svg.getAttribute('height'));
      */
      
      svg.setAttribute('width', width*scale)
      svg.setAttribute('height', height*scale)
    }
    svg{
      border: 1px solid red;
    }
    <svg xmlns="http://www.w3.org/2000/svg" id="svg-number" width="686.280029296875px" height="540.8900146484375px" viewBox="62.619998931884766 245 686.280029296875 540.8900146484375" >
      <path id="path-svg-number" d="m277.9 252.7 0 533.2-106.9 0 0-438.7-108.4 0 0-75.5 215.3-19zm471 451.2 0 82-364 0 0-70 172.5-184.9q37.3-42.8 53.1-72.3 15.7-29.5 15.7-54.8l0 0q0-33.7-18.1-55.1-18.1-21.4-51.5-21.4l0 0q-37 0-56.2 25.1-19.2 25.1-19.2 66.8l0 0-104 0-.7-2.2q-1.9-72.1 47.4-122.1 49.2-50 132.7-50l0 0q82.4 0 129.5 42.8 47 42.9 47 114.3l0 0q0 48.3-26.5 89.2-26.6 40.8-87.7 107.1l0 0-94.9 103.6.8 1.9 224.1 0z" />
    </svg>

    To get calculable values you could either use

    let width = svg.width.baseVal.value;  
    

    or

    let width = parseFloat(svg.getAttribute('width'));
    

    The first will return a number by default and also converts percentage values to absolute (svg user-unit based) ones.

    The latter will strip all units an return the pure number value.