Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use imported SVG to render base SVG element to avoid nesting complexity #17

Open
ollicle opened this issue Jul 9, 2013 · 18 comments
Open

Comments

@ollicle
Copy link

ollicle commented Jul 9, 2013

Would be an improvement to provide a way to use the rawSVG import mechanism to render the initial SVG() element.

Nested SVG elements provide additional complexity when it comes to controlling how they resize and fill available space in a responsive layout.

Some background: I’m using svg.js with svg.import.js to display and animate elements SVG stored in independent .svg files. This allows the SVG elements to be loaded asynchronously or alternatively a .png in non-supporting browsers.

@wout
Copy link
Member

wout commented Jul 9, 2013

I've been thinking about that too. I fact I am planning on writing a plugin called svg.adopt.js, which does exactly that. But no ETA I'm afraid as I'm extremely busy at the moment.

@ollicle
Copy link
Author

ollicle commented Jul 9, 2013

That would be cleaner. I expect many scenarios would call for multiple file imports in which case nested obviously makes sense.

In the meanwhile I am setting the width and height of my imported SVG file to 100%. Seems to have resolved my scaling issues.

@mspanish
Copy link

Hello I realize the main author is swamped and can't be expected to be producing free plugins for the rest of us all the time, but has anybody made any progress on this? Importing to a nested SVG produces some side effects that I don't want in my project - so I'd love to be able to replace the original SVG with the import rather than adding a nested one. Thanks in advance if anyone can help :)

@wout
Copy link
Member

wout commented Jan 13, 2014

You could try with this JS shim: https://github.com/phaistonian/SVGInnerHTML/blob/gh-pages/svginnerhtml.js

It enables innerHTML on svg elements.
I haven't tested it myself so let me know how it goes. :)

@mspanish
Copy link

Hey thanks - tried this but perhaps I don't have the syntax right - I can't replace all 'svg' tags as I have more than one svg on the page - I tried

$.get('/data/default.svg', function(raw_svg){
// console.log( raw_svg );
var svgy = document.getElementById('svga-svgcanvas');

svgy.innerHTML = raw_svg;

But the innerHTML from the shim isn't getting called - (I've got a console.log in there on the node removal function that isn't getting fired...)

Was thinking to try D3.js - although that's a huge library to be including just for this!

So far using svg.import.js does in fact work to import the external svg, and make it editable via svg.js. The defs not being in the correct spot is really the only problem - and my script uses the info in that defs for several coloring things.

Getting closer though, as yesterday it looked like importing and editing an external SVG using the groups already defined via svg.js would not be possible :)

@mspanish
Copy link

by the way using innerHTML on the SVG does work for displaying an external SVG image - but it's the same as just replacing the whole thing with jQuery's html() - the resulting SVG paths can't be edited by svg.js even though the raw SVG code is the same as the code being produced by the character creator I have that uses svg.js (the SVG i'm importing was created by svg.js and saved by my app to begin with).

@mspanish
Copy link

ah and by innerHTML I mean vanilla javascript, as I don't think I have the shim working right yet

@wout
Copy link
Member

wout commented Jan 13, 2014

Here is an idea, why loading the entire svg image and embed it if you are not going to use its contents for interaction anyway. It might be easier to just load it as an external image:

var draw = SVG('canvas')
var image = draw.image('/images/fabulous.svg')

@mspanish
Copy link

Ah but I am using it :) I use each one of the parts or groups (head, mouth, eyes, hair, etc) to change out graphics. Each group is marked by g tags like this: <g id="svga-face". The app uses the path data to color different things like inside of lips, skin, etc.

@mspanish
Copy link

hey right now the svg.import.js appends the defs to the parent svg and not the newly created svg from the raw import - is there a way to append this instead to the new svg (child) and not the primary (parent)?

@mspanish
Copy link

I think the problem is actually with the construction of the defs from the importer - not sure why it ignores some of the attributes - but here is an example from defs that I'm trying to import:

<radialGradient id="SvgjsRadialGradient1391" cx="100" cy="114" r="41" gradientUnits="userSpaceOnUse" class="svga-on-canvas-facehighlight-gradient-single-0">
    <stop id="SvgjsStop1392" stop-opacity="0.5" stop-color="#e9bfa9" offset="0" data-stoptype="hl1"></stop>
    <stop id="SvgjsStop1393" stop-opacity="0" stop-color="#daa488" offset="0.9" data-stoptype="tone"></stop>
</radialGradient>

And here is what the svg.import.js produces:

<radialGradient id="SvgjsRadialGradient1391" class="svga-on-canvas-facehighlight-gradient-single-0" gradientUnits="userSpaceOnUse" r="41" cy="114" cx="100">
    <stop id="SvgjsStop1131" offset="0"></stop>
    <stop id="SvgjsStop1132" offset="0.9"></stop>
</radialGradient>

@wout
Copy link
Member

wout commented Jan 14, 2014

Right, there was a problem with the attributes on stops (they weren't applied). That's fixed now. Could you let me know how goes?

@mspanish
Copy link

Yes guess what it's now working! Full editing of my avatars created by, saved, then re-imported by svg.import.js. I had to change this to add the stops correctly:

case 'radialgradient':
element = context.defs().gradient(type.split('gradient')[0], function(stop) {
for (var j = 0; j < child.childNodes.length; j++) {
console.log('radial child is '+JSON.stringify(objectifyAttributes(child.childNodes[j])))
convertNodes(child.childNodes[j], element, level + 1, store, block)
}
})
break

@mspanish
Copy link

Just so you know I didn't try your new file yet - my post refers to the older file - that's what I got working. Will try your file tomorrow. Thanks so much for your help, this is really awesome - only wish you had the svg.adopt.js ready :) If you need a tester for that, I'd be glad to try it out whenever you are ready.

@wout
Copy link
Member

wout commented Jan 14, 2014

You'll see it appearing quite soon ;)

@mspanish
Copy link

One issue I'm having with the importer - it's overwriting my group id's with its own - this group here:

<g id="svga-group-wrapper" transform="scale(1 1)">
    <g id="svga-group-backs-single">

is being imported and converted to this:

    <g id="SvgjsDefs8425">
        <g id="svga-group-backs-single">

Do you know where the importer is doing this?

@wout
Copy link
Member

wout commented Jan 14, 2014

That's not right indeed. The attr method on line 119 (https://github.com/wout/svg.import.js/blob/master/svg.import.js#L119) should overwrite default id's. Additionally, the id is a defs id (SvgjsDefs8425) because a group id would be SvgjsG8425. Not quite sure how this could happen...

On another note, maybe it would be better to open a new issue as it is totally unrelated to the initial topic. :)

@mspanish
Copy link

Ah sure thanks for that I'll throw in some statements to see what is happening, and open a new ticket with any new info!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants