Auto-resize SVG inside AngularJS directive based o

2019-04-01 18:40发布

问题:

I am placing an angular directive inside a dynamically-sized element. The directive itself consists of an SVG which is computed based on the element size. I am trying to make the SVG auto-resize and redraw based on the size of the container.

I initially tried something like this:

my-directive.js

angular
    .module('myModule')
    .directive('myDirective', function () {
        return {
            templateUri: 'path/to/my-directive-template.html',
            ...
        };
    });

my-directive-template.html

<svg style="width: 100%; height: 100%; max-width: 100%; max-height: 100%">
    ...
</svg>

Note the style attributes on that SVG element. This resizes correctly in Chrome, but fails to work in Firefox. Also, I still don't have a hook to recalculate the SVG contents.

I've also tried adding an onresize handler to the element in the link function, However, JQLite supports onresize only on the main window. I cannot use window.onresize, because my window size does not change.

I've tried to use the answers here: AngularJS - bind to directive resize, but they don't give the required results either.


In short, here's what I am trying to do:

  1. Resize the SVG element inside the directive when the parent element resizes.
  2. Re-calculate the SVG contents by calling some handler function when this happens.

I would prefer not to add a JQuery dependency at this point in the project.

回答1:

This behavior can be achieved using the viewBox and preserveAspectRatio attributes of the <svg> tag.

First, set the viewBox attribute to a normalized bounding box for your SVG image. Your entire drawing should be scaled to fit inside this view box. For example,

viewBox="0 0 100 100"

will set up a coordinate system with the origin at (0, 0) and having the dimensions 100 units x 100 units.

Next, set the resizing behavior using the preserveAspectRatio attribute.

The first part of the value determines the alignment of the SVG with respect to the parent element. This includes left/right/center horizontal alignment and top/bottom/middle vertical alignment. For example,

preserveAspectRatio="xMidYMid ..."

will align the SVG centrally in its container.

The second part of the value determines how the SVG fills the container. For example,

preserveAspectRatio="... meet"

will scale the SVG such that it just fits within the container without cropping.

So the complete example becomes:

<svg viewBox="0 0 64 64" preserveAspectRatio="xMidYMid meet">
    ...
</svg>

Because the image scales automatically with the container, there is no need to recalculate the positions of the content elements. It is handled automatically by the SVG tag.