SVG nine-slice scaling - svg

How could one obtain nine-slice scaling in SVG?
Specifically, I'm looking for a way to define SVG objects that behave like nine-sliced objects when resized (some elements maintain their dimension, and others scale with the container).

If you meant to apply it to an svg, then the CSS3 Borders and backgrounds spec should help you do that if you reference an svg.
If you meant you wanted to do it inside an svg file, then you might be able to use a <pattern> (possibly combined with some nested <svg> elements) to do something similar. Nested <svg> elements might be another way to do this, see e.g this example. Alternatively use 9 <use> elements with different transforms, each having a different clip-path applied.

You need something like a margin around the elements that form the edges and the center, to tell them to start X pixels from the left/top to y pixels from the right/bottom. Use a foreignObject, like this:
<foreignObject width="100%" height="100px">
<div xmlns="http://www.w3.org/1999/xhtml" style="margin: 0 100px;">
<svg>
<!-- code here -->
</svg>
</div>
</foreignObject>
I wrote about methods of applying scaling grids to SVG here: http://w3.eleqtriq.com/2014/03/the-holy-grail-of-image-scaling/
Cheers, Dirk

Related

Making screen-readers read out <text> items in SVG graphics?

I've searched all over the place and not have any success with this.
I'm making SVGs like the following one in order to make them scalable, and also help people who are dyslexic so they can highlight the text and use plugins like Read Out Loud:
https://www.ole.bris.ac.uk/bbcswebdav/institution/TEL/TEL%20guides/Published%20TEL%20guides/Replay/record-now-instructions-web.svg
But I've not been able to get my copy of NVDA to read out the tab-indexed fields as I tab through them. I've tried fields and aria-label on various things...
Is there something simple I can change so NVDA (and similar screen readers) will read out the text as I tab through (NVDA does this on HTML pages).
Or should I just put the full description of all the text in my description at the top?
I noticed you have role="img" in your svg root. That's borking everything, since it tells the accessibility API that it is just a single element, whose accessible name is always aria-labelledby="svgTitle svgDesc"
Try changing that to role="graphics-document" (or perhaps role="application" if you want fancier interactions) and I think you'll have a whole lot more luck.
The other option is to remove the role attribute from the <svg> element. It sounds counterintuative, but it should make any <text> elements accessible.
For an example, see tip 5 in this SitePoint article, which has great background and other helpful tips on making SVG more accessible in different use cases:
Tips for Creating Accessible SVG
From the above article:
<svg version="1.1" width="300" height="200" aria-labelledby="title desc">
<title id="title">Green rectangle</title>
<desc id="desc">A light green rectangle with rounded corners and a dark green border.</desc>
<rect width="75" height="50" rx="20" ry="20" fill="#90ee90" stroke="#228b22" stroke-fill="1" />
<text x="35" y="30" font-size="1em" text-anchor="middle" fill="#000000">Website</text>
</svg>

Aurelia generated SVG elements are invisible when using custom elements

Why are custom elements in SVG invisible?
Composing Svg with Aurelia is similar to composing html. You have to make sure though that any custom elements are implemented containerless (either by decorating the ViewModel with the `#containerless' attribute or adding an attribute 'containerless' to the custom element tag. SVG is picky about elements that are not defined in the specification and attributes that have the wrong value type.
Even if you have taken care of making them containerless it is still possible the custom elements do not show, even though they are added to the DOM.
Checkout this GistRun. You would expect two white rectangles, that are present in the DOM, above the other elements. But they are not visible.
The reason the elements do not show is because of the comments Aurelia uses to track element positions (<!--<view>-->). You can avoid this issue by wrapping your elements in a SVG tag:
<template>
<svg>
...
</svg>
</template>
See this Gistrun for a working result.
Edit: Be sure to add an attribute overflow="visible" if you dont want the inner elements to be clipped by the SVG element:
<template>
<svg overflow="visible">
...
</svg>
</template>
More info in the Aurelia cheat sheet :
http://aurelia.io/hub.html#/doc/article/aurelia/framework/latest/cheat-sheet/9

Where to put <style> inside SVG?

Sorry if that might come an opinion-based, but I hope there's a right answer..
Where an inline CSS style should be placed inside an SVG document? In the
example I provide below I have defined two styles and a circle that uses them.
The first style is defined inside defs tag and the second styles is defined right inside the svg tag.
Both styles are successfully displayed on the circle (at least in Chrome they do, didn't check other browsers though).
My question is which way is more standard?
I think keeping styles in defs keeps the whole SVG more tidy. However, one can claim that I should not use defs tag since no one references the style with <use>
Thanks!
<svg height="100" width="100">
<defs id="someDefs">
<style id="style1">
.blue-fill {
fill : blue;
}
</style>
</defs>
<style id="style2">
.red-stroke {
stroke : red;
stroke-width : 12
}
</style>
<circle cx="50" cy="50" r="40" class="blue-fill red-stroke" />
</svg>
It doesn't matter. Neither approach is "more standard". <style> elements are not renderable anyway, so there is no real need to put them in the <defs> section
As commented by Paul LeBeau.
After reading this article about style on MDN, that shows an example of a style simply under the SVG root, I am more convinced it is correct to put <style> there rather than under <defs>.
Also, since <defs> tag is indeed for reusable graphical elements that should be rendered, and <style> is not a renderable element, there's no point keeping it there.
Graphical elements defined in <defs> are not rendered directly and will be rendered only with use. Hence it is always a good practice to use <defs> if the graphical object is defined for later use. It also increases the readability of the code.
More Information

SVG shape rendering dots appears

I'm making SVG effects by combining 2 identical photos with alternate slits. When you look closely, there are dotted lines 45 degree across the whole images. Referencing this question, I already tried the option shape-rendering="optimizeQuality", shape-rendering="geometricPrecision" and shape-rendering="auto" on <polygon> tags, but the dots still appears.
How do I remove the tiny dots?
Partial HTML codes (full code is too long to post here, see JSFiddle below for full CSS, JS and HTML codes):
<div class="image_wrapper">
<svg id="svg-1" class="clip-svg">
<image class="svg-image" xlink:href="http://cdn.idigitaltimes.com/sites/idigitaltimes.com/files/styles/image_embed/public/2016/09/28/pen-pineapple-apple-pen-meaning-lyrics-ppap-piko-taro-youtube-video-watch-how-do_1.jpg" width="640" height="360" />
</svg>
</div>
<div class="image_wrapper2">
<svg id="svg-2" class="clip-svg">
<image class="svg-image" xlink:href="http://cdn.idigitaltimes.com/sites/idigitaltimes.com/files/styles/image_embed/public/2016/09/28/pen-pineapple-apple-pen-meaning-lyrics-ppap-piko-taro-youtube-video-watch-how-do_1.jpg" width="640" height="360" />
</svg>
</div>
JSFiddle demo is here
The dots are caused by anti-aliasing of the polygons that you are using for the diagonal slit clipping paths.
IMO there isn't any way to prevent that. It may or may not get better if you turn anti-aliasing off with `shape-rendering="optimizeSpeed". And even if that works on one browser, it may not work on other ones.
My suggestion is to just have a complete ("un-slitted") version of the image on top. Make it invisible initially, then show it once the animation has finished.

Stretch <svg> inside an <embed> to fit window size

I am trying to stretch an svg document inside an DOM in order to fit the window size.
like so:
<div id="y">
<div id="button"> click to zoom</div>
<embed id="x" src="s17.svg" >
<script>
var btn= document.getElementById("button");
btn.addEventListener('click',function(){
var z= document.getElementsByTagName("embed")[0];
var y = z.getSVGDocument();
y.lastChild.setAttribute("viewBox","0 0 "+window.innerWidth+" "+window.innerHeight);
},false);
</script>
</div>
css:
#x{
height:100%;
width:100%;
overflow:hidden;
}
#y{
position:absolute;
top:0;
bottom:0;
left:0;
right:0;
overflow:hidden;
}
This isn't working... What am I doing wrong?
All browsers should be able to handle this just fine:
add a viewBox to the svg element (s17.svg in your example) without using script if possible
remove the width and height attributes on the svg element if they are specified
add an attribute preserveAspectRatio="none" to the svg element to make it stretch even if the css-viewport aspect ratio doesn't match the viewBox aspect ratio.
set the width/height of the embed/iframe/object to whatever you want and the svg will automatically stretch to fit
If you don't want stretching then you can also do preserveAspectRatio="xMidYMid slice" (fill whole viewport, slicing away parts if necessary) or preserveAspectRatio="xMidYMid meet" (this is the default, center the svg in the viewport and maintain the aspect ratio).
All browsers handle SVG support completely differently. I think your best bet is to use an object tag instead of embed, and you still have to do some hacking to get it to look right on each browser. This link and this link have some useful information for getting it to work cross-browser.

Resources