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

Way to use external svg file #28

Open
vortice3D opened this issue Jun 18, 2018 · 7 comments
Open

Way to use external svg file #28

vortice3D opened this issue Jun 18, 2018 · 7 comments

Comments

@vortice3D
Copy link

vortice3D commented Jun 18, 2018

Hi there Ian:

We're using your excellent pan-zoom framework in a development which manages assets in a side-by-side basis, using PNGs and SVGs. Of course, PNG's part is piece of cake, but I'm having problems in the SVG part.

Our SVGs are external files, wich we need to "ajax" in order to have the advantage of media-caching and the ability to tweak styles through CSS (not inline SVG or img translation are covered here).

This way We're "ajaxing" the SVG under the general algorithm to insert an external SVG in an HTML page:

var ajax=new XMLHttpRequest();
ajax.onload=function(e){
  try{
    document.body.insertBefore(ajax.responseXML.documentElement,document.body.childNodes[0]);
  }
  catch(e){
    console.log(e);
  }
};
//
ajax.open("GET",path,true);
ajax.responseType="document";
ajax.send();

The case is that under this approach I'm creating a node with all the header , symbols, etc..., and I suspect the overlay.node() SVG surface is waiting for SVG primitives only. So we had to parse our SVGs and add the different elements (path, rect, line, ...) one after the other. Isn´t it?

Best regards.

@iangilman
Copy link
Member

Yes, this plugin creates its own SVG object:

https://github.com/openseadragon/svg-overlay/blob/master/openseadragon-svg-overlay.js#L34

One approach would be to pull the elements you want out of the SVG object you're loading via ajax and stuffing those into the SVG object the plugin creates. If you nest everything inside of a g, that could be quite straight forward.

Another option would be to modify this plugin so you can pass in an SVG element for it to use instead. The plugin is very small, so it should be an easy code change if you want to go that way, and I'd be happy to merge such a patch if you wanted to make a pull request.

@vortice3D
Copy link
Author

vortice3D commented Jun 18, 2018

Hi Ian:

Well I prefer to use the first approach , that is, to parse the SVG file pulling out the contents I need to draw.

Anyway, trying to implement that is not working:
overlay.node().appendChild(xhr.responseXML.documentElement.getElementById("bird"));
(where "bird" is the name of a svg path):

But following the same technique using a regular html svg element, (svgBlock) as container, instead overlay.node(), perfectly works:
document.getElementById("svgBlock").appendChild(xhr.responseXML.documentElement.getElementById("bird"))

Any help on this?

Best regards.

@vortice3D
Copy link
Author

vortice3D commented Jun 19, 2018

Hi Ian:

I can see that when using the xhr.response directly to a svg block (not OSD at all), my code looks like this:
<svg id="svgContent" class="openseadragon1"><path id="bird" d="M210.333,65.331C104.367,66.105-12.349,150.637,1.056,276.449c4.303,40.393,18.533,63.704,52.171,79.03 c36.307,16.544,57.022,54.556,50.406,112.954c-9.935,4.88-17.405,11.031-19.132,20.015c7.531-0.17,14.943-0.312,22.59,4.341 c20.333,12.375,31.296,27.363,42.979,51.72c1.714,3.572,8.192,2.849,8.312-3.078c0.17-8.467-1.856-17.454-5.226-26.933 c-2.955-8.313,3.059-7.985,6.917-6.106c6.399,3.115,16.334,9.43,30.39,13.098c5.392,1.407,5.995-3.877,5.224-6.991 c-1.864-7.522-11.009-10.862-24.519-19.229c-4.82-2.984-0.927-9.736,5.168-8.351l20.234,2.415c3.359,0.763,4.555-6.114,0.882-7.875 c-14.198-6.804-28.897-10.098-53.864-7.799c-11.617-29.265-29.811-61.617-15.674-81.681c12.639-17.938,31.216-20.74,39.147,43.489 c-5.002,3.107-11.215,5.031-11.332,13.024c7.201-2.845,11.207-1.399,14.791,0c17.912,6.998,35.462,21.826,52.982,37.309 c3.739,3.303,8.413-1.718,6.991-6.034c-2.138-6.494-8.053-10.659-14.791-20.016c-3.239-4.495,5.03-7.045,10.886-6.876 c13.849,0.396,22.886,8.268,35.177,11.218c4.483,1.076,9.741-1.964,6.917-6.917c-3.472-6.085-13.015-9.124-19.18-13.413 c-4.357-3.029-3.025-7.132,2.697-6.602c3.905,0.361,8.478,2.271,13.908,1.767c9.946-0.925,7.717-7.169-0.883-9.566 c-19.036-5.304-39.891-6.311-61.665-5.225c-43.837-8.358-31.554-84.887,0-90.363c29.571-5.132,62.966-13.339,99.928-32.156 c32.668-5.429,64.835-12.446,92.939-33.85c48.106-14.469,111.903,16.113,204.241,149.695c3.926,5.681,15.819,9.94,9.524-6.351 c-15.893-41.125-68.176-93.328-92.13-132.085c-24.581-39.774-14.34-61.243-39.957-91.247 c-21.326-24.978-47.502-25.803-77.339-17.365c-23.461,6.634-39.234-7.117-52.98-31.273C318.42,87.525,265.838,64.927,210.333,65.331 z M445.731,203.01c6.12,0,11.112,4.919,11.112,11.038c0,6.119-4.994,11.111-11.112,11.111s-11.038-4.994-11.038-11.111 C434.693,207.929,439.613,203.01,445.731,203.01z"></path></svg>

And when I load it on the OSD overlay (overlay.node()), it is the following:
<svg style="position: absolute; left: 0px; top: 0px; width: 100%; height: 100%;" width="1222" height="982"><g transform="translate(-371.94953627932824,-119.01136570285395) scale(1837.0000000000002) rotate(0)"><path id="bird" d="M210.333,65.331C104.367,66.105-12.349,150.637,1.056,276.449c4.303,40.393,18.533,63.704,52.171,79.03 c36.307,16.544,57.022,54.556,50.406,112.954c-9.935,4.88-17.405,11.031-19.132,20.015c7.531-0.17,14.943-0.312,22.59,4.341 c20.333,12.375,31.296,27.363,42.979,51.72c1.714,3.572,8.192,2.849,8.312-3.078c0.17-8.467-1.856-17.454-5.226-26.933 c-2.955-8.313,3.059-7.985,6.917-6.106c6.399,3.115,16.334,9.43,30.39,13.098c5.392,1.407,5.995-3.877,5.224-6.991 c-1.864-7.522-11.009-10.862-24.519-19.229c-4.82-2.984-0.927-9.736,5.168-8.351l20.234,2.415c3.359,0.763,4.555-6.114,0.882-7.875 c-14.198-6.804-28.897-10.098-53.864-7.799c-11.617-29.265-29.811-61.617-15.674-81.681c12.639-17.938,31.216-20.74,39.147,43.489 c-5.002,3.107-11.215,5.031-11.332,13.024c7.201-2.845,11.207-1.399,14.791,0c17.912,6.998,35.462,21.826,52.982,37.309 c3.739,3.303,8.413-1.718,6.991-6.034c-2.138-6.494-8.053-10.659-14.791-20.016c-3.239-4.495,5.03-7.045,10.886-6.876 c13.849,0.396,22.886,8.268,35.177,11.218c4.483,1.076,9.741-1.964,6.917-6.917c-3.472-6.085-13.015-9.124-19.18-13.413 c-4.357-3.029-3.025-7.132,2.697-6.602c3.905,0.361,8.478,2.271,13.908,1.767c9.946-0.925,7.717-7.169-0.883-9.566 c-19.036-5.304-39.891-6.311-61.665-5.225c-43.837-8.358-31.554-84.887,0-90.363c29.571-5.132,62.966-13.339,99.928-32.156 c32.668-5.429,64.835-12.446,92.939-33.85c48.106-14.469,111.903,16.113,204.241,149.695c3.926,5.681,15.819,9.94,9.524-6.351 c-15.893-41.125-68.176-93.328-92.13-132.085c-24.581-39.774-14.34-61.243-39.957-91.247 c-21.326-24.978-47.502-25.803-77.339-17.365c-23.461,6.634-39.234-7.117-52.98-31.273C318.42,87.525,265.838,64.927,210.333,65.331 z M445.731,203.01c6.12,0,11.112,4.919,11.112,11.038c0,6.119-4.994,11.111-11.112,11.111s-11.038-4.994-11.038-11.111 C434.693,207.929,439.613,203.01,445.731,203.01z"></path></g></svg>

So basically, the "bird" is there but is scaled or positioned in a way it can´t be seen over the OSD canvas.

The case is that the transform "figures" (translate(-371.94953627932824,-119.01136570285395) scale(1837.0000000000002) rotate(0)) seem to be correct. However, deleting that transform node makes the trick, and the bird is shown then.

As that transform node is added by OSD, and I suppose it is the basis for the zoom-pan functionality, how can I get rid of this behavior?

@iangilman
Copy link
Member

I see! Yes, that transform is what aligns the SVG with the zoom/pan of the OSD object. To be precise, what it does is set your SVG to the viewport coordinate system of your OSD. If your SVG path isn't naturally in those viewport coordinates (because it's too big or too small), you have a couple of options: you can change your OSD viewport coordinate system, or you can scale your path.

To change the OSD viewport coordinates, you specify a different size for your image. By default the image is 1 unit wide. If you wanted 1000 units wide, you could do this:

OpenSeadragon({
  tileSources: [
    {
      tileSource: '/foo.dzi',
      width: 1000
    }
  ]
});

On the other hand, if you want to transform your path instead, you can add a transform attribute to it so it matches viewport coordinates. Then the transform in its parent group will handle the zooming/panning as normal.

You might even use a combination of the two techniques, changing the OSD coordinates to be a more comfortable scale, but also putting a translate transform on your path to make sure it is positioned properly.

BTW, for more info on viewport coordinates see:

http://openseadragon.github.io/examples/viewport-coordinates/

@vortice3D
Copy link
Author

vortice3D commented Jul 11, 2018

Well, I'm here again with the OSD part (among many) of this project.

First of all, thanks for your explanation!, Ian.

In order to keep the things simple and efficient, I'm trying to keep the same OSV Viewer settings, meanwhile toggling between the PNG (simple image, not pyramidal one) and the SVG visualization.

Said this, I assume the best solution is the second you have mentioned, as It can be done with not programming at all, in the SVG authoring stage of the workflow.

Said this, I'd like also to check the "tilesource width solution". Before going with the SVG part, I need to check whether changing the things, as you are instruct me, breaks my code down or not for the PNG part. Sadly, I've tried to change the width of the image without luck.

The case is that I implement "creation plus photo loading" in a two-stages pattern.

First:

function _create() {
                ...
		_viewer = OpenSeadragon({
			homeFillsViewer : true,
			id : param.viewer,
			navigatorId : param.navigator,
			showNavigationControl : false,
			showNavigator : true
		});
		...
	}

and then, when needed:

function _loadImage(file) {
		...
		_file = file;
		//
		var type = file.substring(file.length - 3, file.length);
		//fichero PNG (photo)
		if (type == "png") {
			_viewer.open({
				buildPyramid : false,
				type : "image",
				url : file
			});
		}
		//fichero SVG (blueprint)
		else if (type == "svg") {
                      //TO DO
                }
		...
}

Said this, where must it be the "width" property set, in OSD constructor (stage 1) or when actually opening the file (stage 2)? As said, I've tried both approach without any luck.

Thank you for your time.

P.S. I'm sorry for the lack of indentation in the code blocks. It is there meanwhile writing but not shown in preview (?)

@iangilman
Copy link
Member

To make your viewer width, say, 1000, you could do:

_viewer.open({
  tileSource: {
    buildPyramid : false,
    type : "image",
    url : file
  },
  width: 1000
});

This can work in the OSD constructor as well, if that's when you're adding the image... basically you do it wherever you add the image.

I've gone ahead and fixed the indentation in your comment... you just use ```.

@vortice3D
Copy link
Author

Thanks again Ian.

I'll check it this weekend.

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

No branches or pull requests

2 participants