How to scale SVG text clickable area? - svg

> <text x="0" y="50" font-family="Verdana" font-size="35" fill="blue"
> opacity="0">​Hello <animate attributeName="opacity"
> begin="theSVG.click" dur="3s" values="0;1;0" repeatCount="1"
> fill="freeze"> </animate> </text>
As I learn SVG text, I am confused about how to scale the area where it is clickable to active the animate, since I found that I can only click "Hello" to active the animate, and other area is not clickable.
I have tried like padding-top/bottom, pointer-event, and the only way is to add " " in the text to enlarge the clickable area, do you guys have better ideas?
Thanks for your help!

I had the same requirement, and ended up by adding a separate transparent text element just before and just after the required one. The same click event was allocated to these transparent elements.
This doesn't increase the height of the clickable area, but does solve the particular problem where the text is just the single letter 'I' which has little area to click on

Related

Inline SVG pattern repeating horizontally and scaling vertically?

I'm looking for a way to use an inline SVG pattern that scales vertically and only repeats horizontally. Does anyone know if this is possible and if so how?
I know I can makes this just using a SVG as a background-image, but I want to be able to use this SVG in a javascript/component-based workflow so inline is the best fit for that.
Here is link with my work-in-progress: https://codepen.io/devotee/pen/GRJJpKL
And some code:
<div class="divider">
<svg width="100%" height="40px">
<defs>
<pattern id="pattern" x="0" y="0" width="60" height="6" patternUnits="userSpaceOnUse">
<path fill="none" stroke="#F5A861" d="M60 5C45 5 45 1 30 1S15 5 0 5"/>
</pattern>
</defs>
<rect x="10" y="6" width="100%" height="12" fill="url(#pattern)" />
</svg>
As you can see in the link, this repeats in both directions, so setting a bigger height value does not accomplish what I want. I would like this pattern to always fill the containers height (or simply be set to a value with CSS) but repeat horizontally.
Here are some images to illustrate what I mean:
Top is wanted behaviour, bottom is unwanted behaviour:
The background scales vertically and does not repeat. It takes as much space vertically as it can (fills parent height or whatever height value it has specified)
Top is wanted behaviour, bottom is unwanted behaviour:
It does not stretch the SVG horizontally but merely repeats it.
Any ideas or input on how to achieve this?

How to continue to the end of duration for indefinite animation on mouse out

I want to create an SVG that has the animation attributes that can continue the animation on mouse over.
On mouse out, I want the animation to continue to its end of duration before ending.
I am unable to achieve this as my animation always ends abruptly.
<svg viewBox="0 0 300 100" xmlns="http://www.w3.org/2000/svg">
<!-- Simple color fill -->
<circle cx="50" cy="50" r="40" fill="teal" >
<animate attributeName="fill" values="teal;cyan;teal;" dur="1s" calcMode="paced" repeatCount="indefinite" begin="mouseover" end="mouseout" />
</circle>
</svg>
Understand that we can achieve a slightly seamless feel by adding the fill="freeze" attribute.
However it brings back the issue of the colour not being the same as from where it left off.
Any idea how we can create a smooth animation on mouse over just by using svg attributes?
I hope to not use Javascript.

SVG dominant-baseline not working in Safari

I'm trying to position SVG text so that it site entirely above the y-location at which it is located. A dominant baseline of text-after-edge appears to be the appropriate setting for this.
This works just fine in Chrome, but with Safari text-after-edge renders with the text centred around the y-location.
I explored further, as seen in this codepen:
https://codepen.io/anon/pen/obrreb?editors=1010
Here is the output in Chrome:
And in Safari:
As you can see a number of the dominant baseline renderings differ.
Jakob's suggestion to use dy is the simplest and most reliable solution. I would also suggest you use values defined in em units.
1em is the height of the font glyph from the bottom of the lowest descender to the top of the highest ascender or accent.
Descenders are typically around a quarter of an em. So to raise the text above the line use dy="-0.25em". Correspondingly, to hang below the line, use dy="0.75". See the example below.
<svg width="100%" height="200">
<line y1="100" x2="100%" y2="100" stroke="grey"/>
<text x="20" y="100" font="Arial, sans-serif" font-size="40">
<tspan>Hanging</tspan>
<tspan y="100" dy="-0.25em">Hanging</tspan>
<tspan y="100" dy="0.75em">Hanging</tspan>
</text>
</svg>
The main advantage to using em units is that they are independent of the font size. So you can tweak the value to suit your font exactly, and those em values will automatically work for any font size you specify.
I ran into the same problem recently, and found a solution that worked in my case:
After trying the dominant-baseline and baseline-shift properties only to find out that both of them don't work in all browsers I'm aiming to support, a college pointed out to me that you can use the dy attribute on a <text> element to shift it after the glyphs have been positioned along a <textPath>.
Here is some pseudocode/jsx to illustrate my solution:
<g {...}>
<path
id={textPathId}
fill="none"
transform={…}
d={…}
/>
<text
textAnchor="middle"
fill={textFill}
dy={shiftText}
>
<textPath
xmlnsXlink="http://www.w3.org/1999/xlink"
xlinkHref={`#${textPathId}`}
startOffset="50%"
>
{text}
</textPath>
</text>
</g>
Notice that this depends on the knowledge of a shiftText value that has to be known or calculated independently. If this isn't given I think the only road forward is to use a combination of dominant-baseline and baseline-shift while distinguishing the browsers used.

SVG Text centering in NodeJS

I would like to insert a text (maybe multi-line) into a rect, vertically and horizontally centered. The SVG is created on server side in NodeJS, and the result will be displayed in a browser.
SVG does not really support centering text. On the other hand, I have no idea how to calculate width/height of a text on server side to position it properly.
Any ideas?
If you know the width/height, you can position your text element with x,y and set the alignment to middle...
https://jsfiddle.net/ian_b/z9t291nL/1/
<svg width="400" height="400" viewBox="0 0 400 400">
<text text-anchor="middle" alignment-baseline="middle" x="200" y="200">QWERTYUIOPASDFGHJKLZXCVBNM</text>
<circle cx="200" cy="200" r="5"/>
</svg>
Its more tricky for multiple lines, and you would need to adjust taking into account font sizes etc.

How to drag complex SVG?

I have the following svg
<g id="end" transform="translate(125,125)">
<path fill="#4DB3B3" d="M50,2.333C23.674,2.333,2.333,23.674,2.333,50S23.674,97.667,50,97.667S97.667,76.326,97.667,50S76.326,2.333,50,2.333z
M82.771,58.973H17.229c-0.862,0-1.561-0.699-1.561-1.561V42.587c0-0.862,0.699-1.561,1.561-1.561h65.542
c0.862,0,1.561,0.699,1.561,1.561v14.825C84.332,58.274,83.633,58.973,82.771,58.973z"/>
<title>End</title>
</g>
The generated svg looks like
If I were to drag from the blue area the dragging works fine.
The only issue I am facing is whenever I try to drag from the center (white area), the event listener doesn't fire. As if the white area in the middle is not part of the SVG.
How can I tackle this issue ?
As if the white area in the middle is not part of the SVG.
Because it's not part of SVG :) The white area inside is the page background. You could try to put something filled inside (like a white rectangle)?
<g id="end" transform="translate(125,125)">
<rect x="10" y="40" width="80" height="20" style="fill:#fff"></rect>
<path fill="#4DB3B3" d="M50,2.333C23.674,2.333,2.333,23.674,2.333,50S23.674,97.667,50,97.667S97.667,76.326,97.667,50S76.326,2.333,50,2.333z
M82.771,58.973H17.229c-0.862,0-1.561-0.699-1.561-1.561V42.587c0-0.862,0.699-1.561,1.561-1.561h65.542
c0.862,0,1.561,0.699,1.561,1.561v14.825C84.332,58.274,83.633,58.973,82.771,58.973z"/>
<title>End</title>
</g>

Resources