archi icon indicating copy to clipboard operation
archi copied to clipboard

[Feature request] Diagram zooming in HTML reports

Open nicorikken opened this issue 5 years ago • 20 comments

I also use Archimate to create deployment diagrams, as it has the nice feature of clickable documentation. This use-case comes with giant diagrams which contain all the features in one encompassing diagram.

Currently the HTML report shows the entire diagram, making it hard to read the actual content. And there is no way of zooming, to get to a readible level.

By offering a zooming solution within the diagram frame, you can explore the elements in a readeble fashion. Perhaps even with an outline, just as in the normal Archimate UI.

Another solution to this problem might be sub-diagrams, so that by double clicking on an element, you can get a sub-diagram providing more detail on the element just clicked.

nicorikken avatar Nov 25 '19 20:11 nicorikken

Reading further into the details, I see that the https://github.com/davidjbradshaw/image-map-resizer is already used in the current version of the HTML view. So theoretical, if the image can be resized and panned, than the imageMapResize() should correct the image map to enable interaction.

Considering that the topright frame includes more than just the image, just the image should zoom and pan, not the entire iframe. Ideally it would be easily discoverable, either by mouseover or with UI elements like a +, - and a D-pad.

Ideally this should also work in the future HTML report update https://github.com/archimatetool/archi/wiki/HTML-export-v3

Perhaps there are better ways than just a image map for making it interactive. I'm not sure about that. But that might be a greater overhaul.

nicorikken avatar Nov 26 '19 06:11 nicorikken

Hi

At my company, my colleague Anita (@anitaMistry) implemented a zoom slider that keeps the image map working correctly.

It looks like this: Animation2

Please let me know if you want more info, but basically, we just attach this function to the iframe's load event:

document.querySelector('iframe[name=view]').addEventListener('load', initZoomSlider);

function initZoomSlider() {
	let ifrm = document.querySelector('iframe[name=view]');
	let lnkHtml = ifrm.contentWindow.location.pathname.substring(1);

	const sliderAndLinkHtml = ' \
	<style>#btnZoomIn, #btnZoomOut{cursor:pointer;}</style> \
	<div class="row" style="width: 230px;float:right;"> \
		<div class="col-xs-1" id="btnZoomOut"><span class="glyphicon glyphicon-minus"></span></div> \
		<div class="col-xs-7"><input type="range" min="50" max="400" value="100" id="zoomRange"></div> \
		<div class="col-xs-1" id="btnZoomIn" style="padding:0"><span class="glyphicon glyphicon-plus"></span></div> \
		<div class="col-xs-2" id="linkToView"> <a target="_blank" href="/?link=' + lnkHtml + '">link</a></div> \
	</div>';
	
	let doc = ifrm.contentDocument ? ifrm.contentDocument : ifrm.contentWindow.document;
	$(doc.getElementsByClassName("panel-heading")[0]).append(sliderAndLinkHtml);
	var slider = doc.getElementById("zoomRange");
	let img = doc.getElementsByClassName("diagram")[0];
	img.style.maxWidth = slider.value + "%";

	slider.oninput = function () {
		img.style.maxWidth = this.value + "%";
		img.style.width = this.value + "%";
		window.focus();
	}

	const step = 10;

	doc.getElementById("btnZoomOut").onclick = function () {
		slider.value = ((parseInt(slider.value)) - step);
		$(slider).trigger("input");
	}
	doc.getElementById("btnZoomIn").onclick = function () {
		slider.value = ((parseInt(slider.value)) + step);
		$(slider).trigger("input");
	}
}

Update: I have updated the code to be compatible with ES5, IE11

eduardobbs avatar Apr 26 '21 12:04 eduardobbs

@jbsarrodie maybe this could be useful for others as well

eduardobbs avatar Apr 26 '21 13:04 eduardobbs

Hi

At my company, my colleague Anita (@anitaMistry) implemented a zoom slider that keeps the image map working correctly.

It looks like this: Animation2

Please let me know if you want more info, but basically, we just attach this function to the iframe's load event:

document.querySelector('iframe[name=view]').addEventListener('load', initZoomSlider);

function initZoomSlider() {
	let ifrm = document.querySelector('iframe[name=view]');
	let lnkHtml = ifrm.contentWindow.location.pathname.substring(1);

	const sliderAndLinkHtml = ' \
	<style>#btnZoomIn, #btnZoomOut{cursor:pointer;}</style> \
	<div class="row" style="width: 230px;float:right;"> \
		<div class="col-xs-1" id="btnZoomOut"><span class="glyphicon glyphicon-minus"></span></div> \
		<div class="col-xs-7"><input type="range" min="50" max="400" value="100" id="zoomRange"></div> \
		<div class="col-xs-1" id="btnZoomIn" style="padding:0"><span class="glyphicon glyphicon-plus"></span></div> \
		<div class="col-xs-2" id="linkToView"> <a target="_blank" href="/?link=' + lnkHtml + '">link</a></div> \
	</div>';
	
	let doc = ifrm.contentDocument ? ifrm.contentDocument : ifrm.contentWindow.document;
	$(doc.getElementsByClassName("panel-heading")[0]).append(sliderAndLinkHtml);
	var slider = doc.getElementById("zoomRange");
	let img = doc.getElementsByClassName("diagram")[0];
	img.style.maxWidth = slider.value + "%";

	slider.oninput = function () {
		img.style.maxWidth = this.value + "%";
		img.style.width = this.value + "%";
		window.focus();
	}

	const step = 10;

	doc.getElementById("btnZoomOut").onclick = function () {
		slider.value = ((parseInt(slider.value)) - step);
		$(slider).trigger("input");
	}
	doc.getElementById("btnZoomIn").onclick = function () {
		slider.value = ((parseInt(slider.value)) + step);
		$(slider).trigger("input");
	}
}

Update: I have updated the code to be compatible with ES5, IE11

Hi, Could you tell me where to copy this code ? I put it in model.js but it doesn't work. Thanks a lot.

vbo75 avatar Jun 10 '21 16:06 vbo75

Hi, Could you tell me where to copy this code ? I put it in model.js but it doesn't work. Thanks a lot.

You'de better use the latest version of the HTML report template which includes this and other changes. It will be shipped with Archi 4.9 but in the meantime you can easily use it: simply replace the plugins\com.archimatetool.reports_x.x.x\templates folder by the one you can get inside the html-report branch. You can get the zip version of this branch here.

Report now looks like this: image

You'll note the zoom slider but also the serach feature on the model tree. There's also now a way to hide views, concepts or folders from the export (based on properties set inside your model).

jbsarrodie avatar Jun 10 '21 16:06 jbsarrodie

Thanks a lot ! Works very well, this new template is very nice. Great job !

Le 10 juin 2021 à 18:28, Jean-Baptiste Sarrodie @.***> a écrit :

 Hi, Could you tell me where to copy this code ? I put it in model.js but it doesn't work. Thanks a lot.

You'de better use the latest version of the HTML report template which includes this and other changes. It will be shipped with Archi 4.9 but in the meantime you can easily use it: simply replace the plugins\com.archimatetool.reports_x.x.x\templates folder by the one you can get inside the html-report branch. You can get the zip version of this branch here.

Report now looks like this:

You'll note the zoom slider but also the serach feature on the model tree. There's also now a way to hide views, concepts or folders from the export (based on properties set inside your model).

— You are receiving this because you commented. Reply to this email directly, view it on GitHub, or unsubscribe.

vbo75 avatar Jun 11 '21 21:06 vbo75

HI guys! Do you keep in mind the hot keys like Ctrl+mouse wheel (or Ctrl +/-)? It's always quicker to roll the wheel rather than using particular controls.

ilyacoos avatar Jul 16 '21 07:07 ilyacoos

As big brother GitHub already indicates, I created a docker container so I can generate html reports easily during CI without uploading or downloading Archi in the pipeline directly.

The new template does look really nice, but unfortunately trying to zoom kind of nukes the layout most of the time. Occasionally it works fine. By nuking I mean: title bar of the diagram looses color en the diagram image just vanishes.

Going back and forth a few times between Views seems to somehow solve the issues.

The console if full of these errors, maybe that helps: image

Any idea on what I am doing wrong?

YoeriVD avatar Jul 16 '21 12:07 YoeriVD

Hi, I've had no issues and I tested with IE, Edge, Chrome and Firefox. Can you provide more information on your exact setup?

jbsarrodie avatar Jul 16 '21 12:07 jbsarrodie

Of course, thanks for replying 👍 I really appreciate it. I have downloaded the Archi linux version, coArchi plugin and new html template. Copy everything inside a docker container where I:

  1. unzip Archi
  2. add the coArchi jars to the plugins folder
  3. delete the reports.xxx/templates folder en replace it with the new template (included in the repo)
  4. run Archi report generator from the cli, using the linux headless instructions
  5. deploy as a static website to an Azure Web App

the entire source can be found here: https://github.com/YoeriVD/archi-html-report-container

I have tested in Edge (mac) and Safari (mac) and my repro steps are the following:

  1. Launch website
  2. open specific View (important: do not click on anything else)
  3. zoom using the slider
  4. Diagram vanishes sometimes

if I click on an element before zooming, somehow zooming seems to work fine. Refreshing the page also helps sometimes. In any case, the console is spammed with the "Uncaught TypeError: e.originalEvent.data.split is not a function" error.

Does this help?

YoeriVD avatar Jul 16 '21 13:07 YoeriVD

I can confirm the diagram vanishing on Mac with Safari. A Refresh seems to help.

Phillipus avatar Jul 16 '21 13:07 Phillipus

Wild guess, going from the js code sample above: Could it be a race condition?

  1. load view
  2. init slider for loaded iframe
  3. change view
  4. zoom before new iframe loaded event
  5. ?? unexpected behavior

It would explain why it works after a refresh or clicking something. Also why it only happens sometimes.

YoeriVD avatar Jul 16 '21 13:07 YoeriVD

If you click on the link for the View in the Model Tree twice it works OK.

Phillipus avatar Jul 16 '21 15:07 Phillipus

@Phillipus does your latest commit fix the race condition? In my case it is quite persistent. I have been getting remarks that the website "doesn't work" rendering it almost unusable.

YoeriVD avatar Nov 24 '21 10:11 YoeriVD

@Phillipus does your latest commit fix the race condition? In my case it is quite persistent. I have been getting remarks that the website "doesn't work" rendering it almost unusable.

No. I haven't worked on this aspect of the HTML report nor do I know how to fix it. Perhaps someone could contribute a patch.

Phillipus avatar Nov 24 '21 10:11 Phillipus

I experimented using Safari on Mac.

In file frame.js, function initZoomSlider, there is this line:

let imgNativeWidth = img.width;

Sometimes img.width is 0 which causes the problem.

A workaround is to add a small delay to calling the function initZoomSlider at line 171:

// initZoomSlider();
setTimeout(initZoomSlider, 50)

@YoeriVD Can you edit your frame.js file and try this?

Phillipus avatar Nov 24 '21 12:11 Phillipus

Hi, I was looking at the modified implementation, I guess that the problem is that the $(document).ready() does not wait for the images to be loaded. If you can rely on the onload event instead, it can do the work without using the setTimeout call

SO thread

eduardobbs avatar Nov 24 '21 12:11 eduardobbs

Hi, I was looking at the modified implementation, I guess that the problem is that the $(document).ready() does not wait for the images to be loaded. If you can rely on the onload event instead, it can do the work without using the setTimeout call

SO thread

Indeed, that is the case. Thanks for the heads up.

@YoeriVD Please replace line 134 with:

$(window).on('load', function() {

and try that.

Phillipus avatar Nov 24 '21 12:11 Phillipus

This looks good to me! I was not able to break it anymore :) I really appreciate the effort guys, helps a lot.

YoeriVD avatar Nov 24 '21 15:11 YoeriVD

This looks good to me! I was not able to break it anymore :) I really appreciate the effort guys, helps a lot.

Thanks for confirmation. We'll get this fix into the next maintenance release. In the meantime, you can simply use the modified frame.js file.

Phillipus avatar Nov 24 '21 16:11 Phillipus