I'm trying to make a react Component which is based on this CodePen markup.
My component looks like this:
import React from 'react';
class Arches extends React.Component {
render(){
return(/*markup from codepen*/);
}
}
export default Arches;
But on render it breaks:
unexpected token (764:3)
762 | d="m 46.842051,219.06796
What is the proper way to integrate SVG in a React component?
React does support SVG, but the main problem here is that JSX is not identical to HTML. You can't just copy-paste any old blob of HTML or SVG markup and expect it to work in JSX without some effort to clean it up. The main problems with this particular SVG snippet are:
JSX doesn't allow HTML-style comments, like this one from your example:
<!-- Child Dentition -->
You'll either need to remove these completely, or replace them with JSX Javascript-style comments:
{/* Child Dentition */}
JSX doesn't support XML namespaces. So namespaced elements like here won't work:
<metadata id="metadata8">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
<dc:title>Human Dental Arches</dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
In fact, if you look at the list of supported SVG tags, metadata is not even included, so this section can be removed outright since it doesn't affect the visual output anyway. And also note that namespaced attributes like xml:space won't work either:
<text xml:space="preserve" x="87.802124" y="124.42228" style="font-size:10.13467216px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans">
JSX uses the className attribute instead of class. This is necessary because class is a reserved keyword in Javascript, so anything like this:
<path class="tooth-11 tooth-11-parent" />
Should become this:
<path className="tooth-11 tooth-11-parent" />
The style attribute in JSX takes a Javascript object, not a string literal. So values like this:
<path style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"/>
Will need to be turned into:
<path style={{fill: 'none', stroke: '#000000', strokeWidth: 1, strokeLinecap: 'round', strokeLinejoin: 'miter', strokeMiterlimit: 4, strokeOpacity: 1, strokeDasharray: 'none'}} />
Okay, that's a lot of changes! But as a reward for reading this far, I can let you know there's an easy way to make most of these transformations: this page on the React documentation site will let you paste in arbitrary HTML snippets and output the corresponding JSX. It seems this doesn't take care of the namespace issues I mentioned above, but with a few manual fixes you can end up with some valid JSX that will display nicely.
Related
To import and use svg file in sveltekit I refer to this article
https://riez.medium.com/svelte-kit-importing-svg-as-svelte-component-781903fef4ae
By the way, when I finally input the code
<svelte:component this={Logo} />
I got the error like below
<svelte:component this={...}> is not a valid SSR component. You may need to review your build config to ensure that dependencies are compiled, rather than imported as pre-compiled modules
I wish someone help me with this problem.
There is a SvelteKit plugin for inlining SVG:s. You can use the plugin in three different ways:
As a Svelte Component
As URL (e.g for use in an img tag)
As raw text (e.g for use in {#html rawText})
https://www.npmjs.com/package/#poppanator/sveltekit-svg
Looking through the article it seems to be solving a problem that doesn't exist in a way that is much more elaborate than needed.
In Svelte you can make a .svelte component that only contains SVG markup (inline), then use the svelte:component tag as you would with any other content.
Parent.svelte
<script>
import Circle from './Circle.svelte'
</script>
<svelte:component this={Circle} />
Circle.svelte
<svg viewbox="0 0 200 200">
<circle cx="100" cy="100" r="20"/>
</svg>
Here's a REPL showing how to switch between components that only have SVG in them.
You can even add stuff to the SVG components to make them dynamic since it's just markup like shown in this REPL.
In svelte-kit You can fix it by trying
<img src={YourSVGComponent} />
It worked for me.
I have a Stencil component that should draw SVG shapes over an image.
If I generate the shapes (simple rect below) directly in the svg tag, it's ok, but if I use Stencil subcomponents instead, they're not hydrated.
But they are if I place them outside the svg tag (of course they do not render properly scaled over the image in this case...)
render() {
return (
<Host>
<svg viewBox={this.size}>
<image xlinkHref={this.Image} x="0" y="0"
width={this.width} height={this.height}
preserveAspectRatio="xMinYMin meet"
/>
{this.Bands.map((d) => // THESE ARE NOT HYDRATED
<bands-list data={d} />
)}
{this.Bands.map(() => // BUT THIS IS SHOWN CORRECTLY
<rect x={0} y={0} width={100} height={100} />
)}
</svg>
{this.Bands.map((d) => // HYDRATED, but outside SVG...
<bands-list data={d} />
)}
</Host>
);
}
here is what it produces :
what am I missing please ?
You got it wrong, you are using custom Web Components to dynamically render SVGs. Not WebComponents inside SVGs. Think of it that way - SVG is its own language for basically everything vector-related, basically any HTML inside SVG doesn't make sense. If you want a WebComponent as an abstraction for dynamically generated SVG content, you either generate the whole SVG our you could give StencilJS functional components a try.
Stencil components won't "hydrate" inside SVG, because they are at the heart of it all WebComponents, which are not supported within SVGs. Although you could use <foreignObject> I doubt it will serve you needs.
I am using ember-inline-svg, there is a logo.svg file, I'm calling it with
{{inline-svg 'logo' class="logo" }}
in my hbs file.
It works fine. I just need to send one more data param to it and access that in the svg file so that I can dynamically generate svgs. How would I go about doing that?
what you want is not possible, because svg itself has no dynamic parts.
however you probably don't need ember-inline-svg at all. Could it be a possibility to put your svg inline into a component?
Just create a component Logo and put the svg inside the logo.hbs:
<svg height="60" width="200" ...attributes>
<text y=20 >I love {{#name}}</text>
</svg>
Then set tagName: '' (or use a template-only-glimmer-component). Then you can just use it as a component:
<Logo class="logo" #name="Ember" />
i load a svg file like this
var draw=SVG('container');
var rawSVG=$('rawSVG').get('html'); //get content of invisible div with mootools
draw.svg(rawSVG);
in rawSVG DIV i can see the link tags. But in container, everything inside of the link tags is dropped and i get empty tags
in import.svg.js the only thing related to xlink:href i could found is related to image
element = context.image(attr['xlink:href'])
the links are created by svg.js and saved by export.svg.js correctly but on importing the next time the get dropped.
edit:
i want to load a svg graphic into an cms and than be able to modify the graphic.
it is working fine but on next import the text within the link tag get dropped.
edit 2
ok, now i loose the xlink element but the child elements are kept
what i want is to change a svg node in an external svg file
i include in a hidden div called rawSVG
in witch i see
...//more svg
<a xlink:href="test/" id="lktest">
<text y="86.83333396911621" x="100" font-family="Muli" id="txtest">
<tspan dy="1.8em" x="0" id="tstest">test</tspan>
</text>
</a>
...//more svg
than i grab the content of that div with mootools
var rawSVG=$('rawSVG').get('html');
and than i do
draw.svg(rawSVG);
to make it editable in svg.js
but in my container div i see
... //more svg
<text y="86.83333396911621" x="100" font-family="Muli" id="txtest">
<tspan dy="1.8em" x="0" id="tstest">test</tspan>
</text>
... //more svg
the ink was created and exported with svg.js and works. this behavior happens after reload
i have the xmlns:xlink="http://www.w3.org/1999/xlink" in my svg node
I tried html 5 and html 4 strict
i tried svg with doctype and without
I also tried images and they get dropped aswell
it's like the xml link namespace is not recognized
i tried to set the namespace of xlink like in the comment of the answer to this cuestion:
xmlserializer strips xlink from xlink:html svg image tag
but nothing changed
any suggestion what I'm doing wrong?
I am trying to properly implement the switch tag for a foreignObject tag in SVG so that Internet Explorer can display something else (nothing new in IE, always leaving features out). The documentation is almost perfectly clear on how to do this:
<switch>
<!-- Process the embedded XHTML if the requiredExtensions attribute
evaluates to true (i.e., the user agent supports XHTML
embedded within SVG). -->
<foreignObject width="100" height="50"
requiredExtensions="http://example.com/SVGExtensions/EmbeddedXHTML">
<!-- XHTML content goes here -->
<body xmlns="http://www.w3.org/1999/xhtml">
<p>Here is a paragraph that requires word wrap</p>
</body>
</foreignObject>
<!-- Else, process the following alternate SVG.
Note that there are no testing attributes on the 'text' element.
If no testing attributes are provided, it is as if there
were testing attributes and they evaluated to true.-->
<text font-size="10" font-family="Verdana">
<tspan x="10" y="10">Here is a paragraph that</tspan>
<tspan x="10" y="20">requires word wrap.</tspan>
</text>
The example is nice and clear and shows how to use the requiredExtensions attribute. However, the hyperlink "http://example.com/SVGExtensions/EmbeddedXHTML" is meaningless to me. What would I have to put in place of this in order to denote that XHTML is the requiredExtension for this foreignObject?
I have found the answer after much fiddling. The example should probably be added to the documentation... I have tested in IE, FF, and Chrome so far and all three have treated the switch properly:
Instead of using the "requiredExtensions" attribute, I used the "requiredFeatures" attribute and linked to "http://www.w3.org/TR/SVG11/feature#Extensibility"
So it would look like:
<switch>
<foreignObject width="100" height="50"
requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility">
<!-- whatever external user-agent stuff -->
</foreignObject>
<!-- Alternate SVG content if foreignObject is not supported -->
</switch>
This works for testing if foreignObject is supported by the user-agent, but it isn't perfect as you still aren't denoting which external namespace you plan to use in the foreignObject which that user-agent may not support. It works better than nothing though.
Unfortunately, no standard says what to do but Firefox uses http://www.w3.org/1999/xhtml to indicate that it supports xhtml in foreignObject tags (and http://www.w3.org/1998/Math/MathML for mathml). I believe other UAs may have copied this but I haven't checked.