John Holcroft
John Holcroft

Reputation: 473

Vertical spacing issue with SVG graphic displayed in a UIWebView when using a viewBox

I'm trying to display an SVG graphic in a UIWebView for iOS. However with the images I am using the web view is adding large amounts of white space, 100s of pixels, above and below the graphic. Leading to the image being half of the screen vertically and you have to scroll to get it fully into view.

I've searched high and low on this issue and tried many, many things. I've got a 'good enough' workaround that I will share here. I'm asking this question in case anyone has a better fix and to help anyone else who encounters the same issue.

The real images I'm using are of sheet music generated by another tool (lilypond post processed by inkscape). However this simple rectangle which is twice as wide as it is tall shows the exact same issue.

<svg xmlns="http://www.w3.org/2000/svg" version="1.2" viewBox="0 0 20 10" width="100%" height="100%">
  <rect height="10" style="fill:currentColor" width="20" x="0" y="0" />
</svg>

If you view that in Safari or Chrome then it displays perfectly, filling the window and starting at the top. But in UIWebView it has this massive amount of white space above and below it. If you remove the viewBox attribute then the random extra white space disappears, but this isn't useful as then the graphic is miniscule. And anyway the SVG is correct. Calling [webView sizeThatFits:CGSizeZero] in webViewDidFinishLoad returns 1024x1120. Not 1024x512 as I would expect

In my case I get the UIWebView to display the raw SVG. Here are the things I have tried that have no effect.

A partial workaround is to add the attribute preserveAspectRatio="xMinYMin meet" in the svg tag.

<svg xmlns="http://www.w3.org/2000/svg" version="1.2" 
  preserveAspectRatio="xMinYMin meet" viewBox="0 0 20 10" width="100%" height="100%">
  <rect height="10" style="fill:currentColor" width="20" x="0" y="0" />
</svg>

That removes the excess whitespace at the top of the image, but leaves it at the bottom. It is only a partial workaround as though it initially looks right you can still scroll when you shouldn't be able to. Therefore I still need to disable scrolling to keep it looking right.

Any thoughts?

Upvotes: 3

Views: 2114

Answers (3)

Anton
Anton

Reputation: 2297

I've just had a similar problem. Somehow loading about:blank first helped…

Upvotes: 0

John Holcroft
John Holcroft

Reputation: 473

Part, but not all, of my problem was due to a mistake setting the UIWebView dimensions. I was trying to set the UIWebView to be full screen by using this code.

CGRect screenFrame = [UIScreen mainScreen].applicationFrame;
self.webView = [[UIWebView alloc] initWithFrame:screenFrame];
[self.webView setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight];

This turned out not to be right as the application frame is always returned in a portrait orientation and I was viewing in landscape. So the webview was set to be too tall and too thin, then it must have been auto-resized to be full width. Hence the massive vertical white space seem to have just been the image being centered.

However the issue with the excess vertical white space remains, just a lot less of it. So I'm sticking with my solution of adding preserveAspectRatio="xMinYMin meet" in the SVG.

Interesting new knowledge from trying out Chris Vander Mey's suggestions. These two calls for displaying the SVG are identical, except that loadData displays the image edge to edge, but loadHTMLString gives it the default padding.

[self.webView loadData:[svgContent dataUsingEncoding:NSUTF8StringEncoding]
              MIMEType:@"image/svg+xml" textEncodingName:@"UTF-8" baseURL:baseURL];

[self.webView loadHTMLString:svgContent baseURL:baseURL];

Upvotes: 1

Chris Vander Mey
Chris Vander Mey

Reputation: 461

I used your image and in iOS5.1 and 6 I can either get the image to fit fully or be top left justified. I did this with the

preserveAspectRatio="xMinYMin meet"

for the fit to the width & stick to the top, and for the fit-to-the-window:

preserveAspectRatio="xMinYMin slice"

In addition, to allow zooming, I embed the SVG inside HTML and add a meta tag. The initial-scale fits it to the viewport.

<meta name='viewport' content='initial-scale=1.0; user-scalable=1; maximum-scale=20.0'/>

For reference, you need to additionally set your webView to scalesPageToFit, and you'll need to set up your webView with the right mimeType. Like so:

webView.scalesPageToFit = YES;
[webView   loadData:[htmlPage dataUsingEncoding:NSUTF8StringEncoding]
           MIMEType:@"image/svg+xml"
   textEncodingName:@"UTF-8"
            baseURL:baseURL];

Final Top Tip: "xMidYMid" != "xMidyMid". You'll note that iOS 6.0 has no problem with the difference, but the spec says "xMidYMid" and that's what iOS 5.1 requires. See here.

Upvotes: 2

Related Questions