Closed necolas closed 9 years ago
Or perhaps provide another option like transformSvg
but to operate on a per-icon basis, rather than the output svg. If the name was more generic then it could be used for purposes other than the specific metadata extraction I need.
Can you provide an example of what you want to achieve? Each symbol tag in combined svg has viewBox so you don't need to specify it for svg element that uses symbol.
On 18 Oct 2014, at 00:38, Nicolas Gallagher notifications@github.com wrote:
In order to use the output correctly for SVG's that have variable widths, you need to include the viewBox in the HTML:
What do you think about this plugin writing icons.json or similar, with name: viewbox pairs, so that downstream tools or a server can have access to the correct viewBox value for each icon.
— Reply to this email directly or view it on GitHub.
transformSvg is hacky indeed, I introduced it because I didn't want to bloat plugin with lots of options. Ideally, transformSvg should be another gulp plugin, so we would be able to use it for sources and for the result svg.
I don't have a full internet connection, but perhaps there is already some kind of gulp plugin that lets you manipulate xml files.
On 18 Oct 2014, at 01:04, Nicolas Gallagher notifications@github.com wrote:
Or perhaps provide another option like transformSvg to operate on a per-icon basis, rather than the output svg. If the name was more generic then it could be used for purposes other than the specific metadata extraction I need.
— Reply to this email directly or view it on GitHub.
Each symbol tag in combined svg has viewBox so you don't need to specify it for svg element that uses symbol.
That isn't correct. The css-tricks article is wrong about that. If your icons have variable width, then you need to include the viewbox on each reference to the combined svg if you want the icon to scale proportionally.
I ended up writing a script rather than using gulp and this plugin. But there is an inherit limitation to this technique if you don't also have knowledge of the viewbox values.
Interesting! Would be cool if you could craft an example of the icon that scales proportionally. I was only able to do it using percentage padding trick on the container to set the ratio and then using absolute position for svg inside.
On 18 Oct 2014, at 20:25, Nicolas Gallagher notifications@github.com wrote:
Each symbol tag in combined svg has viewBox so you don't need to specify it for svg element that uses symbol.
That isn't correct. The css-tricks article is wrong about that. If your icons have variable width, then you need to include the viewbox on each reference to the combined svg if you want the icon to scale proportionally.
— Reply to this email directly or view it on GitHub.
What you need is:
<!-- 'viewBox' preserves the correct width/height ratio -->
<svg class="icon" title="{{name}}" viewBox="{{viewBox}}">
<!-- 'fill="currentcolor"' allows for simpler color styling -->
<use fill="currentcolor" xlink:href="#icon-{{name}}"></use>
</svg>
Then you can use CSS to control size and color:
.Icon {
/* setting the color doesn't require use of 'fill' */
color: green;
/* proportional scaling only requires height to be set */
height: 1em;
}
Setting the correct viewBox
for each svg
isn't a problem if you're using a templating system / ui-component architecture. But it's a pain if you're building your markup by hand. It seems to be the only way to use properly SVG icons that don't all use a fixed width/height ratio.
@necolas thanks! I have to check if this works in all of the browsers. Right now it is possible to solve your problem with current api, inside transformSvg
function.
var jsonData = $svg.children('symbol').map(function () {
return {
name: $(this).attr('id'),
viewBox: $(this).attr('viewBox')
}
}).get()
Will produce jsonData similar to this:
[ { name: 'icon-circle', viewBox: '0 0 40 40' },
{ name: 'icon-square', viewBox: undefined } ]
I'm not going to close this issue, and will think of a better solution to this problem.
I have done something similar lately, and ended up writing separate plugin for it (unfortunately private). The only missing thing was the ability to push new file down the stream from transform function.
If the stream object (or its push function) could be passed into the transform function, it would allow to generate files on the fly and push them down the stream along with svg.
For now as a workaround you can push it down the other, previously prepared stream and join then at the end with event-stream's es.merge().
@Frizi its not hard to implement, just change transform call to transformSvg.call(this, $combinedSvg, done)
and you'll be able to call this.push
from within transformation function. But I'm not sure if it is nice as an api.
@necolas @Frizi I added an example of how to extract viewboxes from combined svgs: https://github.com/w0rm/gulp-svgstore#extracting-metadata-from-combined-svg
This is now possible because gulp-svgstore caches cheerio in gulp file object.
If you need to extract from svg sources, then you may do the same with gulp-cheerio, pipe it to through2, collect data in transform
function and write result json in flush
function.
Cool. We wrote our own script to accommodate various requirements, but this will be useful for normal projects. Thanks!
@necolas transformSvg wasn't a good idea in the first place, gulp-cheerio combination seems to be much better. It doesn't degrade performance, because cached file.cheerio
is used instead of parsing file multiple times.
In order to use the output correctly for SVG's that have variable widths, you need to include the
viewBox
in the HTML:What do you think about this plugin writing
icons.json
or similar, withname: viewbox
pairs, so that downstream tools or a server can have access to the correctviewBox
value for each icon.