<div contentEditable>
<svg viewBox='0 0 300 300'>
<text x=2 y=40>
Can this be a text input field?
</text>
<text y=80>
But not this
</text>
<text y=110>
And not this
</text>
</svg>
</div>
The text in the above SVG is editable because it is wrapped in <div contentEditable>, however for our use case this is not ideal as is:
most importantly, we are using React and we'd like the editable text to be controlled in state.
all text in the above SVG is editable, not just the first text field as is desired
it is a big buggy, with the cursor going way far to the right
It is possible to create an individually controlled (with React useState) SVG text field?
EDIT: something along these lines does appear to work:
const [test, setTest] = useState('here is some text');
// And Return
return (<>
<svg>
<foreignObject x="40" y="40" width="300" height="150">
<div xmlns="http://www.w3.org/1999/xhtml">
<FormControl
className='modal-input'
type='text'
value={test}
onChange={(e) => setTest(e.target.value)}
name='firstname'
placeholder='First Name'
/>
</div>
</foreignObject>
...
Where FormElement is from react-bootstrap. We are going to keep working with this and see if it fits our use case fully, but so far, so good!
You can embed HTML fragments (including React portals for example) in SVG using the <foreignObject> tag (which is specifically designed to allow HTML in SVG). BTW I think if you just want to embed some inputs into SVG, doing it using contenteditable does not seem to make any sense. Just use normal <inputs>
<svg viewBox='0 0 300 300'>
<foreignObject x='0' y='0' width='100' height='100'>
<div contenteditable>
Can this be a text input field?
</div>
</foreignObject>
<text y='80'>
But not this
</text>
<text y='110'>
And not this
</text>
</svg>
Related
Let's say that I have an SVG file in my database:
<svg width="400" height="100">
<rect width="400" height="100"
style="fill:rgb(0,0,255);stroke-width:10;stroke:rgb(0,0,0)" />
</svg>
It looks like this
And in my React code I fetch the SVG file like so:
fetch('/api/picture')
.then(res => res.json())
.then(res => {
this.setState({
picture: res
})
})
So now in my state, I have a variable called picture whose value is this:
<svg width="400" height="100">
<rect width="400" height="100"
style="fill:rgb(0,0,255);stroke-width:10;stroke:rgb(0,0,0)" />
</svg>
After doing some research, the only way that I have found to render the SVG is this way:
<div>
<div dangerouslySetInnerHTML={{ __html: this.state.picture }}></div>
</div>
But I'm a little confused on whether this is the preferred and flexible way to do it.
If I want a button on my page where if I click it, the circle will turn red, how will I be able to do that with my current code? What about a button that will add another circle to the svg?
I know I have to access the rect in some way and change the style, but I cannot think of a way with the way I've set it up.
I tried looking for a solution but I can't seem to find one, so I'm under the impression that I have to render my SVG a different way. Could anyone help me figure this out? Thank you
I created https://github.com/hugozap/react-svgmt to facilitate SVG loading and manipulation:
You can load the SVG from a url or string and use SvgProxy to
update any element using a CSS selector.
<SvgLoader width="100" height="100" path="/sample1.svg">
<SvgProxy selector="rect" fill="red" />
</SvgLoader>
If you are interested I wrote an article about it sometime ago
https://medium.com/#hugozap/svg-manipulation-tools-for-react-e1d58b754c81
I have this line of code in my project that generates a certain percentage and shows it on the dashboard.
<text
className="netProfit-circle-text"
x="50%"
y="50%"
dy=".2em"
textAnchor="middle"
>
{`${this.state.percentage}%`}
</text>
What I want to do is to be able to style the "%" and change its size using CSS. How can I do this?
Thanks in advance.
Regards.
You can use the tspan element to wrap the % part. The tspan element can be styled to look visually different than the rest of the text's content. Link to MDN
<tspan>%</tspan>
You can simply wrap the % in a <span> with a class:
<text
className="netProfit-circle-text"
x="50%"
y="50%"
dy=".2em"
textAnchor="middle"
>
{this.state.percentage}
<span class="percentage">%</span>
</text>
and then add some styles to it:
span.percentage {
...
}
yes, it's possible. You can render it as two different jsx elements like this:
<text
className="netProfit-circle-text"
x="50%"
y="50%"
dy=".2em"
textAnchor="middle"
>
<text>{this.state.percentage}</text>
<text className="per-color">%</text>
</text>
Working example: https://codesandbox.io/s/hungry-leftpad-lue55.
I have to print my SVG straight from the browser, but I have no idea how to do that.
The locations and sizes of the SVG's elements are important, that's why the numbers are all in mm.
It has to print on pre-printed paper, in pre-printed containers.
The SVG currently looks something like this:
<svg xmlns="http://www.w3.org/2000/svg" class="col-md-12 designerCanvas" id="svgLabel" width="240mm" height="90mm" viewbox="0 0 240 90">
<image class="svg" id="img-160-68" visibility="visible" x="160.202" y="68.0135" width="14.0043" height="14.0043" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="/images/Icons/icon02.png" />
<image class="svg" id="img-175-68" visibility="visible" x="175.791" y="68.0135" width="14.0043" height="14.0043" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="/images/Icons/icon05.png" />
<image class="svg" id="img-191-68" visibility="visible" x="191.381" y="68.0135" width="14.0043" height="14.0043" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="/images/Icons/icon07.png" />
<text class="svg" id="txt-0-5" font-family="Arial" font-size="1.64233" visibility="visible" text-anchor="start" x="0.5285" y="5.5489" height="33.29333142498542" width="79.26983672615574">
<tspan x="0.5285" dy="1.6423">[EN] Some Title: </tspan>
<tspan x="0.5285" dy="1.6423">There is some text here.</tspan>
<tspan x="0.5285" dy="1.6423">Even more text here. </tspan>
<tspan x="0.5285" dy="1.6423">WOW, a third line.</tspan>
<tspan x="0.5285" dy="1.6423">You're overdoing it</tspan>
<tspan x="0.5285" dy="1.6423">Please</tspan>
<tspan x="0.5285" dy="1.6423">STAHP</tspan>
<tspan x="0.5285" dy="1.6423">No More!!</tspan>
<tspan x="0.5285" dy="1.6423">That's it</tspan>
<tspan x="0.5285" dy="1.6423">I'm outta here....</tspan>
</text>
</svg>
Do note that the paper's (=SVG canvas) width and height come from the DB and can have several values.
The x, y, width and height of the elements now don't have mm, as the viewbox and units combo of the SVG canvas solve that, though I can add it if needed.
Client only wants me to support IE11+, though I myself want to support recent Chrome and FF as well.
I could load the drawing in a fresh (temporary) window to print it, though I'm not sure it'll print on the correct coördinates like that.
Maybe creating a PDF and print that is the way to go, though no idea how to send the svg to that.
The web application itself is an ASP.NET MVC (Core), with plain javascript and jQuery added to the front end.
Couldn't find much info on the web on the topic, besides printing a SVG in pixels on default paper, but I'm pretty sure the elements will get printed in the wrong location/size that way.
Any ideas?
I have a d3.js chart on which I'm trying to use jQueryUi Selectable plug-in while it shows the selection rectangle (no selecting effect as shown on plugin page) but once I release mouse nothing is selected. You can try on fiddle http://jsfiddle.net/mantrig/5b5698dr/
My code is somewhat like below :
<div class="selectable">
<svg height="90" width="200">
<text x="10" y="20" style="fill:red;">Several lines:</text>
<text x="10" y="45">First line.</text >
<text x="10" y="70">Second line.</text >
Sorry, your browser does not support inline SVG.
</svg></div>
--js script--
$(function() {
$( ".selectable" ).selectable();
}
});
No class is getting add or remove on selection . These text elements are sample in my case these things will be dynamic from some json.
I would like to know if there is a way to get a better rendering of svg rotated text?
<?xml version="1.0" encoding="UTF-8"?>
<svg version="1.1" width="900" height="400" xmlns="http://www.w3.org/2000/svg">
<text x="50" y="50" id="text_0" transform="rotate(17, 50, 50)">
SVG text test
</text>
</svg>
You can test the render of this code here: http://jsfiddle.net/vbzTd/2/
It seems like characters are not following the baseline and I don't understand why.
Thanks a lot for your help.
I had similar problem. When the text is rotated all the letters twitching. And it happens in all browsers. Fortunately, I had not so many text for rotating and I just converted text to path. After that it works perfectly. But if you have to rotate a lot of text - size of svg will increase dramatically.