-->

SVG Foreign Object sizing inconsistent

2019-07-18 12:24发布

问题:

I'm trying to make 2 html objects in SVGs and further use them inside Vis.js graphs. My first svg (Button) works as intended and looks good. My problem is that when I try to insert the table div the width/height are not what I have set them to be.

Here's what I get:

As you can see the button is larger than the red box even though the red box has a larger width and height (1000px x 800px versus 220px x 68px)!

Here's my JavaScript:

// THE RED BOX
const tableComponent =
`<svg xmlns="http://www.w3.org/2000/svg" width="1000px" height="800px">
<foreignObject x="0" y="0" width="100%" height="100%">
<div xmlns="http://www.w3.org/1999/xhtml" style="height: 100%; width: 100%; background-color: red;">
  <p>Here is a paragraph that requires word wrap</p>
</div>
</foreignObject>
</svg>`;

// THE ORANGE BUTTON
const buttonComponent =
  `<svg xmlns="http://www.w3.org/2000/svg" width="220px" height="68px">
  <foreignObject x="0" y="0" width="100%" height="100%">
  <div xmlns="http://www.w3.org/1999/xhtml" style="height: 100%; width: 100%;">
    <button style="width: 100%; height: 100%; font-size: 20px; color: white; background-color: #FF9700; border-radius: 8px; border: none;">Order Filling</button>
  </div>
  </foreignObject>
  </svg>`;


const tableComponentUrl = "data:image/svg+xml;charset=utf-8," + encodeURIComponent(tableComponent);
const buttonComponentUrl = "data:image/svg+xml;charset=utf-8," + encodeURIComponent(buttonComponent);

const nodes = new DataSet([
  { id: 1, image: buttonComponentUrl, shape: 'image' },
  { id: 2, image: tableComponentUrl, shape: 'image' },
  { id: 3, label: 'Node 3', shape: 'box' }
]);
// create an array with edges
const edges = new DataSet([
  { from: 1, to: 2, arrows: 'to' },
  { from: 1, to: 3, arrows: 'to' }
]);
// create a network
const container = document.querySelector('.data-source-container');
const data = {
  nodes: nodes,
  edges: edges
};
const options = {
  edges: { smooth: false }
};
const network = new Network(container, data, options);

回答1:

Well, SVG is scalable vector graphics, the inner sizes has nothing to do with the sizes a user sees (more accurately: x dimensions of objects that user sees are x_orig*scale where x_orig is the x dimension inside SVG and scale is a factor set by the x dimension of the whole SVG element).

In other words (assuming the other parts work and if they do, you have invented an interesting hack to extend vis.js' possibilities of inserting html) you have to set the dimensions of your pictures. Try to use size, scale or shapeProperties.useImageSize in corresponding nodes' options. I can't see an option to adjust aspect ratio, though, so this may require additional tweaking inside SVG itself (like setting its dimensions even).

Let me know how it goes, that's quite an interesting approach that you have.