I've been playing around with using a single container that contains multiple viewports that I add a "synced" attribute to in order to iterate through them and add them to a synchronizer. However, it doesn't seem to be working as expected.
I'm only using the scrollStack tool for example purposes and the behavior that I am looking for is "when one of the synced elements is scrolled, all of the elements will scroll up", however the current behavior seems to have all of the elements scrolling independently (e.g. if you scroll the first viewport to the 50th image, when you try to scroll another one of the elements, it will begin at the 50th element). So it seems that the actual index is being synced between the viewports, but the actual viewports do not all scroll at the same time (which is the expected behavior).
A rough example of the code that I am using to wire up this syncronizer looks like the following :
// Create a syncronizer
imageViewer.syncronizers.push(new cornerstoneTools.Synchronizer("CornerstoneNewImage", cornerstoneTools.stackImageIndexSynchronizer));
// Activate all of the view ports (within the new template that was added)
$('.viewport.synced', viewportTemplate).each(function () {
var element = $(this).get(0);
cornerstone.enable(element);
// Populate the number of view ports that need to be populated
if (imageIndex < $('.viewport.synced', viewportTemplate).length && imageIndex < activeStack.imageIds.length) {
// Store the current instance on the element
$(this).attr('data-instance', imageIndex);
// Pull the specific image to be loaded for this stack (relative to the appropriate position)
var image = imageViewer.images[activeStack.imageIds[imageIndex++]];
// Add this viewport to the collection of viewports (along with the stack / series it is associated with)
imageViewer.viewports.push({ Viewport: element, Series: activeStack });
// Display the image on the viewer element
if (image != undefined) {
// Load the image and wire up the appropriate tools, adding the element to the syncronizer
cornerstone.displayImage(element, image);
cornerstoneTools.addStackStateManager(element, ['stack']);
cornerstoneTools.addToolState(element, 'stack', activeStack);
cornerstoneTools.stackScroll.activate(element, 1);
cornerstoneTools.stackScrollWheel.activate(element);
imageViewer.syncronizers[0].add(element);
}
// Details omitted for brevity
}
});
// Define these elements (equivalent to the synced viewports above)
var axialElement1 = $('#axial1').get(0);
var axialElement2 = $('#axial2').get(0);
var axialElement3 = $('#axial3').get(0);
// Grab the image ids from the stack (present in the activeStack above)
var axialImageIds = [ 'example://1', 'example://2']
var axialStack1 = { currentImageIdIndex : 0, imageIds: axialImageIds };
var axialStack2 = { currentImageIdIndex : 0, imageIds: axialImageIds };
var axialStack3 = { currentImageIdIndex : 0, imageIds: axialImageIds };
// Define a syncronizer to use (present in the imageViewer.syncronizers collection above)
var synchronizer = new cornerstoneTools.Synchronizer("CornerstoneNewImage", cornerstoneTools.stackImageIndexSynchronizer);
// Enable each element
cornerstone.enable(axialElement1);
cornerstone.enable(axialElement2);
cornerstone.enable(axialElement3);
// Enable elements for this element
cornerstoneTools.mouseInput.enable(axialElement1);
cornerstoneTools.mouseWheelInput.enable(axialElement1);
cornerstoneTools.mouseInput.enable(axialElement2);
cornerstoneTools.mouseWheelInput.enable(axialElement2);
cornerstoneTools.mouseInput.enable(axialElement3);
cornerstoneTools.mouseWheelInput.enable(axialElement3);
// Images are already loaded within the imageViewer.images collection (so grab them)
cornerstone.loadImage(axialImageIds[0]).then(function(image) {
// display this image (equivalent to being called within the loop)
cornerstone.displayImage(axialElement1, image);
cornerstone.displayImage(axialElement2, image);
cornerstone.displayImage(axialElement3, image);
// set the stack as tool state (being set above as well)
cornerstoneTools.addStackStateManager(axialElement1, ['stack']);
cornerstoneTools.addStackStateManager(axialElement2, ['stack']);
cornerstoneTools.addStackStateManager(axialElement3, ['stack']);
// Is the issue that these are all targeting the same stack? Should they be independent elements?
cornerstoneTools.addToolState(axialElement1, 'stack', axialStack1);
cornerstoneTools.addToolState(axialElement2, 'stack', axialStack2);
cornerstoneTools.addToolState(axialElement3, 'stack', axialStack3);
// Enable all tools we want to use with this element
cornerstoneTools.stackScroll.activate(axialElement1, 1);
cornerstoneTools.stackScrollWheel.activate(axialElement1);
cornerstoneTools.stackScroll.activate(axialElement2, 1);
cornerstoneTools.stackScrollWheel.activate(axialElement2);
cornerstoneTools.stackScroll.activate(axialElement3, 1);
cornerstoneTools.stackScrollWheel.activate(axialElement3);
// Done above as well
synchronizer.add(axialElement1);
synchronizer.add(axialElement2);
synchronizer.add(axialElement3);
}
Is there anything in particular that looks to be missing or that I should be looking into as to why each of the elements may not be all syncing as expected. Any ideas or insight would be helpful and I would be glad to try and provide some additional examples if needed.