为什么canvg选项中的scaleWidth和scaleHeight异常大?

问题描述 投票:0回答:1

我的代码片段产生了我想要的输出......非常接近。

enter image description here

但是,我很难理解为什么scaleWidth和scaleHeight需要为400。

我的目标是绘制宽度和高度为 40 的 SVG。我本以为我会设置:

  preset.scaleWidth = 40;
  preset.scaleHeight = 40;

正如他们的文档所说:

Scales horizontally to width.
Scales vertically to height.

SVG 的宽度和高度约为 44 像素。

我怎样才能更好地理解这些属性,以便我可以用 40 的宽度和高度绘制 SVG?

const svg = `<svg xmlns="http://www.w3.org/2000/svg" fill="#ff0000" viewBox="0 0 512 512"><!--!Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2024 Fonticons, Inc.--><path d="M256 0c17.7 0 32 14.3 32 32l0 10.4c93.7 13.9 167.7 88 181.6 181.6l10.4 0c17.7 0 32 14.3 32 32s-14.3 32-32 32l-10.4 0c-13.9 93.7-88 167.7-181.6 181.6l0 10.4c0 17.7-14.3 32-32 32s-32-14.3-32-32l0-10.4C130.3 455.7 56.3 381.7 42.4 288L32 288c-17.7 0-32-14.3-32-32s14.3-32 32-32l10.4 0C56.3 130.3 130.3 56.3 224 42.4L224 32c0-17.7 14.3-32 32-32zM107.4 288c12.5 58.3 58.4 104.1 116.6 116.6l0-20.6c0-17.7 14.3-32 32-32s32 14.3 32 32l0 20.6c58.3-12.5 104.1-58.4 116.6-116.6L384 288c-17.7 0-32-14.3-32-32s14.3-32 32-32l20.6 0C392.1 165.7 346.3 119.9 288 107.4l0 20.6c0 17.7-14.3 32-32 32s-32-14.3-32-32l0-20.6C165.7 119.9 119.9 165.7 107.4 224l20.6 0c17.7 0 32 14.3 32 32s-14.3 32-32 32l-20.6 0zM256 224a32 32 0 1 1 0 64 32 32 0 1 1 0-64z"/></svg>`;

var blob = new Blob(
  Array.prototype.map.call(
    document.querySelectorAll('script[type="text/js-worker"]'),
    function (oScript) {
      return oScript.textContent;
    }
  ),
  { type: "text/javascript" }
);

const worker = new Worker(window.URL.createObjectURL(blob), {
  type: "module"
});

const img = document.querySelector("img");

worker.postMessage({svg: svg});

worker.onmessage = (event) => {
  img.src = event.data.pngUrl;
};
<script type="text/js-worker">
  import { DOMParser } from 'https://cdn.skypack.dev/@xmldom/xmldom@^0.7.5'
  import {
    Canvg,
    presets
  } from 'https://cdn.skypack.dev/canvg@^4.0.0'

  const preset = presets.offscreen({
    DOMParser
  })

  preset.ignoreClear = true;
  preset.scaleWidth = 400;
  preset.scaleHeight = 400;
  
  self.onmessage = async (event) => {
    const { svg } = event.data;
    
    const radius = 28;
    const canvas = new OffscreenCanvas( radius * 2, radius * 2 ); // width, height
    const ctx = canvas.getContext( '2d' );
    
    ctx.beginPath();
    ctx.arc(radius, radius, radius, 0, 2 * Math.PI);
    ctx.fillStyle = 'blue';
    ctx.fill();
    
    const v = await Canvg.from(ctx, svg, preset)
    await v.render()

    const blob = await canvas.convertToBlob()
    const pngUrl = URL.createObjectURL(blob)

    self.postMessage({
      pngUrl
    })
  }
</script>

<img />

svg canvg offscreen-canvas
1个回答
0
投票

实际上,您的 SVG 尺寸是

viewBox
属性中指定的 512x512 单位。

因此

preset.scaleWidth=400
将转换为
0.78125

的缩放因子

const svg = `<svg xmlns="http://www.w3.org/2000/svg" fill="#ff0000" viewBox="0 0 512 512"><!--!Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2024 Fonticons, Inc.--><path d="M256 0c17.7 0 32 14.3 32 32l0 10.4c93.7 13.9 167.7 88 181.6 181.6l10.4 0c17.7 0 32 14.3 32 32s-14.3 32-32 32l-10.4 0c-13.9 93.7-88 167.7-181.6 181.6l0 10.4c0 17.7-14.3 32-32 32s-32-14.3-32-32l0-10.4C130.3 455.7 56.3 381.7 42.4 288L32 288c-17.7 0-32-14.3-32-32s14.3-32 32-32l10.4 0C56.3 130.3 130.3 56.3 224 42.4L224 32c0-17.7 14.3-32 32-32zM107.4 288c12.5 58.3 58.4 104.1 116.6 116.6l0-20.6c0-17.7 14.3-32 32-32s32 14.3 32 32l0 20.6c58.3-12.5 104.1-58.4 116.6-116.6L384 288c-17.7 0-32-14.3-32-32s14.3-32 32-32l20.6 0C392.1 165.7 346.3 119.9 288 107.4l0 20.6c0 17.7-14.3 32-32 32s-32-14.3-32-32l0-20.6C165.7 119.9 119.9 165.7 107.4 224l20.6 0c17.7 0 32 14.3 32 32s-14.3 32-32 32l-20.6 0zM256 224a32 32 0 1 1 0 64 32 32 0 1 1 0-64z"/></svg>`;

var blob = new Blob(
  Array.prototype.map.call(
    document.querySelectorAll('script[type="text/js-worker"]'),
    function (oScript) {
      return oScript.textContent;
    }
  ),
  { type: "text/javascript" }
);

const worker = new Worker(window.URL.createObjectURL(blob), {
  type: "module"
});

const img = document.querySelector("img");

worker.postMessage({svg: svg});

worker.onmessage = (event) => {
  img.src = event.data.pngUrl;
};
<script type="text/js-worker">
  import { DOMParser } from 'https://cdn.skypack.dev/@xmldom/xmldom@^0.7.5'
  import {
    Canvg,
    presets
  } from 'https://cdn.skypack.dev/canvg@^4.0.0'

  const preset = presets.offscreen({
    DOMParser
  })
  

  // intrinsic dimensions from the SVG viewBox
  const svgW=512, svgH = 512
  const svgScale=0.75;
  
  preset.ignoreClear = true;
  preset.scaleWidth = svgW*svgScale;
  preset.scaleHeight = svgH*svgScale;
  
  self.onmessage = async (event) => {
    const { svg } = event.data;
    
    const radius = 20;
    const canvas = new OffscreenCanvas( radius * 2, radius * 2 ); // width, height
    const ctx = canvas.getContext( '2d' );
    
    ctx.beginPath();
    ctx.arc(radius, radius, radius, 0, 2 * Math.PI);
    ctx.fillStyle = 'blue';
    ctx.fill();
    
    const v = await Canvg.from(ctx, svg, preset)
    await v.render()

    const blob = await canvas.convertToBlob()
    const pngUrl = URL.createObjectURL(blob)

    self.postMessage({
      pngUrl
    })
  }
</script>

<img />

另请参阅工作codepen

这也是在本机画布上绘制 SVG 的示例。

let svg = `<svg xmlns="http://www.w3.org/2000/svg" fill="#ff0000" width="320" height="320" viewBox="0 0 512 512"><path d="M256 0c17.7 0 32 14.3 32 32l0 10.4c93.7 13.9 167.7 88 181.6 181.6l10.4 0c17.7 0 32 14.3 32 32s-14.3 32-32 32l-10.4 0c-13.9 93.7-88 167.7-181.6 181.6l0 10.4c0 17.7-14.3 32-32 32s-32-14.3-32-32l0-10.4C130.3 455.7 56.3 381.7 42.4 288L32 288c-17.7 0-32-14.3-32-32s14.3-32 32-32l10.4 0C56.3 130.3 130.3 56.3 224 42.4L224 32c0-17.7 14.3-32 32-32zM107.4 288c12.5 58.3 58.4 104.1 116.6 116.6l0-20.6c0-17.7 14.3-32 32-32s32 14.3 32 32l0 20.6c58.3-12.5 104.1-58.4 116.6-116.6L384 288c-17.7 0-32-14.3-32-32s14.3-32 32-32l20.6 0C392.1 165.7 346.3 119.9 288 107.4l0 20.6c0 17.7-14.3 32-32 32s-32-14.3-32-32l0-20.6C165.7 119.9 119.9 165.7 107.4 224l20.6 0c17.7 0 32 14.3 32 32s-14.3 32-32 32l-20.6 0zM256 224a32 32 0 1 1 0 64 32 32 0 1 1 0-64z"/></svg>`;

(async () => {

  //desired width and height
  let width = 40;
  let height = 40;

  // set canvas dimensions
  canvas.width = width;
  canvas.height = height;

  // manual scale for SVG graphic
  let svgScale = 0.75;


  // parse to retrieve viewBox
  let svgEl = new DOMParser()
    .parseFromString(svg, "image/svg+xml")
    .querySelector("svg");

  // prefer viewBox - otherwise take width and height attributes
  let w = svgEl.viewBox.baseVal?.width || (svgEl.width.baseVal?.value || 300);
  let h = svgEl.viewBox.baseVal?.height || (svgEl.height.baseVal?.value || 150);


  // draw SVG on canvas
  let blob = new Blob([svg], {
    type: "image/svg+xml"
  });
  let blobURL = URL.createObjectURL(blob);

  let tmpImg = new Image();
  tmpImg.src = blobURL;
  tmpImg.width = w;
  tmpImg.height = h;
  tmpImg.crossOrigin = "anonymous";

  await tmpImg.decode();
  let ctx = canvas.getContext("2d");

  let radius = width / 2
  ctx.beginPath();
  ctx.arc(radius, radius, radius, 0, 2 * Math.PI);
  ctx.fillStyle = 'blue';
  ctx.fill();

  // calculate offsets to center SVG
  let offsetX = (width - width * svgScale) / 2
  let offsetY = (height - height * svgScale) / 2

  // scale SVG to desired dimensions and draw
  ctx.drawImage(tmpImg, offsetX, offsetY, width * svgScale, height * svgScale);
})();
<canvas id="canvas"></canvas>

© www.soinside.com 2019 - 2024. All rights reserved.