4

Solutions to similar questions involve CSS and the img tag.

However, I cannot use the <img src="myFile.svg"> because the SVG contains Angular directives, such as

  <path id="Top row 1" ng-click='RoomClicked($event, "A-1")'
        fill={{GetFillColour('A-1')}} stroke="black" stroke-width="1"
        d="M 226.00,69.00
           C 226.00,69.00 226.00,136.00 226.00,136.00  ...

So, I thought to have the SVG inline, in a view, and to size the SVG viewBox according to its its container, because (important) the whole idea is that I want to be able to display the web page at any resolution and have the SVG scale to fit it's parent DIV.

So, I tried

<div>
    <svg xmlns="http://www.w3.org/2000/svg"         
         viewBox="0 0 {{GetSvgDivHeight()}} {{GetSvgDivWidth()}}">

in my view, and

$scope.GetSvgDivHeight = function() 
{
   height = Math.round(screen.height * 0.8);

   return height;
}

$scope.GetSvgDivWidth = function() 
{
   width = document.getElementById('SVG_goes_here').offsetWidth;

   return width;
}

in my controller.

But, the SVG does not show, and the developer console shows

jquery-3.1.1.min.js:3 Error: <svg> attribute viewBox: Expected number, "0 0 {{GetSvgDivHeigh…".

So, 1) can I set the size of my in line SVG's viewBox programactically, from $scope? 2) if not, how can I make the inline SVG, containing Angular directives, fill its parent DIV, and resize if that DIV is resized?


[Update] InkScape generated

<svg xmlns="http://www.w3.org/2000/svg"
     width="7.22222in" height="10.0444in"
     viewBox="0 0 650 904">

when I change that to

<svg xmlns="http://www.w3.org/2000/svg"
     height="100%"
     viewBox="0 0 650 904">

The image fills the width of the containing DIV, but only the top half shows and the browser tab grows a vertical scroll bar.

Mawg says reinstate Monica
  • 38,334
  • 103
  • 306
  • 551

2 Answers2

4

viewBox describes which part of the SVG canvas to display. If, in SVG root coordinates, the left/upper border is at (0,0) and the right/lower at (300,200), set viewBox="0 0 300 200".

To set the display size of the SVG, use width and height. Setting both to 100% suffices to make it fit into the <div>. Even better, they are the default values, so you can leave them off. Note that HTML blocks have no intrinsic height, so you still need to restrict that to screen size.

If you start out with a external SVG that does not set viewBox, but (some of) x, y, width and height

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg xmlns="http://www.w3.org/2000/svg" width="300" height="200">

move them into the viewBox for the inline element, remove the width attribute and set the computed screen-related height:

<div style="position:relative;height:{{GetSvgDivHeight()}}">
    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 300 200">

or (Angular 1.x syntax)

<div>
    <svg xmlns="http://www.w3.org/2000/svg"
         ng-attr-height="{{GetSvgDivHeight()}}" viewBox="0 0 300 200">

The need for the ng-attr-height= workaround is explained here and was the reason for the original error message. For Angular 2+, use attribute binding: [attr.height]=

ccprog
  • 20,308
  • 4
  • 27
  • 44
  • 1
    That's the clearest description of the viewBox that I ever read. But, when I set the height to 100%, only the top half of the image showed. Please see the update to the question (at the bottom). Sounds like you can help me with a simple correction (fingers crossed). – Mawg says reinstate Monica Aug 08 '17 at 14:59
  • 1
    aah yes...divs have no intrinsic height...you'll have to set either the div or the SVG height. I'll edit my answer. – ccprog Aug 08 '17 at 15:06
  • It looked like we were getting closer ... But, now I am back to the original problem ` attribute height: Expected length, "{{GetSvgDivHeigh…".` in the browser console :-( – Mawg says reinstate Monica Aug 08 '17 at 15:19
  • 1
    return `height + "px"` from your function. Angular is pretty peculiar about what it considers to be valid HTML. – ccprog Aug 08 '17 at 15:28
  • It's returning `450px`, but I am still getting the same error :-( I don't understand that – Mawg says reinstate Monica Aug 08 '17 at 15:42
  • 1
    I've never used Angular v2+, but I've just seen [this](https://stackoverflow.com/questions/45571792) syntax: `[attr.height] ="fn()"` (stab in the dark) – ccprog Aug 08 '17 at 15:59
  • I ought to have said that I am using 1.6. Looks like I need to think in another direction - maybe HTML canvas. I really don't know. This is frustrating – Mawg says reinstate Monica Aug 08 '17 at 16:01
  • 1
    I think I found it: https://docs.angularjs.org/guide/interpolation#-ngattr-for-binding-to-arbitrary-attributes – ccprog Aug 08 '17 at 16:08
  • I think that you ***did*** find it !!!! Just as soon as the system allows a bounty, I shall award one. I take my head covering off to you, sir! – Mawg says reinstate Monica Aug 08 '17 at 16:19
2

The bounty has (quite rightly) been awarded, but adding this answer as a resolution in my case wasn't immediately clear.

In my case, the ng-attr-viewBox was being inappropriately lower-cased. The solution for this is described here, and repeated here for posterity.

If one wants to modify a camelcased attribute (SVG elements have valid camelcased attributes), such as viewBox on the svg element, one can use underscores to denote that the attribute to bind to is naturally camelcased.

For example, to bind to viewBox, we can write:

<svg ng-attr-view_box="{{viewBox}}"> </svg>

ne1410s
  • 6,864
  • 6
  • 55
  • 61