Interaction on namespaced SVG - javascript

I am trying to insert a SVG diagram on a Web page and add JavaScript interaction.
My issue: the SVG includes elements with namespaces, and when I insert it inline, only the non-namespaced elements are rendered. I have tried direct insertion in the html, innerHTML, and the SVGjs library, all give the same result.
Is there a way to render namespaced SVG on the page and interact with it?
For the record, the SVG files come from Visio and I don't have control on the namespaces. Also, I am using Reactjs if that can help.
Sample script (both methods work but strip out namespaced elements):
fetch (fileURL)
.then(response => response.text())
.then((image) => {
let startOfSvg = image.indexOf('<svg')
startOfSvg = startOfSvg >= 0 ? startOfSvg : 0
// innerHTML method
document.getElementById("map").innerHTML = image.slice(startOfSvg);
// svg.js library
const draw = SVG(image.slice(startOfSvg))
.addTo('#map')
.size('100%', 450);
}

There is a checkbox to export SVG without visio namespace. Other than that, you could take a look at my exporter (it can export pure svg as well, depending on the template you use): https://unmanagedvisio.com/products/svg-publish

Related

d3 importing external .SVG files and bind them to objects for functions

Exactly like this (https://bl.ocks.org/mbostock/2206590) but calling the data from an external .svg file drawn from Inkscape instead.
Here is my code so far (using Laravel):
<script>
// Extract the width and height that was computed by CSS.
var chartDiv = document.getElementById("vis");
var width = chartDiv.clientWidth;
var height = chartDiv.clientHeight;
// load the external svg from a file
d3.xml("{{ asset('assets/groundfloor.svg') }}", "image/svg+xml", function(xml) {
var importedNode = document.importNode(xml.documentElement, true);
d3.select("div#vis")
.each(function() {
this.appendChild(importedNode);
})
// inside of our d3.xml callback, call another function
// that styles individual paths inside of our imported svg
styleImportedSVG(); //calling the zoom feature from a function (it can be called here too)
});
Yes, I have looked it up everywhere on the web for the last few days browsing through multiple blocks and none have yet to make a sample on external .svg files and how to append the elements inside it and assigning it to objects.
EDIT: To be clear, I wanted to know the external .svg file variation of .data(importedNode.feature(us, us.objects.buildings).features) and if that's the only thing I need to change in order to bind the elements in my svg file to objects for d3 functions.

How to get time of page's first paint

While it is easy enough to get firstPaint times from dev tools, is there a way to get the timing from JS?
Yes, this is part of the paint timing API.
You probably want the timing for first-contentful-paint, which you can get using:
const paintTimings = performance.getEntriesByType('paint');
const fmp = paintTimings.find(({ name }) => name === "first-contentful-paint");
enter code here
console.log(`First contentful paint at ${fmp.startTime}ms`);
Recently new browser APIs like PerformanceObserver and PerformancePaintTiming have made it easier to retrieve First Contentful Paint (FCP) by Javascript.
I made a JavaScript library called Perfume.js which works with few lines of code
const perfume = new Perfume({
firstContentfulPaint: true
});
// ⚡️ Perfume.js: First Contentful Paint 2029.00 ms
I realize you asked about First Paint (FP) but would suggest using First Contentful Paint (FCP) instead.
The primary difference between the two metrics is FP marks the point
when the browser renders anything that is visually different from what
was on the screen prior to navigation. By contrast, FCP is the point
when the browser renders the first bit of content from the DOM, which
may be text, an image, SVG, or even a canvas element.
if(typeof(PerformanceObserver)!=='undefined'){ //if browser is supporting
const observer = new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
console.log(entry.entryType);
console.log(entry.startTime);
console.log(entry.duration);
}
});
observer.observe({entryTypes: ['paint']});
}
this will help you just paste this code in starting of your js app before everything else.

svgjs transform imported element

Using svg.js I am able to import a fragment from an existing svg file and add it to the dom. However I am not able to then manipulate that element using svg.js.
Here is my code.
$.get('img/sprite.svg', function (doc) {
var figure = $(doc).find('g#figure')[0];
var figureHTML = figure.outerHTML;
var added = draw.svg(figureHTML);
added.transform({rotate: 90});
});
Here is the link to the docs for importing
http://svgjs.dev/importing-exporting/
and the links for transforming
http://svgjs.dev/manipulating/transforms/
I can't get any transformations to work on the imported element.
Perhaps there is another way, but if one uses css selectors one can get a handle into the objects in question then the transformations work.
var elements = SVG.select('g#figure')
.transform({rotate: 90});
http://svgjs.dev/referencing/

Convert SVG to PNG inside Web Worker

I would like to convert an SVG to a PNG inside a Web Worker.
My problem is, that the DOM is not accessible from within the Worker,
so I cannot draw the SVG to a canvas or something like that.
Weeell, you can always manually parse the SVG and build a bitmap from that, but (!) it's a tad more work obviously as you'd have to build a SVG parser as well as a PNG writer, not to mention rasterizing code for lines and two-modes polygon fill incl. anti-aliasing, pattern, matrix, composition, blending and gradient support. Could be a nice weekend project though :)
On a more serious note though: you can only do this with the built-in tools using regular context (none-webworker) or optionally set up a server based service.
You can use thumbo
import Thumbo, { Transfer } from "thumbo";
Thumbo.init().then(async () => {
Thumbo.thumbnail(
Transfer(await (await fetch("/path/to/img.svg")).arrayBuffer()),
Thumbo.ImageFormat.Svg,
20,
20
).then((thumbnailBuffer) => {
document.getElementById("img1").src = URL.createObjectURL(
new Blob([thumbnailBuffer])
);
});
Thumbo.thumbnailFromUrl(
"https://example.com/image.svg",
Thumbo.ImageFormat.Svg,
20,
20
).then((thumbnailBuffer) => {
document.getElementById("img2").src = URL.createObjectURL(
new Blob([thumbnailBuffer])
);
});
});
Under the hood, thumbo uses Rust's tiny_skia & resvg libraries compiled to a Web Assembly module, to render SVG in a web worker and convert it to PNG. See thumbo-core, thumbo
Demo ▶️
Source code
PS: I'm the author of thumbo

P5js SVG Export

I have a P5js sketch which creates a font that users can type anything they want.
I want to allow the user to download an svg/pdf (vector) version of their result.
As of now I succeeded to have them download a .jpg version using the save order and saving a shot of my screen.
Any ideas?
That's an old thread, but maybe my solution will be useful to someone. To export vector graphics in P5js to SVG file, first I use SVG renderer from p5.svg.js library - this will put svg element directly into HTML document. Exporting is to extract the content of that element (by outerHTML property) and save it to a file (like in this post).
So, for example, your "Save as SVG" button callback function may look like this:
function downloadSvg()
{
let svgElement = document.getElementsByTagName('svg')[0];
let svg = svgElement.outerHTML;
let file = new Blob([svg], { type: 'plain/text' });
let a = document.createElement("a"), url = URL.createObjectURL(file);
a.href = url;
a.download = 'exported.svg';
document.body.appendChild(a);
a.click();
setTimeout(function()
{
document.body.removeChild(a);
window.URL.revokeObjectURL(url);
}, 0);
}
From googling "p5.js svg", there doesn't seem to be a built-in way to work with SVG images in p5.js.
However, that search returns several promising results:
Here is a GitHub issue with a discussion about working with SVGs in p5.js.
Here is a project that attempts to add SVG support to p5.js:
The main goal of p5.SVG is to provide a SVG runtime for p5.js, so that we can draw using p5's powerful API in <svg>, save things to svg file and manipulating existing SVG file without rasterization.
Another discussion that links to two more SVG libraries.
The p5.SVG library sounds especially promising. I suggest you try something out and post an MCVE if you get stuck.
A new package called canvas-sketch seems to solve this issue. They have a wealth of examples for p5.js as well.
const canvasSketch = require('canvas-sketch')
const p5 = require('p5')
const settings = {
p5: { p5 },
// Turn on a render loop
animate: true,
}
canvasSketch(() => {
// Return a renderer, which is like p5.js 'draw' function
return ({ p5, time, width, height }) => {
// Draw with p5.js things
p5.background(0)
p5.fill(255)
p5.noStroke()
const anim = p5.sin(time - p5.PI / 2) * 0.5 + 0.5
p5.rect(0, 0, width * anim, height)
};
}, settings)
If you use p5 globally, there's also an example for that called animated-p5.js

Categories