Change class after hovering for a second over svg polygon - javascript

I have a SVG polygon displayed, what I want to do is:
When mouse is hovered over the object, wait for one second and then change the class.
If user hovers out, before one second nothing happens.
What I would like to achieve is something like http://codepen.io/jdsteinbach/pen/CsypF but the svg element must only glow after a second.
What I have so far is:
$("#firstObject").stop().hover(
function() { //hovered in
//delay it and add new class
console.log("hovered in");
setTimeout(function() {
console.log("hovered in in");
$("#firstObject").attr("class", "SVGOverVideo1 hoveredObject");
}, 1000);
}, function() { //hovered out
//remove class
$("#firstObject").attr("class", "SVGOverVideo1");
console.log("hovered out");
}
);
.SVGOverVideo1 {
fill: transparent;
stroke: purple;
stroke-width: 2;
position: absolute;
z-index: 1;
top: 0%;
left: 0%;
}
.hoveredObject {
border: double;
border-color: white;
}
<svg class="SVGOverVideo" id="objectsOverVideoContainer">
<polygon id="firstObject" class="SVGOverVideo1" points="200,10 250,190 160,210"></polygon>
Sorry, your browser does not support inline SVG.
</svg>
Thanks!!

You can do it with css only using transition with delay:
transition: stroke 0.01s 1s;
The 1s delays the actual transition, and the actual transition time is so small to that no actual transition occurs.
body {
background: black;
}
.SVGOverVideo1 {
fill: transparent;
stroke: purple;
stroke-width: 2;
position: absolute;
z-index: 1;
top: 0%;
left: 0%;
}
.SVGOverVideo1:hover {
stroke: white;
transition: stroke 0.001s 1s;
}
<svg class="SVGOverVideo" id="objectsOverVideoContainer">
<polygon id="firstObject" class="SVGOverVideo1" points="200,10 250,190 160,210"></polygon>
Sorry, your browser does not support inline SVG.
</svg>

Related

issue with line through animation

I want to create a simple line through animation and so far I'm here:
.strikethrough {
display: inline-block;
position: relative;
line-height: 1.5em;
}
.strikethrough:after {
content: '';
position: absolute;
display: block;
width: 100%;
height: 1px;
box-shadow: 0 1px rgba(252, 3, 3,0.7);
margin-top: -0.7em;
background: rgba(252, 3, 3,0.8);
transform-origin: center left;
animation: strikethrough 1s 0.5s cubic-bezier(.55, 0, .1, 1) 1;
}
#keyframes strikethrough {
from {
transform: scaleX(0);
}
to {
transform: scaleX(1);
}
}
<span class="strikethrough">Favor packaging over toy</span>
As you see everything works fine except two things:
Now we can see the line at first then it hides and starts the animation, I want to see only the animated line.
I want to initiate the animation using javascript... but with this pseudo-element (after) it seems complicated!
You can fix your animation using animation-fill-mode:
animation-fill-mode: backwards;
To trigger your animation, just add the strikethrough class. The thing where I think this won't work is when you have a multiline text, as your ::after won't cover that.
document.querySelector( '.strikethrough' ).addEventListener( 'click', event => { event.target.classList.toggle( 'strikethrough' ); });
.strikethrough {
display: inline-block;
position: relative;
line-height: 1.5em;
}
.strikethrough:after {
content: '';
position: absolute;
display: block;
width: 100%;
height: 1px;
box-shadow: 0 1px rgba(252, 3, 3,0.7);
margin-top: -0.7em;
background: rgba(252, 3, 3,0.8);
transform-origin: center left;
animation: strikethrough 1s 0.5s cubic-bezier(.55, 0, .1, 1) 1;
animation-fill-mode: backwards;
}
#keyframes strikethrough {
from {
transform: scaleX(0);
}
to {
transform: scaleX(1);
}
}
<span class="strikethrough">Favor packaging over toy</span>
Personally, I would take this simpler tack to reduce the amount of actual objects on screen, and the amount of code, by using a background image to scale. If cleverly set up, you could even multi-line this (by making the background the line height and having a middle pixel in it - and with SVGs you could ensure it was only 1px regardless of the stretching etc...).
document.querySelector( 'p' ).addEventListener( 'click', event => {
event.target.classList.toggle( 'strikethrough' );
})
#keyframes stretch {
to { background-size: 100% var(--line-height); }
}
:root {
--line-height: 1.2em;
}
p {
line-height: var(--line-height);
}
.strikethrough {
line-height: 1.2em;
background: url('data:image/svg+xml;charset=utf8,<svg xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="none"><line x1="0" y1="50%" x2="100%" y2="50%" stroke="black" stroke-width="1px" /></svg>') repeat-y 0 0 / 0 var(--line-height);
animation: stretch 4s;
animation-fill-mode: forwards;
}
<p>Hello World!<br />Another line, does it work?</p>

Make animation keyframes repeat infinitely

I am making a countdown timer circle. The animation works fine on the first iteration, but the circle animation always stays full after the first iteration and does not rest. The number continues to work correctly and rests back to 20, counting down again. I need the red countdown line to copy this.
First time:
Second time:
I have tried adding things like
animation: circletimer 59s linear infinite forwards;
and
animation-iteration-count: infinite
But I can't seem to make the animation happen more than once.
The code that I currently have is:
Countdown component -
interface IProps {
countdown: number
}
const CountDownCircle: FunctionComponent<IProps> = ({
countdown,
}) => {
console.log(countdown)
return (
<div className={'countdown__circle'}>
<svg className={'countdown__circle-svg'} width="200px" height="200px">
<circle className={'circle'} cx="100" cy="100" r="28" />
</svg>
<span className={'timer'}>{countdown}</span>
</div>
)
}
export default CountDownCircle
css(scss) -
.countdown__circle {
position: absolute;
bottom: 34px;
right: 47px;
}
#keyframes circletimer {
0% {
stroke-dashoffset: 500;
stroke-dasharray: 500;
}
100% {
stroke-dashoffset: 0;
stroke-dasharray: 500;
}
}
.countdown__circle-svg {
background-color: transparent;
position: absolute;
background-color: transparent;
top: 50%;
left: 50%;
transform: translate(-50%, -50%) rotateZ(-90deg);
.circle {
stroke: $red;
stroke-width: 5;
stroke-linecap: round;
fill: transparent;
stroke-dashoffset: 500;
stroke-dasharray: 0;
animation: circletimer 59s linear infinite forwards;
}
}
.timer {
position: absolute;
display: block;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
color: $black;
font-size: 25px;
font-weight: 100;
font-family: $proximaBold;
}
Any advice on how to make this animation happen infinitely would be helpful.
You must remove forwards from your aniamtion, as forwards indicates that animation stays like it is after the first run.
animation: circletimer 59s linear infinite;
W3Schools description for aniamtion-fill-mode:forwards is: "The element will retain the style values that is set by the last keyframe (depends on animation-direction and animation-iteration-count)"

Css Animation Keyframes Doesn't start when tab out

I have a css animation that basically starts only after 10 seconds. However, sometimes, if I'm on another tab before the animation starts and I stay on that tab, the animation starts only when I return to the tab / page that has the animation.
document.getElementById('CircleTimer').getElementsByTagName('circle')[0].style.animation = ' countdown 10s linear infinite';
#CircleTimer circle {
stroke-dasharray: 200px;
stroke-dashoffset: 0px;
stroke-width: 2px;
stroke: #04e004;
fill: none;
}
#keyframes countdown {
from {
stroke: #04e004;
stroke-dashoffset: 0px;
}
to {
stroke: #dd0000;
stroke-dashoffset: 200px;
}
}
<svg id="CircleTimer">
<circle r="31" cx="35" cy="35"></circle>
<span id="CountDown">10</span>
</svg>
Update: I'm pretty sure now that the issue is with :
document.getElementById('CircleTimer').getElementsByTagName('circle')[0].style.animation = ' countdown 10s linear infinite';
It seems to not give those properties until I'm on the page.
I made a Jsfiddle to give you an example.
https://jsfiddle.net/8L8vfjsg/

How to to hide text and show on click

I have one dark division box I want to develop such thing when you click and hold mouse over div one round shape div will transparent and it will show hidden sentence under that dark div.
give that div box a class e.g darkBox then in css
u can also give "active" property for clicking
border-radius can make it round, if u give 50% it will make it circle, if u want corner edges round or curved u can give values less than this
.darkBox:hover{
background-color: transparent;
border-radius: 50%;
}
I hope this helps ,if not can you please tell me what u exactly require
Key point:
A round shape can easily be made by using border-radius: 50%.
The pseudo-class :hover is what activates the alternate state.
The pseudo-class :before (and :after) can insert into an element some text.
The extra fading effects were done with transition.
.orb {
font-size: 3em;
border: 2px solid black;
border-radius: 50%;
height: 1.5em;
width: 1.5em;
text-align: center;
cursor: pointer;
background-color: black;
}
.orb:before {
content: '\2620';
transition: opacity 3.5s ease-in, color 4s linear;
opacity: 0;
color: transparent;
}
.orb:hover:before {
content: '\2620';
opacity: 1;
color: white;
}
.cap:after {
content: '';
transition: opacity 3.5s ease-in, color 4s linear;
opacity: 0;
color: transparent;
}
.orb:hover .cap:after {
content: 'The skull and crossbones is actually a font character';
opacity: 1;
color: red;
font: 400 16px/.3 'Palatino Linotype';
white-space: nowrap;
}
<figure class="orb">
<figcaption class="cap"></figcaption>
</figure>

Trigger opacity transition on mouse in and out

I want to trigger a opacity transition. If an element is hovered by the cursor, the cursor shall fade out, change its background-image and then fade in again. I wanted to achieve that by adding and removing a css class. It's not working, what is wrong?
js fiddle
HTML
<div class="wrapper">
<div class="cursor">
</div>
<div id="grey">
</div>
</div>
CSS
.wrapper {
width: 100%;
height: 100%;
background-color: lightgrey;
padding: 60px;
cursor: none;
}
#grey {
width: 100px;
height: 100px;
background: grey;
}
.cursor {
position: fixed;
width: 20px;
height: 20px;
pointer-events: none;
opacity: 0;
-webkit-transition: opacity .3s; /* Safari */
transition: opacity .3s;
}
.red {
background: red;
opacity: 1;
}
.green {
background: green;
opacity: 1;
}
JS
$('.wrapper').on('mousemove', function(e){
$('.cursor').css('left', e.clientX-10).css('top', e.clientY -10);
if ($.contains($('.wrapper')[0], e.target)){
$('.cursor').removeClass('green').addClass('red');
}else{
$('.cursor').removeClass('red').addClass('green');
}
});
DEMO HERE
Ok, here you go. You need to keep track of 2 things here which you already achieved partially and also wait for fadeOut to complete and add a callback for adding and removing respective class
Whether cursor has entered element
Whether cursor has left element
Below is how you could actually do it.
var entered=false;//global variables to show the position of cursor
var left=false;
$('.wrapper').on('mousemove', function(e){
$('.cursor').css('left', e.clientX-10).css('top', e.clientY -10);
if ($.contains($('.wrapper')[0], e.target)){
if(!entered)
{
//just to do it once and not on every mousemove you need to check here whether
//it has already entered and moving inside the element
entered=true;
left=false;//to check the vice versa operation
$('.cursor').fadeOut('fast',function(){
//callback function after fadeOut completes
$(this).removeClass('green').addClass('red');
}).fadeIn('fast');
}
}else{
if(!left)
{
left=true;
entered=false;
//same goes here too
$('.cursor').fadeOut('fast',function(){
$(this).removeClass('red').addClass('green');
}).fadeIn('fast');
}
}
});
you have to change background color , not opacity ( opacity is always 1 )
CSS
.cursor {
position: fixed;
width: 20px;
height: 20px;
pointer-events: none;
opacity: 0;
-webkit-transition: background-color .3s; /* Safari */
transition: background-color .3s ;
}
.red {
background-color: red;
opacity: 1;
}
.green {
background-color: green;
opacity: 1;
}
So you said your question is wrong, it is "no, I just made it easier for hier, in reality it is an background image" - so you transition between two background-images.
Here is how you do it:
You can not do it with CSS transition in ONE element/div
You will have to make two divs wich one background each
Increase the zIndex of the div you want to fade out in by one
Fade out div, while the new div stays at opacity: 1

Categories

Resources