anvaka / VivaGraphJS

Graph drawing library for JavaScript
Other
3.76k stars 426 forks source link

getting real size of images to decorate links #31

Closed xdiscovery closed 11 years ago

xdiscovery commented 11 years ago

Hello! I want to decorate nodes with images, and position the label of my nodes at the bottom of images. The images I get can be different in size.

I would like to than pass the image Width, height to the svg node, once I get the source url of img; than pass this value to the svg tag (at least, this is what I've learnt here:

http://stackoverflow.com/questions/6884513/how-to-get-the-real-unscaled-size-of-an-embedded-image-in-the-svg-document http://stackoverflow.com/questions/318630/get-real-image-width-and-height-with-javascript-in-safari-chrome

I am using indeed the solution above, but I noticed that with the method described at http://stackoverflow.com/questions/6884513/how-to-get-the-real-unscaled-size-of-an-embedded-image-in-the-svg-document sometimes images cannot load in time: it is like i should wait to load for them, and then attach them.

This behavior does not happen when getting the src Img directly with ui.append('svg') .link(srcIMG).

Is there something I am mismatching or doing wrong? Also, is there the possibility to apply the loaded image directly on svg ? I think I am loading twice the same image ...

Here's my method I would like to discuss with you!

svgGraphics.node(function(node){
    // This time it's a group of elements:http://www.w3.org/TR/SVG/struct.html#Groups
        var groupId = node.data.group;
    // set img dimensions
        var imgCover = new Image();
        var imgLink = node.data.linkOfTheImg;
        imgCover.src = imgLink;
        var imgW = imgLink.width, imgH=imgLink.height;
    //then
        img = Viva.Graph.svg('image')
        .attr('width', imgW)
        .attr('height', imgH);
    //decorate svg
        ui.append('defs')
        .append('pattern')
        .attr('id','nodeImg')
        .attr('patternUnits','userSpaceOnUse')
        .attr('x',nodeSize/2-imgW/2+'px')
        .attr('y',nodeSize/2-imgH/2+'px')
        .attr('width',imgW)
        .attr('height',imgH)
        .append(img);
    //apply img
        ui.append('rect').
        .attr('fill','url(#nodeImg)')
}
xdiscovery commented 11 years ago

I also tried to work out with this solution but didn't help for me yet... (http://stackoverflow.com/a/5933319/305883)

function FULL_IMAGE(fimage) { var loaded = false; function loadHandler() { if (loaded) { return; } loaded = true; } var img = new Image(); img.onload = loadHandler; img.src = fimage; img.style.display = 'block'; if (img.complete) { loadHandler(); return (img.width, img.height); } }

anvaka commented 11 years ago

Here is a demo: http://jsfiddle.net/anvaka/nK75s/ It loads detached DOM image and only then sets the link to svg image.

I'm not sure why Google Chrome does not fire load event as described here for SVG images. Firefox does fire it.

Anyways solution with plain DOM images worked in both browsers. I wouldn't worry too much about loading the same image twice - browsers normally will not make additional request for the same resource, and reuse what they have. In the JS Fiddle above Chrome indeed does only one request for each image.

gg4u commented 11 years ago

thank you man! I've just seen your answer only now!

anvaka commented 11 years ago

Glad it worked :)