Get your own customer support community
 

Dynamic resize

Anyone have a working example of dynamically resizing the seadragon viewer?
 
silly I’m unsure
Inappropriate?
1 person has this question

The company marked this question as answered.


  • Baba
    Inappropriate?
    BTW,
    I tried the following:

    viewer.addEventListener("resize", onViewerResize);

    function onViewerResize() {

    viewer.viewport.resize(viewer.viewport.getContainerSize(), true);
    viewer.viewport.update();
    }

    in the hope that the bool passed in to viewport.resize would maintain the visible portion of the canvas in the viewport. The behaviour appeared to be the same whether I passed true or false here?
  • Inappropriate?
    Sorry that the documentation on this is unclear! Resizing the viewer is as simple as:


    1. Modifying the CSS width and height of your container, and

    2. Calling viewer.viewport.resize() with the new size and a "maintain" flag (which you alluded to).


    If "maintain" is true, then the image isn't stretched or scaled with your resize -- its size and position on screen is maintained, relative to the top-left of the viewer. If "maintain" is false, the image appears to scale on screen with the viewer, so anything that was previously visible in the viewer remains visible. Here's an example to illustrate the difference.

    Initially, the HTML element I passed in to the Viewer constructor, called "c" here, is 300x200:


    alert(Seadragon.Utils.getElementSize(c)); // alerts (300, 200)
     



    Here's what it would look like if I resized the viewer to 350x250 with maintain=true:


    c.style.width = "350px";
    c.style.height = "250px";
    var newSize = Seadragon.Utils.getElementSize(c); // is (350, 250)
    viewer.viewport.resize(newSize, true);
     



    Alternately, here's what it would look like if I resized the viewer (in the first screenshot) to 350x250 with maintain=false:


    c.style.width = "350px";
    c.style.height = "250px";
    var newSize = Seadragon.Utils.getElementSize(c); // is (350, 250)
    viewer.viewport.resize(newSize, false);
     



    Here's another example. This time I start the viewer at 350x250, and I'll be resizing down to 200x200.

    Original:



    Resizing the original to 200x200 with maintain=true:



    Resizing the original to 200x200 with maintain=false:



    See how in the maintain=false cases, whatever was visible in the original viewer remained visible? We just had to show a bit more on the top and bottom.

    So with that said, do you really need to resize the viewer yourself? The viewer already resizes the viewport automatically in two cases:


    1. It detects the CSS width/height changed from the previous frame. In this case, it resizes with maintain=true, to mimic the behavior of windows, etc.

    2. You go to full page mode or back. In this case, it resizes with maintain=false, so that the experience is sensible.


    In most cases for dynamic resizing, maintain=true is just fine. So in that case, don't worry with the code yourself; just change the CSS width and height. In other words, don't worry about step 2 above; it's not technically needed.

    Finally, the "resize" event listener isn't needed unless you care to be notified when the height of width is changed. For example, maybe you need to do something special like adjust the position of some controls, etc. If you don't need to do anything, don't worry about this listener.

    Hope that helps!
  • Comment_icon
    Hi Aseem,

    The behaviour you describe with 'maintain = false' is exactly the behaviour I require. I would like this behaviour whenever the container div is resized (as a result of the browser window frame being resized).

    This does not give the result you describe; could this be due to the timing of the automatic resizing you mention in case 1 and the resize I carry out in my resize handler?

    function init() {

    viewer = new Seadragon.Viewer("container");
    viewer.openDzi("url here");

    Seadragon.Utils.addEvent("container", "onresize", onContainerResize);
    }

    function onContainerResize() {

    var c = document.getElementById("container");
    var newSize = Seadragon.Utils.getElementSize(c);
    viewer.viewport.resize(newSize, false);
    }

    Seadragon.Utils.addEvent(window, "load", init);

    The container div has style like this:

    position: absolute;
    width: 99%;
    height: 99%;

    Thanks in advance.
  • Baba
    Inappropriate?
    Apologies, to actually try this out please replace

    window.onresize = onContainerResize;
    //Seadragon.Utils.addEvent(window, "onresize", onContainerResize);
  • Inappropriate?
    Hmm, that's strange. Your code looks fine -- you're acting at your earliest opportunity (the window's "resize" event) and manually resizing the viewport yourself -- so it should be working.

    Do me a favor: also add an event listener on the viewer for its "resize" event. Add a Seadragon.Debug.log() statement (be sure to turn on Seadragon.Config.debugMode) in both that event listener and in your onContainerResize() listener, right after you call the viewport.resize() method. See which log is fired first -- your onContainerResize() one should be.

    Thanks!

    P.S. And I believe one of our testers, Melinda, took this exact same approach for a test app she made, and it worked just fine for her!
  • Baba
    Inappropriate?
    Hi Aseem,

    Having explored this further it appears that when dynamically resizing there is an issue with precision and/or with the order in which the updates occur (the code works fine until it is called continually as in the resizing case). The resizing looks like sometimes it is doing the right thing but it is very easy to leave the viewer in the wrong state. Please try this to see what I mean -

    1) Click and drag the resize grip in the bottom right corner of browser window.
    2) Without releasing the mouse, repeatedly resize the browser window up and down.

    When I do this the viewport gets bigger and bigger until eventually the image disappears completely and won't come back.

    I will log out the events and report in my next update post.

    Thanks,
    Baba
  • Inappropriate?
    Hey Baba,

    I tried what you said on a regular viewer (the one at http://livelabs.com/seadragon-ajax/ga... in full page mode) in all the browsers and I'm not getting any weird behavior ever.

    So it must have to do with the dynamic resizing technique you're using on your viewer. Like I said, it should work since I think our team had tried the same thing earlier, but it sounds like it's not in your case. Can you share your app?

    Thanks!
  • Baba
    Inappropriate?
    Hi Aseem,

    It's a bit tricky to share the whole app but I have uploaded a html file here

    http://cid-4f1b7368284539e5.skydrive....

    which displays the issue in IE8 and Chrome (I haven't tested with other browsers). Just edit the image url for a valid one and then open in browser and resize drag with the size grip up and down a few times to replicate.

    If you don't have the problem still I can upload the image composition I am using.

    Regards,
    Baba.
  • Inappropriate?
    Hey Baba,

    Thanks for sharing your file! I tested this on both IE8 and Chrome. Now I understand what you were asking a little better, and I also found the (rare) bug you mention.

    So first of all, re: the viewport getting bigger and bigger, this is expected behavior with maintain=false. Just remember that "what was visible will remain visible". So when two or more resizes occur that don't maintain the viewport's aspect ratio, the viewport will necessarily get bigger.

    Here's an example of that. First, a 300x200 viewport with a square image at home:



    Next, we resize the viewport to 300x300. The green rectangle is what the viewport previously was, so note how "what was previously visible remains visible".



    Finally, we resize the viewport back to 300x200. The green rectangle is again what the viewport previously was, so again, "what was previously visible remains visible".



    So if you keep resizing the viewport repeatedly, up and down, while not maintaining aspect ratio, the viewport will keep zooming out more and more, in order to preserve what was previously visible. This is the reason that the default behavior in Seadragon Ajax for arbtirary resizes is to use maintain=true (and also because this mimics the way windows resize). So I have to ask -- are you sure you don't want this default behavior? =P

    But nonetheless, re: the image disappearing, I found three cases where this happens, and two of them are indeed bugs and indeed due to precision errors like you mentioned.

    The first case is expected, and that's when you resize the viewer down to 0 in either dimension, as it's not mathematically possible for us to fit anything in zero space. This causes the viewport's values to go to NaN (not a number), causing the image to disappear. You could argue that the Viewport class should autoamtically account for this and ignore any resizes that go to 0. Maybe you'd be right; I'm not sure yet. You can easily account for this yourself for now; only resize if the new size isn't 0.

    The second case is where the precision error leads to a division by zero somehow, leading to the same NaN symptom. Precision errors are nasty, and I don't know of any easy to make a consistent repro, nor any clean way to really "fix" them. So the only workaround I could come up with was similar to the one above: just check the new size yourself and "undo" the resize if it's NaN.

    The third case is where the precision error leads to an overflow, so that e.g. the viewport's x value will be 2 million instead of -2. This means that image hasn't disappeared; it's just way off the screen. So an easy workaround for this is to just call Viewport.ensureVisible() after resizing. This still unfortunately shows the error, as the image will suddenly move to the corner of the viewport, but at least the image is still visible?

    So while none of these three workarounds are ideal, at least they're workaround-able. And the three cases are, at least for me, definite edge cases. I had a very tough time reproing the precision bugs, and actually, they only occurred for me in Chrome, not IE8. (I didn't test Firefox extensively.)

    Here's the modified code I used:


    function onContainerResize() {
     
    var c = document.getElementById("container");
    var newSize = Seadragon.Utils.getElementSize(c);
    var oldBounds = viewer.viewport.getBounds();
     
    // only resize if viewport isn't 0 in either dimension
    if (newSize.x && newSize.y) {
    viewer.viewport.resize(newSize, false);
    viewer.viewport.ensureVisible();
    }
     
    // check new bounds for NaN, reset if necessary
    var newBounds = viewer.viewport.getBounds();
    if (window.isNaN(newBounds.x) || window.isNaN(newBounds.y)) {
    Seadragon.Debug.log("image disappeared, resetting to " + oldBounds.toString());
    viewer.viewport.fitBounds(oldBounds, true);
    Seadragon.Debug.log("bounds are now " + viewer.viewport.getBounds().toString());
    }
    }
     

    So hope this helps for now. Let me know if you continue to have any problems. Thanks for your patience through this!

    Best,
    Aseem
  • Baba
    Inappropriate?
    Hi Aseem,

    No problem; I am happy to help.
    I misunderstood what the intended resize behaviour was. I was expecting that when the container resized a 'best fit' of the current viewport would occur whilst the aspect ratio was kept intact.

    Regards,
    Baba.
User_default_medium