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

Rendering of mermaid diagrams broken after the 3rd slide #2863

Closed
koutbo6 opened this issue Dec 10, 2020 · 12 comments
Closed

Rendering of mermaid diagrams broken after the 3rd slide #2863

koutbo6 opened this issue Dec 10, 2020 · 12 comments

Comments

@koutbo6
Copy link

koutbo6 commented Dec 10, 2020

Managed to integrate mermaid into reveal4.10 and it renders perfectly.
That it, until you hit the 4th slide.

For some reason, slides 1,2,3 render the diagrams and set their size correctly.

Starting from slide 4 and beyond, the diagrams render, but they get unusually small sizes that prohibit their display.

Attached index.html in this gist illustrates the problem:
https://gist.github.com/koutbo6/44777c84fff9fe559bdf984aa065fe4d

I understand this could be a mermaid.js issue, but any idea why

Here is what the elements look like:

// devtools console output


// this is the problematic diagram svg element from the 4th page, notice size
document.getElementsByClassName("mermaid")[2]
<div class="mermaid" data-processed="true"><svg id="mermaid-1607634965885" width="100%" xmlns="http:​/​/​www.w3.org/​2000/​svg" xmlns:xlink="http:​/​/​www.w3.org/​1999/​xlink" height="16" style="max-width:​ 16px;​" viewBox="-8 -8 16 16">​…​</svg></div>​

// output fro svg getBBox for that element
document.getElementsByClassName("mermaid")[2].getElementsByTagName("svg")[0].getBBox()
SVGRect {x: -2, y: -2, width: 120, height: 70}



// here is the working diagram svg element from the 2nd page, compare dimensions to problematic one
document.getElementsByClassName("mermaid")[0]
<div class="mermaid" data-processed="true"><svg id="mermaid-1607634965816" width="100%" xmlns="http:​/​/​www.w3.org/​2000/​svg" xmlns:xlink="http:​/​/​www.w3.org/​1999/​xlink" height="167.46875" style="max-width:​ 400.515625px;​" viewBox="0 0.0000019073486328125 400.515625 167.46875">​…​</svg></div>​

// this is the svg.getBBox() result, notice how dimensions differ from problematic one
document.getElementsByClassName("mermaid")[0].getElementsByTagName("svg")[0].getBBox()
SVGRect {x: 0, y: 0, width: 0, height: 0}

document.getElementsByClassName("mermaid")[1].getElementsByTagName("svg")[0].getBBox()
SVGRect {x: -2, y: -2, width: 120, height: 70}
@koutbo6
Copy link
Author

koutbo6 commented Dec 12, 2020

Ok found a workaround and cause for this.

As I understand, the content of reveal slides is lazy loaded.
Problem is mermaid diagrams are rendered prior to content of slides being fully loaded.
So if we can time rendering after a slide is ready, the diagram renders successfully.

I wasnt able to find a slide-loaded or data-loaded event. Having such an event would make this an easy solution.

My workaround is to look for slides that style.display is set to "block" and data-loaded attribute is set to true that have a non-rendered mermaid diagram, and start rendering the diagram object.

Please see this workaround:
https://gist.github.com/koutbo6/f78bca0e2e2789c9892df77eafa1b70f

Feature request:
Need a data-loaded event added

Other issues to think about:
Diagrams will not show up in Pdf prints unless the whole slides were traversed. Is it possible to render all pages and fire all diagram rendering event when printing pdf?

Thanks!

@malmarz
Copy link

malmarz commented Dec 19, 2020

Noticed also that the diagrams render well if transition is set to: none, fade, or slide
Anything else will cause diagrams to render incorrectly.
Any clues as to why?

@Martinomagnifico
Copy link
Collaborator

Let me know if this works:

	mermaid.mermaidAPI.initialize({
		startOnLoad:false
	});

	let doMermaidStuff = function doMermaidStuff(event) {
		
		let mermaidDivs = event.currentSlide.querySelectorAll('.mermaid:not(.done)');
		let indices = Reveal.getIndices();
		let pageno = `${indices.h}-${indices.v}`

		mermaidDivs.forEach(function (mermaidDiv, i) {

			let insertSvg = function(svgCode, bindFunctions){
				mermaidDiv.innerHTML = svgCode;
				mermaidDiv.classList.add('done');
			};
			let graphDefinition = mermaidDiv.textContent;
			mermaid.mermaidAPI.render(`mermaid${pageno}-${i}`, graphDefinition, insertSvg);
		});

	};

	Reveal.on( 'ready', event => doMermaidStuff(event) );
	Reveal.on( 'slidechanged', event => doMermaidStuff(event) );

@FlorianCassayre
Copy link

FlorianCassayre commented Apr 19, 2022

@Martinomagnifico The solution you provided does in fact fix most of the problems, thanks. There are still some minor quirks, for instance the diagrams become correctly aligned only on the second time the slide is viewed; but probably good enough in my case.

@Mershmelow
Copy link

#2863 (comment)

@FlorianCassayre
Copy link

Here is what I ended up using:

document.querySelectorAll('.mermaid').forEach(function (mermaidDiv, i) {
  let insertSvg = function(svgCode, bindFunctions){
     mermaidDiv.innerHTML = svgCode;
     mermaidDiv.classList.remove('mermaid');
  };
  let graphDefinition = mermaidDiv.textContent;
  mermaid.mermaidAPI.render(`mermaid-${i}`, graphDefinition, insertSvg);
});

It's certainly less efficient than your solution because all the mermaid graphs are generated at the beginning, but it appears to fix the above mentioned issues.

@Martinomagnifico
Copy link
Collaborator

Martinomagnifico commented Apr 23, 2022

Or add Reveal.layout(); near the end of the function. The thing is that this function loads after the slide is starting to appear. So the slide is starting to change from a to b, and at that point the mermaid content is being converted to SVG. But if the content is centered, there will have been a calculation already to calculate the top of the section. Adding the SVG afterwards will then result in some alignment issues. If we add a Reveal.layout(); in the function, it will fix that:

mermaid.mermaidAPI.initialize({
        startOnLoad:false
});

let doMermaidStuff = function doMermaidStuff(event) {
		
    let mermaidDivs = event.currentSlide.querySelectorAll('.mermaid:not(.done)');
    let indices = Reveal.getIndices();
    let pageno = `${indices.h}-${indices.v}`
    
    mermaidDivs.forEach(function (mermaidDiv, i) {
    
	    let insertSvg = function(svgCode, bindFunctions){
		    mermaidDiv.innerHTML = svgCode;
		    mermaidDiv.classList.add('done');
	    };
	    let graphDefinition = mermaidDiv.textContent;
	    mermaid.mermaidAPI.render(`mermaid${pageno}-${i}`, graphDefinition, insertSvg);
    });
    Reveal.layout();
};

Reveal.on( 'ready', event => doMermaidStuff(event) );
Reveal.on( 'slidechanged', event => doMermaidStuff(event) );

@Martinomagnifico
Copy link
Collaborator

By the way, @FlorianCassayre, your function works just as well. It's only some SVG's that are generated, and will hardly impact performance.

@malmarz
Copy link

malmarz commented Jul 11, 2022

fix seems to have worked perfectly ... thanks everyone

@malmarz
Copy link

malmarz commented Jul 11, 2022

I have to change

let insertSvg = function(svgCode, bindFunctions){

to

let insertSvg = function(svgCode){

@Martinomagnifico
Copy link
Collaborator

Martinomagnifico commented Jul 12, 2022

Good catch, bindFunctions is indeed not needed. @koutbo6 Seems to me that this issue can be closed. 😀

gcushen pushed a commit to HugoBlox/hugo-blox-builder that referenced this issue Aug 14, 2022
@maurerle
Copy link

Hi,
I still have an issue using recent reveal.js, mermaid and pandoc.
Maybe someone can take a look at it here:
mermaid-js/mermaid#1824

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

No branches or pull requests

6 participants