Javascript trigger (progressbar) when on screen - javascript

i am currently making my own 1-page portfolio website for school and i had this cool idea that i want to show how far ive become in some coding languages by using a progressbar, for example, c# = 60% and that would be 60% of a circle. i think i can do that bu using the internet but i would like it to start / end at 60 when i'm scrolling down and it should start the progressbar when it is on screen. i do not know and cannot find on how to trigger the code when the (in this case progressbar) is visible on screen.
note: i am a fairly new javascript programmer and a fairly new user so please explain if i did something wrong.

Here is a working example of triggering an animation when you scroll to 75% of an image's height using the Intersection Observer API:
const images = document.querySelectorAll('.animate-me');
const config = {
root: null, // viewport
rootMargin: '0px',
threshold: 0.75
};
let observer = new IntersectionObserver(function(entries) {
entries.forEach(function(entry) {
if (entry.intersectionRatio >= config.threshold) {
entry.target.classList.add("active");
}
});
}, config);
images.forEach(image => {
observer.observe(image);
});
.spacer {
height: 400px;
}
.animate-me.active {
animation: anim1 .7s ease-out;
}
#keyframes anim1 {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
<div class="spacer">(Scroll down)</div>
<img src="https://picsum.photos/200" class="animate-me">
<div class="spacer"></div>
You should be able to translate this to your own use case, but please share more specifics if you are looking for something else.

Related

JS slider flickering on transform: translate

I have a Vue component that is an image slider, and I use transform: translateX to cycle through the images. I based my work off of Luis Velasquez's tutorial here: https://dev.to/luvejo/how-to-build-a-carousel-from-scratch-using-vue-js-4ki0
(needed to make a couple of adjustments, but it follows it pretty closely)
All works fairly well, except I get a strange flicker after the sliding animation completes, and I cannot figure out why.
In my component I have:
<button
:class="btnClass"
#click="prev"
#keyup.enter="prev"
#keyup.space="prev"/>
<button
:class="btnClass"
#click="next"
#keyup.enter="next"
#keyup.space="next" />
<div class="slider-wrap">
<div class="slider-cards">
<div ref="slidewrap"
v-hammer:swipe.horizontal="handleSwipe"
class="cards"
>
<div class="inner" :style="innerStyles" ref="inner">
<SliderCard v-for="(item, index) in slides"
:key="`${item.id}-${index}`"
:item="item"
/>
</div>
</div>
</div>
</div>
The navigation of those is handled via the following methods (just including the "next" navigation one to spare some redundancy here:
next () {
// translate the inner div left, push first element to last index, and slide
// inner div back to original position
if (this.transitioning) {
return;
}
this.transitioning = true;
const elementToMoveToEnd = this.slides[2];
this.moveLeft();
this.afterTransition(() => {
this.resetTranslate();
this.slides.splice(0, 1);
this.slides.push(elementToMoveToEnd);
this.transitioning = false;
});
},
resetTranslate() {
/// NOTE: this.navigationStep is just a static px value set up elsewhere in my component, based on screenwidth -- it just sets how much the slider should translate based on the card widths.
this.innerStyles = {
transition: 'none',
transform: `translateX(-${this.navigationStep})`
};
},
moveLeft() {
this.innerStyles = {
transform: `translateX(-${this.navigationStep})
translateX(-${this.navigationStep})`
};
},
afterTransition (callback) {
const listener = () => {
// fire the callback (reorganizing slides, resetting the translation),
// and remove listener immediately after
callback();
this.$refs.inner.removeEventListener('transitionend', listener);
};
this.$refs.inner.addEventListener('transitionend', listener);
},
In my CSS, I control the translation animation via:
.inner {
transition: transform 0.2s linear;
white-space: nowrap;
-webkit-transform-style: preserve-3d;
}
(the preserve-3d was a desperate attempt to fix the flickering).
My slides move, but there is a flash immediately after they move -- I suspect it has something to do with competing translations/transitions in the moveLeft and resetTranslation methods, but I've messed with those, and nothing has improved the flashing. If anyone has any ideas, I'd really appreciate it!

which is faster between translateX and translate3d(x,0,0)

I'm learning browser rendering to understand render process and event loop. I always thought translate3d is faster by GPU render with new layer.
today I test in chrome watching by Performance tool tab. find below:
translate3d used 105ms
translateX only 49ms
#keyframes move {
100% {
transform: translateX(300px);
}
}
#keyframes move3d {
100% {
transform: translate3d(300px, 0, 0);
}
}

Slideshow's animation doesn't work

In this Vue component, I tried to make a slideshow.
The logic works this way:
1) Making an array of all sources of pictures I want to put in(array: pictures)
2) Set a variable(Count) to 0, so that it starts from the start.
3) Putting v-bind:src="pictures[count]" on an img tag so that it changes the source by the variable(count)
4) Putting functions on 2 buttons that returns in images or goes forward in images.
<template>
<div>
<img v-bind:src="pictures[count]" alt="">
<button #click="Switching(1)">Forward</button>
<button #click="Switching(-1)">Back</button>
<p>{{this.count + 1}}</p>
</div>
</template>
<script>
export default {
data() {
return {
count: 0,
pictures: [
"http://www.hotel-bb.com/image.htm?id=93652",
"https://s-ec.bstatic.com/images/hotel/max1280x900/681/68184730.jpg",
"https://images.all-free-download.com/images/graphiclarge/hd_picture_of_the_beautiful_natural_scenery_03_166249.jpg",
"https://images.all-free-download.com/images/graphiclarge/the_beach_at_dusk_couple_of_picture_165871.jpg"
],
stop: false
};
},
methods: {
Switching: function(n) {
this.count += n;
if (this.count > this.pictures.length - 1) {
this.count = 0;
} else if (this.count < 0) {
this.count = this.pictures.length - 1;
}
}
}
};
</script>
<style scoped>
#keyframes slideInFromLeft {
0% {
transform: translateX(-100%);
}
100% {
transform: translateX(0);
}
}
img {
max-width: 800px;
height: 500px;
animation: 1s ease-out 0s 1 slideInFromLeft;
}
</style>
It works properly. The problem is that when I put an animation on it, it doesn't work except for the first picture that loads, when I switch by the two buttons, the pictures don't get animated.
I tried transition: 0.5s, animation and Keyframes and nothing works. I'm guessing that it is because the pictures don't appear but they get loaded and src gets changed. How I can make it work?
For building a slideshow on Vue JS, I suggest Vueper Slides. It will do all that for you.
Unless it is for a learning purpose.

CSS or JS transition for button that changes size from text changes?

I have an Angular app with a button that has a label of "+"
On mouse-over I call element.append(' Add a New Number'); This adds that text new to the + in the label.
Use clicks the button, new number is added, label of button is returned to "+"
I would like to animate the button size change and/or the txt label change. So far, just adding a css transition to width does nothing.
Thoughts?
UPDATE:
To help clarify, this is a bootstrap input group button. I don't want to set widths or css transforms, to avoid breaking the group either here or at other screen sizes.
here are the 2 states:
I was simply letting the existing button stretch due to the injection of more words.
I am probably guessing you don't have a predefined width. anyways you could use transform-origin and scale to achieve such an effect
FIDDLE HERE
HTML:
<button id="btn">Click</button>
CSS:
#btn {
outline: none;
border:none;
background: orange;
padding: 1em 1.5em;
-webkit-transition: .3s;
-o-transition: .3s;
transition: .3s;
}
#btn:hover {
-webkit-transform: scaleX(1.2);
-ms-transform: scaleX(1.2);
-o-transform: scaleX(1.2);
transform: scaleX(1.2);
-webkit-transform-origin:0 0;
-moz-transform-origin:0 0;
-ms-transform-origin:0 0;
-o-transform-origin:0 0;
transform-origin:0 0;
}
you should use CSS transforms for animations rather than a property like width. The animation is slightly jerky , so you might want to work on it a bit more.
You had jQuery tagged, so this is how I would do it.
All the transitions. fade + animate
function changeButtonText(button, text){
// jQuery it
$button = $(button);
// get orinal css'es
oooon = $button.css('text-align');
doooo = $button.css('overflow');
treee = $button.css('white-space');
$button.css('text-align', 'left').css('overflow', 'hidden').css('white-space', 'nowrap');;
// get new width first
$tmpBtn = $button.clone().append(text).css('opacity', '0.0').appendTo('body');
newWidth = $tmpBtn.outerWidth();
$tmpBtn.remove();
// now stretch the button out
$button.animate({width: newWidth+"px"});
// fade texts into the butt
$button.append('<span style="display:none">'+text+'</span>');
$btnText = $button.find('span').fadeIn('slow');
return {
'text-align':oooon,
'overflow':doooo,
'white-space':treee
};
}
Fiddle
I think that with bootstrap CSS and Angular - it will be more complex, but this is how I would go about it programatically. You'll have to deal with the model and the data differently - and you should probably build a directive to repeat the action and integrate with Angular smoothly:
HTML
<div class="thing">+ <span id="message">
<span id='target'></span>
</span></div>
JavaScript
$('.thing').hover( function() {
var originalWidth = $(this).outerWidth();
$messageHolder = $(this).find('#message');
$target = $(this).find('#target');
$target.text('Some helpful text');
var targetWidth = $target.outerWidth();
$messageHolder.animate({
width: targetWidth
}, {
duration: 200,
complete: function() {
$messageHolder.animate({
opacity: 1
}, 500);
}
});
});
$('.thing').on('click', function() {
$target = $(this).find('#target');
$target.empty();
$messageHolder = $(this).find('#message');
$messageHolder.animate({
opacity: 0
}, {
duration: 200,
complete: function() {
$messageHolder.animate({
width: 0
}, 200);
}
});
});
I'm sure that Angular's ng-animate library watches the dom and also has an excellent way of animating things as they change in the model/controller or whatever they are calling it. This is probably something what it looks like behind the scenes.
Good luck!
jsFiddle

How can I start CSS3 Animations at a specific spot?

I'm using CSS3 Animations, and I want to be able to move to a specific spot in the animation. For instance, if the CSS looks like this (and pretend that I used all the proper prefixes):
#keyframes fade_in_out_anim {
0% { opacity: 0; }
25% { opacity: 1; }
75% { opacity: 1; }
100% { opacity: 0; }
}
#fade_in_out {
animation: fade_in_out_anim 5s;
}
then I would like to be able to stop the animation, and move it to the 50% mark. I guess that the ideal JavaScript would look something like this:
var style = document.getElementById('fade_in_out').style;
style.animationPlayState = 'paused';
// Here comes the made up part...
style.animation.moveTo('50%'); // Or alternately...
style.animationPlayPosition = '50%';
Does anyone know of a way to make this happen (hopefully in Webkit)?
We can use the animation-delay property. Usually it delays animation for some time, and, if you set animation-delay: 2s;, animation will start two seconds after you applied the animation to the element. But, you also can use it to force it to start playing animation with a specific time-shift by using a negative value:
.element-animation{
animation: animationFrames ease 4s;
animation-delay: -2s;
}
http://default-value.com/blog/2012/10/start-css3-animation-from-specified-time-frame/

Categories

Resources