CSS svg hover animation/transition - html

im using a svg clip-path as mask for an image.
Now i want an inner border inside it on hover.
So i made a second clip-path for hover but the transition doesnt affect it.
I want the border comming from the sides (reducing zoom/negative scaling).
Here you can see what i want without working animation/transition:
body {
background: #ccc;
}
.clip-svg {
position: relative;
display: block;
height: 400px;
width: 300px;
background-position: center center;
background-size: auto 100%;
clip-path: url(#Emblem);
transition: 0.4s all ease;
}
.clip-svg:hover {
clip-path: url(#Emblem2);
}
<div class="clip-svg" style="background-image: url(https://images.pexels.com/photos/864994/pexels-photo-864994.jpeg?auto=compress&cs=tinysrgb&h=750&w=1260)"></div>
<svg width="0" height="0">
<defs>
<clipPath id="Emblem">
<path d="M279,240c0,96-139.4,145-139.4,145S22,336,22,240c0-58,0-203,0-203s65-11,129-11c75,0,128,11,128,11S279,136,279,240z"/>
</clipPath>
<clipPath id="Emblem2">
<path d="M39,51.6V240c0,72.4,80.9,116.6,101.2,126.5c11-4.5,35.7-15.4,59.8-32.3c18.5-13,33.2-26.8,43.6-41.3
c12.2-17,18.4-34.8,18.4-53V51.3C240.8,48,200.9,43,151,43C106.3,43,59.9,48.7,39,51.6z"/>
<path d="M151,26C87,26,22,37,22,37s0,145,0,203c0,96,117.6,145,117.6,145S279,336,279,240c0-104,0-203,0-203S226,26,151,26z
M270,240c0,19.9-6.7,39.3-19.9,57.7c-10.9,15.1-26.2,29.7-45.5,43.1c-26.2,18.3-52.8,29.8-63.1,33.8l-1.6,0.6l-1.6-0.8
c-10.4-5-37.2-18.9-61.3-41.3c-30.5-28.4-46-59.7-46-93.2V44.7l3.4-0.5C53.5,41.4,103.1,35,151,35c53.2,0,95.3,5.6,115.6,8.9
l3.4,0.5V240z"/>
</clipPath>
</defs>
</svg>
<br/>
Image: https://www.pexels.com/...d-tablet-864994/
Thanks in advance

I would consider two layers each one using a clip-path and I would control the opacity:
body {
background: #ccc;
}
.clip-svg {
position: relative;
display: inline-block;
height: 400px;
width: 300px;
}
.clip-svg::before,
.clip-svg::after {
content: "";
position: absolute;
top: 0;
right: 0;
left: 0;
bottom: 0;
background-position: center center;
background-size: auto 100%;
background-image: var(--i);
transition: 0.8s all ease;
}
.clip-svg::before {
clip-path: url(#Emblem2);
}
.clip-svg::after {
clip-path: url(#Emblem);
}
.clip-svg:hover::after {
opacity:0;
}
<div class="clip-svg" style="--i: url(https://images.pexels.com/photos/864994/pexels-photo-864994.jpeg?auto=compress&cs=tinysrgb&h=750&w=1260)"></div>
<svg width="0" height="0">
<defs>
<clipPath id="Emblem">
<path d="M279,240c0,96-139.4,145-139.4,145S22,336,22,240c0-58,0-203,0-203s65-11,129-11c75,0,128,11,128,11S279,136,279,240z"/>
</clipPath>
<clipPath id="Emblem2">
<path d="M39,51.6V240c0,72.4,80.9,116.6,101.2,126.5c11-4.5,35.7-15.4,59.8-32.3c18.5-13,33.2-26.8,43.6-41.3
c12.2-17,18.4-34.8,18.4-53V51.3C240.8,48,200.9,43,151,43C106.3,43,59.9,48.7,39,51.6z"/>
<path d="M151,26C87,26,22,37,22,37s0,145,0,203c0,96,117.6,145,117.6,145S279,336,279,240c0-104,0-203,0-203S226,26,151,26z
M270,240c0,19.9-6.7,39.3-19.9,57.7c-10.9,15.1-26.2,29.7-45.5,43.1c-26.2,18.3-52.8,29.8-63.1,33.8l-1.6,0.6l-1.6-0.8
c-10.4-5-37.2-18.9-61.3-41.3c-30.5-28.4-46-59.7-46-93.2V44.7l3.4-0.5C53.5,41.4,103.1,35,151,35c53.2,0,95.3,5.6,115.6,8.9
l3.4,0.5V240z"/>
</clipPath>
</defs>
</svg>

I don't see a way to achieve what you want using clip paths on an HTML element. You can only replace one clip path with another in CSS. You can't interpolate between two of them.
However it is fairly easy to do, if you are okay with moving the image into an SVG. Then you can do whatever you want with the inner border.
Note however, with this solution, the inner border is not a clip path, so it doesn't make the image transparent. I don't know if that is important to you or not. It should be possible to do that if you really need it to.
body {
background: #ccc;
}
.clip-svg .emblem2-ref {
transform-origin: 150px 200px;
transform: scale(1.2, 1.2);
transition: 0.4s all ease;
}
.clip-svg:hover .emblem2-ref {
transform: scale(1, 1);
}
#Emblem2 {
fill: #ccc;
}
<!-- Clip path and inner border definitions. Can be included once and used by multiple SVGs -->
<svg width="0" height="0">
<defs>
<clipPath id="Emblem">
<path d="M279,240c0,96-139.4,145-139.4,145S22,336,22,240c0-58,0-203,0-203s65-11,129-11c75,0,128,11,128,11S279,136,279,240z"/>
</clipPath>
<path id="Emblem2"
d="M39,51.6V240c0,72.4,80.9,116.6,101.2,126.5c11-4.5,35.7-15.4,59.8-32.3c18.5-13,33.2-26.8,43.6-41.3
c12.2-17,18.4-34.8,18.4-53V51.3C240.8,48,200.9,43,151,43C106.3,43,59.9,48.7,39,51.6z
M270,240c0,19.9-6.7,39.3-19.9,57.7c-10.9,15.1-26.2,29.7-45.5,43.1c-26.2,18.3-52.8,29.8-63.1,33.8l-1.6,0.6l-1.6-0.8
c-10.4-5-37.2-18.9-61.3-41.3c-30.5-28.4-46-59.7-46-93.2V44.7l3.4-0.5C53.5,41.4,103.1,35,151,35c53.2,0,95.3,5.6,115.6,8.9
l3.4,0.5V240z"/>
</defs>
</svg>
<!-- Will need one of these SVGs for every image you want to display -->
<svg width="300" height="400" class="clip-svg">
<g clip-path="url(#Emblem)">
<image width="300" height="400" preserveAspectRatio="xMidYMid slice"
xlink:href="https://images.pexels.com/photos/864994/pexels-photo-864994.jpeg?auto=compress&cs=tinysrgb&h=750&w=1260"/>
<use class="emblem2-ref" xlink:href="#Emblem2"/>
</g>
</svg>
<br/>
Image: https://www.pexels.com/...d-tablet-864994/

Related

Mojave Safari 14.1.2 - css animation svg disappearing during playback

Is someone able to explain a problem in Safari for this simple example:
codepen example
The logo-1 class element should animate into position from right to left. On mac it works in Firefox, Chrome and in IE11/win8 in the original bigger piece of code. In Safari during css animation the svg graphics disappears and appears only after animation is done. It only animates correctly if there is an extra dummy sibling to the svg element with a 3d transform applied to it. It needs to be on a lower z-index than the svg or the animation display fails. Ideally the svg element should be the only child of the logo-1 class element.
In the codepen example animation shows correctly for me in Safari only in the first main div that has the extra element under logo-1 element.
Any ideas?
Codepen code:
.logo-1 svg {
position: absolute;
top: 0;
left: 0;
}
.logo-1-sequence {
position: absolute;
top: 0;
left: 0;
display: block;
width: 113px;
height: 134px;
transform: scale3d(1, 1, 1) translate3d(0, 0, 0);
}
#keyframes kf-frame-1-logo-1-in {
0% {
transform: scale3d(0.47, 0.47, 1) translate3d(2078px, 20px, 0);
}
100% {
transform: scale3d(0.47, 0.47, 1) translate3d(1578px, 20px, 0);
}
}
.logo-1 {
position: absolute;
z-index: 2;
width: 93px;
height: 150px;
background-color: red;
animation: kf-frame-1-logo-1-in 0.5s 0.5s both linear 1;
}
.main {
background: green;
position: relative;
width: 900px;
height: 150px;
display: block;
overflow: hidden;
}
<div class="main">
<div class="logo-1">
<div class="logo-1-sequence"></div>
<svg class="logo-1-svg" xmlns="http://www.w3.org/2000/svg" width="93" height="150" viewBox="0 0 93 150">
<rect x="10" y="10" width="30" height="30" stroke="black" fill="transparent" stroke-width="5" />
</svg>
</div>
</div>
<div class="main">
<div class="logo-1">
<!-- <div class="logo-1-sequence"></div> -->
<svg class="logo-1-svg" xmlns="http://www.w3.org/2000/svg" width="93" height="150" viewBox="0 0 93 150">
<rect x="10" y="10" width="30" height="30" stroke="black" fill="transparent" stroke-width="5" />
</svg>
</div>
</div>

How to prevent an outline on SVG path when animating clip path?

I'm trying to get this animation to work in my website. For some reason the layered paths show through so a thin white outline for the path (that's animated in) is visible ruining the animation, despite the fact the paths are identical in size. I wondered if anyone has any suggestions on how to prevent this?
I've made a jsFiddle and added the code below. If you change the background for the body to black it's even clearer.
Any help would be appreciate.
body {
background: #333;
padding: 2em;
}
svg {
display: block;
left: 50%;
max-width: 8em;
position: absolute;
top: 50%;
transform: translate(-50%,-50%);
}
#rect {
animation: slideOver 5s linear infinite;
}
#keyframes slideOver {
0% {
transform: translateX(0);
}
100% {
transform: translateX(100%);
}
}v
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 250 346">
<defs>
<clipPath id="clip-path">
<rect id="rect" x="0" y="0" height="346" width="250"/>
</clipPath>
</defs>
<path fill="#fff" d="M1.9 0h245.9v58H1.9zM250.1 139.9l-43.8-43.8-81.2 81.2-81.3-81.2L0 139.9l81.2 81.2L0 302.3l43.8 43.9 81.3-81.2 81.2 81.2 43.8-43.9-81.2-81.2"/>
<path clip-path="url(#clip-path)" fill="#000" d="M1.9 0h245.9v58H1.9zM250.1 139.9l-43.8-43.8-81.2 81.2-81.3-81.2L0 139.9l81.2 81.2L0 302.3l43.8 43.9 81.3-81.2 81.2 81.2 43.8-43.9-81.2-81.2"/>
</svg>

Change size of SVG clipping mask on mouseover

I want to show images using a mask. I tried the css clip-path but because the browser support is that poor I want to use an svg for clipping. My question is how can i change the size of the mask on mousover?
Like here:
I am using this code at the moment:
<svg>
<defs>
<!--defines the shape to use for clipping-->
<circle id="circle" cx="100" cy="100" r="100" />
</defs>
<clipPath id="clip">
<!--creates the clipping mask from the shape-->
<use xlink:href="#circle" overflow="visible"></use>
</clipPath>
<!--group containing the image with clipping applied-->
<g clip-path="url(#clip)">
<image overflow="visible" xlink:href="model_detail.jpg"></image>
</g>
</svg
In your case, since you need to resize both the circle and the clipped image, you may scale the svg element on hover like so:
svg {
display: block;
position: absolute;
margin: auto;
top: 0;
bottom: 0;
left: 0;
right: 0;
transform: scale(1);
transition: transform 0.5s;
}
svg:hover {
transform: scale(1.5);
}
<svg viewBox="0 0 200 200" width="200">
<defs>
<!--defines the shape to use for clipping-->
<circle id="circle" cx="100" cy="100" r="100" />
</defs>
<clipPath id="clip">
<!--creates the clipping mask from the shape-->
<use xlink:href="#circle" overflow="visible"></use>
</clipPath>
<!--group containing the image with clipping applied-->
<g clip-path="url(#clip)">
<image overflow="visible" xlink:href="https://s3-us-west-2.amazonaws.com/s.cdpn.io/222579/darwin300.jpg"></image>
</g>
</svg>
Please observe that I've added a viewBox and a width attribute to the svg. If you don't declare the viewBox and the width the svg element will have a size of 300px/150px and the part of the circle that falls outside the svg canvas will be cuted off.
UPDATE
The OP is commenting
I don't want to scale the image, just the mask. Is that possible?
This is how I would do it: In the next example I'm using transitions to scale the circle when you mouse over the svg element:
#c{transform: scale(1);
transition: transform 0.5s;}
svg:hover #c {
transform: scale(1.5);
}
Next comes a working example:
svg {
border: 1px solid;
display: block;
position: absolute;
margin: auto;
top: 0;
bottom: 0;
left: 0;
right: 0;
}
#c{transform: scale(1);
transition: transform 0.5s;}
svg:hover #c {
transform: scale(1.5);
}
<svg viewBox="-150 -150 300 300" width="200">
<defs>
<clipPath id="clip">
<!--creates the clipping mask from the shape-->
<circle id="c" r="100" />
</clipPath>
</defs>
<!--group containing the image with clipping applied-->
<image clip-path="url(#clip)" id="img" xlink:href="https://s3-us-west-2.amazonaws.com/s.cdpn.io/222579/darwin300.jpg" x="-150" y="-150" width="300" height="300"></image>
</svg>
You could do it easily with JavaScript, adding an eventlistener onMouseOver over a class.
However, if you need CSS, you can an animation that will do it,like this.
.zoom {
padding: 50px;
background-color: green;
transition: transform .2s; /* Animation */
width: 200px;
height: 200px;
margin: 0 auto;
}
.zoom:hover {
transform: scale(1.5); /* (150% zoom - Note: if the zoom is too large, it will go outside of the viewport) */
}
</style>
<div class="zoom"></div>

I want to implement SVG clip-path for SVG element

I want to implement SVG clip-path for SVG element. I have a DIV element in which I want to put SVG element which will act as a clipping mask, and also I have the separate SVG element that has an image to which the clipping mask will be applied.
The first problem I faced with is that clipping mask moves to the left top corner of the viewport but not located inside of the parent DIV element.
The second problem is that I want to make an image on the full screen not depending on the screen size.
Incorrect Mask Circle
Correct Mask Circle (what I want to have)
Do you have suggestions how to make it?
Thanks in advance!
html, body { margin:0; padding:0; overflow:hidden }
svg { position:absolute; top:0; left:0;}
.image-clip-src {
width: 100%;
height: 100%;
}
.svg-wrapper {
width: 72px;
height: 72px;
padding: 2.5em;
border: 1px solid #4D4F51;
margin: 0 auto;
border-radius: 50%;
overflow: hidden;
position: fixed;
top: 55%;
z-index: 9;
left: 64%;
transform: translateY(-50%);
cursor: pointer;
}
.clipped-image image {
clip-path: url(#clipping);
}
<svg class="clipped-image" width="100%" height="100%" viewBox="0 0 1440 960" preserveAspectRatio="xMinYMin meet">
<image class="image-clip-src" xlink:href="https://images.unsplash.com/photo-1526327227970-4bda49fa3489?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=3c4bce33d96df6b18af53fb2dae3363e&auto=format&fit=crop&w=1650&q=80" width="100%" height="100%" overflow="visible"/>
</svg>
<div class="svg-wrapper">
<svg class="svg-defs">
<defs>
<clipPath id="clipping">
<circle r="72" stroke="black" stroke-width="3"/>
</clipPath>
</defs>
</svg>
</div>
That's not the way SVG works.
When you tell something to use a clip path, all it sees is the clip path definition itself. It doesn't know or care about where on the page you have positioned it's parent <svg>.
If you want the clip circle to be at a certain position on the water image, you need to specify its position using cx and cy.
html, body { margin:0; padding:0; overflow:hidden }
svg { position:absolute; top:0; left:0;}
.image-clip-src {
width: 100%;
height: 100%;
}
.clipped-image image {
clip-path: url(#clipping);
}
<svg class="clipped-image" width="100%" height="100%" viewBox="0 0 1440 960" preserveAspectRatio="xMinYMin meet">
<defs>
<clipPath id="clipping">
<circle cx="64%" cy="55%" r="72" stroke="black" stroke-width="3"/>
</clipPath>
</defs>
<image class="image-clip-src" xlink:href="https://images.unsplash.com/photo-1526327227970-4bda49fa3489?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=3c4bce33d96df6b18af53fb2dae3363e&auto=format&fit=crop&w=1650&q=80" width="100%" height="100%" overflow="visible"/>
<circle cx="64%" cy="55%" r="72" fill="none" stroke="#4D4F51" stroke-width="1"/>
</svg>

SVG button affects external div display

I am trying to implement the
http://demosthenes.info/blog/760/Create-A-Responsive-Imagemap-With-SVG
to my needs
The problem is that I want the button Ive created to change the style of a div outside the figure tag. I can not find a way to do that.
All I need is by hovering over the .my-1 button, to display the .y1 div
Here is the code so far.
<style type="text/css">
#burj-imagemap {
overflow: hidden;
padding-bottom: 75%;
vertical-align: middle;
width: 100%;
}
#burj-imagemap svg {
display: inline-block;
left: 0;
position: absolute;
top: 0;
}
.my-1:hover {background:#fff; z-index:100; opacity:0.3; filter: alpha(opacity=30); border:1px solid #000;
}
.my-1 {cursor: pointer;}
.y1 {
display: none;
}
.my-1:hover .y1 {
display: block;
background-color: #F00;
height: 250px;
width: 250px;
z-index:1000;
}
</style>
<figure id="burj-imagemap">
<svg preserveAspectRatio="xMinYMin meet" viewBox="0 0 1200 808" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" version="1.1">
<image xlink:href="http://demosthenes.info/assets/images/burj-khalifa.jpg" height="808" width="1200">
</image>
<a class="my-1" >
<g>
<defs>
<polygon id="SVGID_1_" points="322,131 62,240 79,346 274,250 412,405 501,250"/>
</defs>
<clipPath id="SVGID_2_">
<use xlink:href="#SVGID_1_" overflow="visible"/>
</clipPath>
<g clip-path="url(#SVGID_2_)">
<image overflow="visible" width="1200" height="808" xlink:href="http://demosthenes.info/assets/images/burj-khalifa.jpg" transform="matrix(1 0 0 1 -33.5 -301)">
</image>
</g>
</g></a>
</svg>
</figure>
<div class="y1">Hi!</div>
any ideas?
You could include an event handler in the svg like this..
<g clip-path="url(#SVGID_2_)" onmouseover="document.getElementById('y1').style['display'] = 'inline';">
<div id="y1" class="y1">Hi!</div>
fiddle here http://jsfiddle.net/9mDur/