-
Hi, I'm using drawio in NextCloud to edit .drawio files and I would like to point to those files for display in a Reveal.js presentation. I do not need editing of the .drawio file in the Reveal.js HTML file. All I want to do is display the .drawio file (using javscript I assume) in the client and loading the .drawio file from a URL but after a lot of searching etc I cannot find a simple example of how to do this. There are people building huge stacks to convert .drawio to SVG/PNG/PDF etc but that seems like overkill. I can point to a .drawio file in Google Drive using a URL but I can't point to a .drawio file on any other service (e.g. Nextcloud server). This does not seem like an unrealistic expectation but maybe I am missing part of the story. Is the function of ONLY viewing a .drawio file not available because of some commercial arrangement with Google ? Is there an example of converting a served .drawio file into an image in a browser client? Thanks! |
Beta Was this translation helpful? Give feedback.
Replies: 3 comments 1 reply
-
In the end I used:
|
Beta Was this translation helpful? Give feedback.
-
Great stuff! Really helped me out. I'm moving some of my content off of Confluence onto GitHub pages where I was planning to just host the diagrams as "editable" SVGs. I didn't realize until I was pretty far into it that any "custom actions/links" in my diagrams have to be rendered by client-side js and I was having a hard time finding documentation on how to properly feed a hosted file's data into viewer.min.js. |
Beta Was this translation helpful? Give feedback.
-
Just adding a note to this for my solution for a similar use-case, but in my scenario my drawings were PNG exports with embedded drawio data, and I landed on displaying them in App-based Context: https://www.bookstackapp.com/hacks/interactive-drawings/ JavaScript Code
Note: Some of this is app/scenario-specific, but hopefully the functions and general logic would be useful to others. /**
* This script performs the following:
* - Finds drawings within page content on page view.
* - Fetches the data for those PNG-based drawings.
* - Extracts out the diagrams.net drawing data from the PNG data.
* - Builds embedded "viewer" iframes for the drawings.
* - Replaces the original drawings with embedded viewers.
*/
/**
* Reads a given PNG data text chunk and returns drawing data if found.
* @param {Uint8Array} textData
* @returns {string|null}
*/
function readTextChunkForDrawing(textData) {
const start = String.fromCharCode(...textData.slice(0, 7));
if (start !== "mxfile\0") {
return null;
}
const drawingText = String.fromCharCode(...textData.slice(7));
return decodeURIComponent(drawingText);
}
/**
* Attempts to extract drawing data from a PNG image.
* @param {Uint8Array} pngData
* @returns {string}
*/
function extractDrawingFromPngData(pngData) {
// Ensure the file appears to be valid PNG file data
const signature = pngData.slice(0, 8).join(',');
if (signature !== '137,80,78,71,13,10,26,10') {
throw new Error('Invalid png signature');
}
// Search through the chunks of data within the PNG file
const dataView = new DataView(pngData.buffer);
let offset = 8;
let searching = true;
while (searching && offset < pngData.length) {
const length = dataView.getUint32(offset);
const chunkType = String.fromCharCode(...pngData.slice(offset + 4, offset + 8));
if (chunkType === 'tEXt') {
// Extract and return drawing data if found within a text data chunk
const textData = pngData.slice(offset + 8, offset + 8 + length);
const drawingData = readTextChunkForDrawing(textData);
if (drawingData !== null) {
return drawingData;
}
} else if (chunkType === 'IEND') {
searching = false;
}
offset += 12 + length; // 12 = length + type + crc bytes
}
return '';
}
/**
* Creates an iframe-based viewer for the given drawing data.
* @param {string} drawingData
* @returns {HTMLElement}
*/
function createViewerContainer(drawingData) {
const params = {
lightbox: '0',
highlight: '0000ff',
layers: '1',
nav: '1',
dark: 'auto',
toolbar: '1',
};
const query = (new URLSearchParams(params)).toString();
const hash = `R${encodeURIComponent(drawingData)}`;
const url = `https://viewer.diagrams.net/?${query}#${hash}`;
const el = document.createElement('iframe');
el.classList.add('mxgraph');
el.style.width = '100%';
el.style.maxWidth = '100%';
el.src = url;
el.frameBorder = '0';
return el;
}
/**
* Swap the given original drawing wrapper with the given viewer iframe.
* Attempts to somewhat match sizing based on original drawing size, but
* extra height is given to account for the viewer toolbar/UI.
* @param {HTMLElement} wrapper
* @param {HTMLElement} viewer
*/
function swapDrawingWithViewer(wrapper, viewer) {
const size = wrapper.getBoundingClientRect();
viewer.style.height = (Math.round(size.height) + 146) + 'px';
wrapper.replaceWith(viewer);
}
/**
* Attempt to make a drawing interactive by converting it to an embedded iframe.
* @param {HTMLElement} wrapper
* @returns Promise<void>
*/
async function makeDrawingInteractive(wrapper) {
const drawingUrl = wrapper.querySelector('img')?.src;
if (!drawingUrl) {
return;
}
const drawingPngData = await (await fetch(drawingUrl)).bytes();
const drawingData = extractDrawingFromPngData(drawingPngData);
if (!drawingData) {
return;
}
const viewer = createViewerContainer(drawingData);
swapDrawingWithViewer(wrapper, viewer);
}
// Cycle through found drawings on a page and update them to make them interactive
const drawings = document.querySelectorAll('.page-content [drawio-diagram]');
for (const drawingWrap of drawings) {
makeDrawingInteractive(drawingWrap);
} |
Beta Was this translation helpful? Give feedback.
In the end I used: