Part of SVG changing in animation on hover - animation

Included here is an image of the svg file (could not upload svg file)
I would like to hover mouse over, and radiantly change background (to blue) only of the circle, from the inner circle to the edges, as an animation.
Even better if the animation was kind of wobbling effect from the middle of the circle and outwards. Nice if it was kind of "random" looking, the blue wobbling effect. Important it's animating from the middle of the circle, out towards the edge until the whole circle is blue.
When mouse/hover is removed then the animation is backwards.
Is that possible in svg/css land and can someone point towards the right direction?

This is a slightly hacky way to do it, using a blue circle with a black stroke that starts so thick it fills its interior. Hovering over the circle causes the stroke to shrink to nothing.
.logo-background {
fill: blue;
stroke: black;
stroke-width: 200;
transition: stroke-width 500ms;
}
.logo-background:hover {
stroke-width: 0;
}
.logo {
fill: none;
stroke: white;
stroke-width: 5;
pointer-events: none;
}
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 200 200" height="100px">
<defs>
<clipPath id="circle-clip">
<circle cx="100" cy="100" r="100" />
</clipPath>
</defs>
<circle class="logo-background" cx="100" cy="100" r="100" clip-path="url(#circle-clip)" />
<rect class="logo" x="60" y="60" width="80" height="80" rx="5" ry="5"/>
</svg>

Related

Clicking On-or-Through Image is Browser-Dependent

I have found a difference between how Firefox and Chrome handle clicking near an image that I need to fix. I have a rect with an image occupying roughly the top 65%. I preserve the aspect ratio of the image and so it appears narrower than the full rect, which is perfect for what I need.
However, when I click near to the image, in the margin space either side of it, Firefox says I have clicked on the rect whereas Chrome says that I have clicked on the image. Inspecting the elements, I see that the image element spans the full width of the rect in both cases, but it is the functionality in Firefox that I need (as though I'm clicking "through" those image margins).
This is better explained with an example. The code below shows one rect and a narrow image in the top 65%. If I click either side of the image in Firefox, it says that the event.target.nodeName is "use" (I have the rect in a <g>) whereas Chrome says it is "image".
function clickHandler(ev) {
ev = ev || window.event;
alert (ev.target.nodeName);
}
text {
text-anchor: middle;
font-size: 10px;
font-weight: bold;
font-family: "Times New Roman";
pointer-events: none;
}
.m {
stroke: dimgray;
stroke-opacity: 1.0;
stroke-width: 1.5;
fill-opacity: 1.0;
fill: white;
}
<svg id="TreeTest" xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<g id="G-Box">
<rect width="80" height="80" rx="5" ry="5"/>
</g>
</defs>
<g id="HenryProctor">
<use tabindex="0" xlink:href="#G-Box" class="m" x="50" y="50" onclick="clickHandler(evt);">
</use>
<text x="90" y="106" dy="1em">Henry</text>
<text x="90" y="106" dy="2em">Proctor</text>
<image x="52.5" y="52.5" width="75" height="51.5" xlink:href="https://parallaxviewpoint.com/Images/Proctor_Henry_b1833.jpg" preserveAspectRatio="xMidYMin meet" onclick="clickHandler(evt);">
</image>
</g>
</svg>
Is there a way to detect when the click was only on the visible part of the image?
[Edited for clarification] I need to distinguish between a click on the visible image and a click anywhere else in the rect. I have my event handler on both, but the action it takes depends on knowing what the user clicked on.
That difference is an interesting quirk that I hadn't noticed before.
Although Firefox's behaviour seems the most useful in this case, I think that Chrome's behaviour follows the spec more accurately. The blank areas on each side of the image are still technically part the "fill" of the <image> element. So clicking there probably should return the "image".
Do you care whether the user clicks on the visible part of the image, or the blank areas beside it? If not, then you could just tell the browser to ignore all click events on the <image> element using:
pointer-events="none"
Now when you click anywhere on the image, in Chrome, you get "use".
function clickHandler(ev) {
ev = ev || window.event;
alert (ev.target.nodeName);
}
text {
text-anchor: middle;
font-size: 10px;
font-weight: bold;
font-family: "Times New Roman";
pointer-events: none;
}
.m {
stroke: dimgray;
stroke-opacity: 1.0;
stroke-width: 1.5;
fill-opacity: 1.0;
fill: white;
}
<svg id="TreeTest" xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<g id="G-Box">
<rect width="80" height="80" rx="5" ry="5"/>
</g>
</defs>
<g id="HenryProctor">
<use tabindex="0" xlink:href="#G-Box" class="m" x="50" y="50" onclick="clickHandler(evt);">
</use>
<text x="90" y="106" dy="1em">Henry</text>
<text x="90" y="106" dy="2em">Proctor</text>
<image x="52.5" y="52.5" width="75" height="51.5" xlink:href="https://parallaxviewpoint.com/Images/Proctor_Henry_b1833.jpg" preserveAspectRatio="xMidYMin meet" onclick="clickHandler(evt);"
pointer-events="none">
</image>
</g>
</svg>
SVG content is in shadowDOM, so you can use evt.composedPath() to get the whole Event path.
evt.composedPath()[0] is the Element you clicked.
SO snippets have some delay issues with this; outputting errors in the console, and after a minute the wrong info in the attached SO snippet console.
Update
Argh! OP wants IE support (its 2021, even Microsoft says not to use IE)
For those who want a modern solution with native Web Components, where the IMG is read, and its naturalWidth and naturalHeight are used to generate SVG from a Template
See JSFiddle: https://jsfiddle.net/WebComponents/qv1n9khf/
<person-card img="https://www.gravatar.com/avatar/..."></person-card>
<person-card img="https://www.gravatar.com/avatar/..."></person-card>

Animate calligraphy using image-file instead of SVG

I am creating animated calligraphy using the stroke-dashoffset technique, applying the stroke as an animated mask on top of an SVG. This works on most browsers, but I would like to apply the same mask on top of a PNG instead. That way, even if the browser has trouble with both SVG and mask (IE...), at least it will just display the PNG as-is.
Here is a codepen of the working calligraphy with pure SVG:
https://codepen.io/benviatte/pen/PMzmYB
Here is the codepen of the non-working calligraphy where I put an image instead of the base SVG. It just displays blank, unless I remove the "mask-image" property, in which case it doesn't animate:
https://codepen.io/benviatte/pen/eqzWzJ
Finally, here is the code of the PNG version that just displays blank:
HTML:
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 354.33071 248.03149">
<mask id="mask" maskUnits="userSpaceOnUse">
<path d="M 92.81613,118.88531 C 92.79077,113.54067 89.77774,108.7899 89.336626,103.42689 96.06007,89.146492 85.818314,62.350762 62.06357,80.661632 c -5.787226,7.87329 -12.023557,16.43904 -12.784729,26.500038 -0.404099,5.34115 3.084547,9.85663 7.361464,12.76814 9.170344,6.24271 20.057653,10.0779 27.888503,18.14154 4.373535,4.50356 2.810446,11.25662 2.004789,16.78827 -1.093846,7.51033 -10.89645,19.36241 -18.314927,21.84098 -9.433311,3.81749 -18.936726,-10.31651 -25.709437,-30.06406" />
</mask>
</svg>
<img src="http://thehermitcrab.org/imgs/S2.png"/>
CSS:
mask path {
fill: none;
stroke: white;
stroke-width: 22;
stroke-dasharray: 237 237;
stroke-dashoffset: 237;
animation: brush 1s cubic-bezier(.6,.3,.3,.9);
animation-fill-mode: forwards;
}
#keyframes brush {
0% { stroke-dashoffset: 237; }
20% { stroke-dashoffset: 237; }
80% { stroke-dashoffset: 0; }
100% { stroke-dashoffset: 0; }
}
img, svg{
width: 300px;
position: absolute;
top: 0;
left: 0;
}
img {
-webkit-mask-image: url(#mask);
mask-image: url(#mask);
}
Thank you so much!!!
You can fill the masked path with an image like so:
I hope this is what you were asking.
mask path {
fill: none;
stroke: white;
stroke-width: 22;
stroke-dasharray: 237 237;
stroke-dashoffset: 237;
animation: brush 5s cubic-bezier(.6,.3,.3,.9);
animation-fill-mode: forwards;
}
#keyframes brush {
0% { stroke-dashoffset: 237; }
20% { stroke-dashoffset: 237; }
80% { stroke-dashoffset: 0; }
100% { stroke-dashoffset: 0; }
}
svg {
width: 300px;
height: 300px;
}
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 354.33071 248.03149">
<defs>
<pattern id="img" patternUnits="userSpaceOnUse" width="100" height="100">
<image xlink:href="https://s3-us-west-2.amazonaws.com/s.cdpn.io/222579/darwin300.jpg" x="0" y="0" width="100" height="100" />
</pattern>
<mask id="mask" maskUnits="userSpaceOnUse">
<path d="M 92.81613,118.88531 C 92.79077,113.54067 89.77774,108.7899 89.336626,103.42689 96.06007,89.146492 85.818314,62.350762 62.06357,80.661632 c -5.787226,7.87329 -12.023557,16.43904 -12.784729,26.500038 -0.404099,5.34115 3.084547,9.85663 7.361464,12.76814 9.170344,6.24271 20.057653,10.0779 27.888503,18.14154 4.373535,4.50356 2.810446,11.25662 2.004789,16.78827 -1.093846,7.51033 -10.89645,19.36241 -18.314927,21.84098 -9.433311,3.81749 -18.936726,-10.31651 -25.709437,-30.06406" />
</mask>
</defs>
<path mask="url(#mask)" fill="url(#img)" d="m 84.347106,72.730822 c -6.700057,0.41349 -13.536192,0.895 -20.004337,2.74122 -8.269143,3.35101 -15.144649,10.28592 -18.335113,18.62393 -1.745059,4.7139 -2.424554,9.829858 -1.055133,14.737138 0.971246,7.85177 6.591277,14.03623 12.594733,18.68723 4.899213,3.10976 10.516595,4.80935 15.88174,6.85728 3.598383,2.16843 7.853428,4.63947 9.276845,8.8059 0.995595,7.43174 -3.283258,14.41911 -7.577125,20.14167 -2.859338,3.25041 -7.082956,5.7682 -11.428016,6.06759 -2.76877,-0.88985 -4.676886,-3.50515 -6.467732,-5.66664 -0.8438,-2.84582 -0.503218,-6.25249 -2.88424,-8.50648 -2.356943,-2.51972 -6.848373,-3.89583 -9.901785,-1.90687 -1.783614,1.60567 -1.978665,4.29248 -0.431156,6.14634 0.628015,2.58248 4.330039,1.06794 4.996601,3.36938 -0.140661,3.29536 -3.415289,5.93264 -3.011822,9.2671 1.471965,3.46591 3.011956,7.79888 7.009623,8.93583 2.779476,2.56577 6.811098,1.17952 10.184223,1.15628 7.753544,-0.82418 15.439311,-4.27064 20.776362,-10.01337 3.918376,-5.23506 6.686713,-11.29125 9.19183,-17.29292 0.679648,-4.33031 0.214675,-8.76706 0.319579,-13.12674 -4.685098,-7.44203 -12.013326,-12.8652 -20.16128,-15.99596 -4.833407,-2.57162 -11.582728,-2.85294 -14.441374,-8.15604 -4.638062,-7.39166 -5.929022,-17.810038 -0.40541,-25.114328 3.085422,-4.36163 7.883758,-8.71782 13.633176,-8.01843 4.028691,-0.21996 8.250498,0.0932 11.561718,2.63603 2.904262,1.44386 1.746882,5.41774 0.879004,7.79388 -2.021102,4.66617 -3.832398,9.978878 -2.737189,15.088588 0.62468,1.45971 1.572558,3.02113 2.790336,3.97665 2.563411,1.00256 5.41245,0.65028 7.526616,-1.1464 2.393394,-1.33047 7.187979,-2.70727 6.367699,-6.21466 -1.29931,-1.67133 -4.660058,0.16306 -5.006198,-2.59652 -0.718456,-6.014858 3.485958,-11.212508 3.846428,-17.152098 0.2919,-3.79706 1.28679,-8.45196 -1.339374,-11.64839 -3.199638,-2.55035 -7.777181,-2.43209 -11.649229,-2.47619 z" />
</svg>

svg hover overlapping elements in Firefox

I have a svg with some circles that should get bigger on hover, here is a snippet
!This will not work in Firefox
var svgRoot = $('.svg-root')[0];
$('.bubble').mouseover(function (e) {
svgRoot.append(e.currentTarget);
});
circle{
transition: all 200ms;
}
circle:hover{
stroke: black;
fill: white;
transform: scale(3);
}
.svg-root svg{
overflow: visible;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<svg class="svg-root">
<svg class="bubble" x="50" y="50">
<circle r="10"></circle>
</svg>
<svg class="bubble" x="70" y="70">
<circle r="10"></circle>
</svg>
<svg class="bubble" x="90" y="50">
<circle r="10"></circle>
</svg>
</svg>
To avoid the other circles overlapping the one the mouse is currently hovering over, I used the append trick. That solves the z-index Problem, but it causes a different one. It seems that after appending the node, Firefox does not recognize the hover state of the cursor. The circles will not scale on hover in Firefox, but they will in Chrome.
I need them to scale on hover and to have the highest z-index while doing so.
Any solutions?

Light gray asset on black background - Blurry

I have a light gray SVG button in a label with black background. The SVG button seems 'blurry' / 'bolder' on the edges. This is not something I can notice when using a white background.
I suppose it is related to the high contrast between background and asset colour.
How can I get this better?
Btw, I'm using the SVG has background image of a div and respecting the original size of image.
CSS code of the div containing the SVG asset:
position: absolute;
z-index: 2;
width: 42px;
height: 42px;
padding: 0px;
border: 0px;
top: 20px;
right: 20px;
background-image: url(/assets/images/icons/create-document-close-button.svg);
background-repeat: no-repeat;
background-color: transparent;
background-size: 36px 36px;
background-position: center center;
transition: all 100ms ease-in-out;
The SVG code:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="36px" height="36px" viewBox="0 0 36 36" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs></defs>
<g id="States" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Buttons-&-States-(Documents-Steps)" transform="translate(-104.000000, -138.000000)">
<g id="Close-Button" transform="translate(104.000000, 138.000000)">
<g>
<circle id="circle" fill="#E9EEF2" cx="18" cy="18" r="18"></circle>
<polygon id="X" fill="#9FADB5" transform="translate(17.868000, 17.808000) rotate(-45.000000) translate(-17.868000, -17.808000) " points="16.968 23.616 18.768 23.616 18.768 18.672 23.736 18.672 23.736 16.944 18.768 16.944 18.768 12 16.968 12 16.968 16.944 12 16.944 12 18.672 16.968 18.672"></polygon>
</g>
</g>
</g>
</g>

SVG Text Rotation Around the Center

I have the text with textContent "Design" and text-anchor as start, that was transformed with css to be rotated 45 degree. so it get rotated. problem is that i need to adjust the (x,y)position of the text after my rotation to display the text between the tick as shown in the Expected figure. How can i achieve this.
Result:
http://imageshack.us/content_round.php?page=done&l=img404/2711/result1h.png
Expected:
http://imageshack.us/content_round.php?page=done&l=img266/5138/expected1.png
<svg>
<text x="100" y="100" width="64" height="16" fill="black" transform="rotate(45,100,100)" text-anchor="start">Design</text>
</svg>
Thanks
Gowri
The text needs to be centered horizontally and vertically so rotation won't move it:
<text x="100" y="50" text-anchor="middle"
dominant-baseline="central" transform="rotate(0, 100, 50)"></text>
text-anchor aligns the text horizontally
dominant-baseline aligns the text vertically
svg {
width: 200px; height: 100px;
text-align: center;
border: solid 1px blue;
font-family: monospace;
}
<svg>
<text x="100" y="50" text-anchor="middle" dominant-baseline="central" transform="rotate(180, 100, 50)">
Hello World
</text>
<text x="100" y="50" text-anchor="middle" dominant-baseline="central" transform="rotate(0, 100, 50)">
Hello World
</text>
</svg>
example: http://jsfiddle.net/e4bAh/131/
use transform="rotate(45, cx, cy)"
Where cx, cy are the co-ordinates of the center of screen (or rotation).
This is a good example

Resources