Multiple Arrangements

Add another arrangement and a toggle button to switch between both

Project Source Code

Get the project source code below, and follow along with the lesson material.

Download Project Source Code

To set up the project on your local machine, please follow the directions provided in the README.md file. If you run into any issues with running the project source code, then feel free to reach out to the author in the course's Discord channel.

This lesson preview is part of the OpenSeadragon Deep Dive course and can be unlocked immediately with a \newline Pro subscription or a single-time purchase. Already have access to this course? Log in here.

This video is available to students only
Unlock This Course

Get unlimited access to OpenSeadragon Deep Dive, plus 70+ \newline books, guides and courses with the \newline Pro subscription.

Thumbnail for the \newline course OpenSeadragon Deep Dive
  • [00:00 - 00:07] In the previous lesson, you build a custom arrangement function. Now that you have your own arrangement code, you can build as many kinds of arrangements as you want.

    [00:08 - 00:16] In this lesson, we'll add a second arrangement and a toggle button to switch between them. So far, our HTML has simply been a single div holding the HTML viewer.

    [00:17 - 00:22] Now we want to put a control area along the left with a button in it. We'll need to add some CSS for that.

    [00:23 - 00:27] Flexbox will make this easy. We'll also add some basic styling for the control area.

    [00:28 - 00:32] Nothing fancy, but feel free to improve on it. We'll want to listen for clicks on the button.

    [00:33 - 00:47] Now we're going to want to use our arrangement code in two places. When we first open the viewer, and then whenever the user clicks on the toggle button, this means we'll want to move our arrangement code out of the OpenC Dragon open handler and into its own function.

    [00:48 - 00:55] And of course, call it from the handler where all that code came from. We'll also want a variable to keep track of which layout mode we want, something like so.

    [00:56 - 01:07] We probably could have anticipated that we were going to want that functionality in its own function and written it that way to begin with. But I personally like to start with as simple of an approach as possible, refactoring only as needed.

    [01:08 - 01:18] One nice idea we can add, we're going to want to do this pattern of iterating through all of the images, the for loop in our new update layout. On multiple occasions, so we might as well make a little helper for that.

    [01:19 - 01:25] We can then call that giving it a function that will get called for every image in the viewer. This just makes life a little more pleasant.

    [01:26 - 01:40] One thing you'll note is this new function is accessing viewer, which so far has been a local variable in our main function. In order for the new function to have access to it, we'll want to make that a global variable at the top of the file and remove the const from where it's set up in main.

    [01:41 - 01:53] Okay, with that in place, we can touch up our update layout so it uses our new each image. With these changes, we should be able to run and it'll do exactly what it was doing before, but we'll be pleased to know that it's ready for our new functionality under the hood.

    [01:54 - 02:04] Of course, we could add any sort of arrangement, but I thought we'd add a masonry style, where the images are laid out in columns. This style was popularized by Pinterest and is still used in many places.

    [02:05 - 02:18] The basic idea is that you keep track of how tall each column is and for each image, you add it to whichever column is the shortest. So, let's make an array for our collection of columns, with each entry holding the Y position for the next entry in the column, which will start at zero.

    [02:19 - 02:30] Next, we can do another each image and inside of it, we look through the columns to find the best one to use. Now that we have the column index, we can place the image there, and then based on the image's new location and size, update our column record.

    [02:31 - 02:40] We're now ready to hook up the toggle button click handler to switch between layout modes. After we change the layout mode, we update the layout so it'll move the images around.

    [02:41 - 02:52] This is going to update the home area, the portion of the viewer's world where there are images, but it doesn't automatically zoom you to the new home area. Since it seems like a nice thing to do, we call go home to take the user there.

    [02:53 - 03:05] Note that in both update layout and go home, we're not passing true for the immediately flag that they both have. This allows the rearrangement and the zooming to be animated, which creates more visual continuity for the user.

    [03:06 - 03:10] Give it a try and see what you think. Your new layout should look like this.

    [03:11 - 03:28] Experiment with commenting out the go home to see how that looks, and try passing true for one or the other of those functions to see how that affects things. At first, it can be confusing to distinguish between the images moving around and the viewport zooming and panning, but it's well worth getting a sense for how each looks.

    [03:29 - 03:41] When it all comes together, it just feels like a single fluid motion for the user, but you'll want to be able to tell the difference so you can debug as needed. You've written a new arrangement function and hooked up some simple UI to switch between the two layout modes.

    [03:42 - 03:48] Meanwhile, you got in some good refactoring. By now, you should be pretty good at dealing with multiple images in the OpenC Dragon viewer.

    [03:49 - 03:57] In the next module, you'll get into interacting with the images in the viewer directly. But first, see the next lesson for some exercises to practice what you've learned so far.