Rotating text with Javascript - javascript

I'd like to cycle through an array of words creating a text rotation affect. I have most of it working as expected. Is there any way I can use a css transition on the length of the p element?
When traversing from an object with char.length > 10 to an object with char.length < 5 (for example) the movement isn't smooth and I'd like to ease the movement of the text around the word rather than abruptly jumping backwards (or forwards depending on the length of the word)
HTML:
<p><span id="description-rotate"></span> something built on something else.</p>
SASS:
#-webkit-keyframes rotate-text
0%
opacity: 0
30%
opacity: 1
50%
opacity: 1
70%
opacity: 1
100%
opacity: 0
p
font-family: 'Helvetica', sans-serif
.rotate-text
-webkit-animation: rotate-text 3050ms cubic-bezier(0.645, 0.045, 0.355, 1.000) infinite
-moz-animation: rotate-text 3050ms cubic-bezier(0.645, 0.045, 0.355, 1.000) infinite
-o-animation: rotate-text 3050ms cubic-bezier(0.645, 0.045, 0.355, 1.000) infinite
animation: rotate-text 3050ms cubic-bezier(0.645, 0.045, 0.355, 1.000) infinite
Javascript:
var descriptionArray = ['some text', 'some more text', 'some even longer text'];
var descriptionLength = descriptionArray.length;
var description = $('#description-rotate');
function loop(i) {
description.text(descriptionArray[i%descriptionLength]);
setTimeout(function() {
loop(i+1);
description.addClass('rotate-text');
}, 3050); // This duration must match the length of the animation
}
loop(0);
I realize this may be a poor way of explaining my goal, check out the CodePen for a better idea of what I'm trying to create.
Thanks!
See: http://codepen.io/anon/pen/JueGx

A simple example using jQuery
is by storing the desired looping / swapping words into the data-* attribute:
$("[data-words]").attr("data-words", function(i, words) {
var $self = $(this).text(""),
words = words.split("|"),
tot = words.length,
c = 0;
for(var i=0; i<tot; i++) $self.append($('<span/>',{text:words[i]}));
var $words = $self.find("span");
(function loop(){
$self.animate({ width: $words.eq( c ).width() });
$words.stop().fadeOut().eq(c).fadeIn().delay(1000).show(0, loop);
c = ++c % tot;
}());
});
/* DATA-WORDS Loop/swap words in sentence */
[data-words] {
vertical-align: top;
position: static;
}
[data-words] > span {
display: none;
position: absolute;
color: #0bf;
}
<p>
This is <span data-words="some|an interesting|some longer">some</span> text
</p>
<p>
Say <span data-words="hi|wow">hi</span> to <span data-words="Javascript|Stack Overflow">mom</span>
</p>
<script src="//code.jquery.com/jquery-3.1.0.js"></script>
The | -delimited words will be converted to Array and finally to child <span> elements
Such span elements need to be absolutely positioned inside the parent span
jQuery will than init a recursive loop, calculate the next word width, and animating it (fade + width)

How about jQuery's animate() function?
http://api.jquery.com/animate/
You can trigger an animation for each word in the array. Here's an idea, you will have to figure out how populate the variables hasMoreWordsInTheArray and nextWordInTheArray:
function animateParagraphTag(word) {
if(hasMoreWordsInTheArray) {
//some special code to calculate the best width based on the word's length (theNewWidthValue)
$('p').animate(
{ width: theNewWidthValue },
"fast",
animateParagraphTag(nextWordInTheArray)
);
}
}
You will have to calculate the width based on the length of the words and place that within the parameters of the animation, then, once the p tag finishes the expansion/contraction accordingly, it will trigger the callback function, you can then move on to the next element (word) of the array.

Related

How to set animation state to finish

I've created a slider animation as demonstrated below:
#mixin progress {
#-webkit-keyframes interval {
from {
width: 0;
}
to {
width: 100%;
}
}
animation: var(--duration) linear 0s interval;
animation-play-state: var(--playState);
}
.slider-item {
#include progress;
}
When a click event fires my task is to make the current slider animation be completed.
I have tried to select the target element for example:
this.$refs[`slider-item-${id}`]
Nevertheless, the animation property is still empty, is there something that i'm missing here? or is there a better alternative for that? (i have tried the API https://developer.mozilla.org/en-US/docs/Web/API/Element/animate without success)
Try to replace
animation: var(--duration) linear 0s interval;
with
animation: var(--duration) linear 10ms forwards;
to see the animation end as the last state remaining on your page.

CSS page transition by adding & removing a class (Vanilla JavaScript)

I'm attempting to create a transition that quickly fades in the page on load and then when a link is clicked, the page fades out and moves up slightly.
To do this I created the class 'is-loaded' which I would apply to the elements ('wrapper' and 'page-fade'). When the document is loaded, the 'is-loaded' class would be added, then when a link is clicked, the same class would be removed from both elements.
The code:
.wrapper {
transform: translateY(-25px);
transition: transform cubic-bezier(0.25, 0.46, 0.45, 0.94) 0.3s;
}
.wrapper.is-loaded {
transform: translateY(0);
}
.page-loader {
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
background-color: #ffffff;
z-index: 999999;
transition: opacity cubic-bezier(0.25, 0.46, 0.45, 0.94) 0.4s, visibility cubic-bezier(0.25, 0.46, 0.45, 0.95) 0.4s;
}
.page-loader.is-loaded {
opacity: 0;
visibility: hidden;
}
document.querySelectorAll('a').forEach(e => {
e.addEventListener('click', function() {
event.preventDefault()
var i = this.getAttribute('href')
var wrapper = document.querySelector('wrapper');
var pageloader = document.querySelector('page-loader');
wrapper.classList.remove('is-loaded'),
setTimeout(function() {
pageloader.classList.remove('is-loaded');
}, 80),
setTimeout(function() {
window.location = i
}, 100)
})
})
document.addEventListener("DOMContentLoaded", function() {
var wrapper = document.querySelectorAll('wrapper');
var pageloader = document.querySelectorAll('page-loader');
wrapper.classList.add('is-loaded'),
pageloader.classList.add('is-loaded');
})
I'm new to writing in JavaScript so i'm unsure why my code does nothing. Is there a way to get this to work? No jQuery please and just vanilla js. Thank you.
You're missing the prefix selector notation . necessary to find 'wrapper' or 'page-loader' with document.querySelector()|document.querySelectorAll(). In both cases, you'd use the same kind of selector syntax as you do in your CSS.
var wrapper = document.querySelectorAll('.wrapper');
var pageloader = document.querySelectorAll('.page-loader');
Also, document.querySelectorAll() returns a(n Array-like) HTML NodeList, which doesn't have a classList property. You could convert the NodeList to an Array and iterate through the result, adding to the classList of each element or, if you know there's only one of what you're looking for on the page, swap document.querySelectorAll() for document.querySelector() — which will return a single element.

Vanilla Javascript - Animation with different timing

I would like to make an animation using onscroll in Vanilla Javascript. I have 2 classes. The first one is .photography_box which is active and the second one is .photography_box_active which is not active. When i scroll down to 1500px my second class .photography_box_active kicks in and my animation is working great. My .photography_box consist of 12 boxes. When the animation happens all of them come in at the same time which is not what i want. I would like each one of them to come in one after the other. In jQuery i could use $.each but i would like to have the same effect using Vanilla Javascript. Can someone help me solve the problem?
Thanks
CSS code for my classes :
.photography_box {
overflow: hidden;
position:relative;
cursor: pointer;
margin-bottom:20px;
opacity: 0;
cursor: pointer;
-webkit-transform:translateX(-50px);
transform:translateX(-50px);
-webkit-transition: all .3s ease-in-out;
transition: all .3s ease-in-out;
}
.photography_box_active {
opacity: 1;
-webkit-transform: translateX(0px);
transform: translateX(0px);
}
JS code is :
var photoBox = document.getElementsByClassName("photography_box");
window.onscroll = function() {
loopBox()
};
function loopBox(){
if ( window.pageYOffset > 1500 ){
for ( f = 0; f <= photoBox.length -1; f++ ) {
photoBox[f].classList.add("photography_box_active");
};
};
};
You can use setTimeout in your loop to delay the animation for each item based on its index. So if you want a delay of 150ms:
for ( f = 0; f < photoBox.length; f++ ) {
setTimeout(function(){
photoBox[f].classList.add("photography_box_active");
}, 150 * f);
}
Note that as you know in advance the number of items, and as you are using css transitions, this could be done purely in css, keeping your existing js code. Supposing your .photography_box items are in a .box container
.box .photography_box:nth-child(1) { transition-delay: 0 }
.box .photography_box:nth-child(2) { transition-delay: 0.05s }
// and so on...
quite cumbersome to write, especially with vendor-prefixes, but nothing annoying if you are using a css preprocessor like sass
Example: array.forEach(callback[, thisArg])
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach

Dynamically set css transform before transition

I am trying to simulate a mouse animation. I would like to dynamically set the position, then move it with a css transition. So far I am able to get a program that moves the mouse. However, I am having trouble setting the initial position dynamically with javascript. My code looks like this:
Here is the CSS
.cursorDiv {
width: 30px;
height: 30px;
transform: translate(0px,0px);
transition: 2s ease;
}
.cursorDivMoved {
transform: translate(100px,200px);
}
Here is the javascript:
var cursorDiv = document.createElement("img");
cursorDiv.className = "cursorDiv";
cursorDiv.src="https://cdn2.iconfinder.com/data/icons/windows-8-metro- style/512/cursor.png";
document.body.appendChild(cursorDiv);
setTimeout(function() {
$(".cursorDiv").toggleClass("cursorDivMoved");
}, 1000);
//cursorDiv.style.transform="translate(100px,50px)";
When I run this it works fine. However, when I try to change the initial position with javascript (uncomment last line), then the transition doesn't occur anymore.
Here is a Demo:
https://jsfiddle.net/fmt1rbsy/5/
If you programmatically set the style.transform property directly on your element (which you need if you want to move it to an arbitrary position through JS), it will override any transform specified in classes. Hence adding "cursorDivMoved" class later on does not transform (translate / move) it.
You have to continue moving it by specifying its style.transform property, or simply remove it: cursorDiv.style.transform = null
Demo: https://jsfiddle.net/fmt1rbsy/9/
You may also want to have the very first translate being transitioned. In that case, you have to wait for the browser to make an initial layout with your element at its start position, otherwise it will see no transition (it will see it directly after the transform is applied, i.e. at its final position). You can either:
Use a small (but non zero) setTimeout to give some time for the browser to do its initial layout.
Force a browser layout by trying to access some property that require the browser to compute the page layout (e.g. document.body.offsetWidth).
Use 2 nested requestAnimationFrame's before applying your transform.
Demo: https://jsfiddle.net/fmt1rbsy/8/
Is this what you are looking for? Tell me if it can be improved. Open your console and change the class name to cursorDivMoved.
var cursorDiv = document.createElement("img");
cursorDiv.className = "cursorDiv";
cursorDiv.id = 'cursorDiv';
cursorDiv.src = "https://cdn2.iconfinder.com/data/icons/windows-8-metro-style/512/cursor.png";
document.body.appendChild(cursorDiv);
#cursorDiv {
width:30px;
height:30px;
-o-transition: 2s ease;
-moz-transition: 2s ease;
-webkit-transition: 2s ease;
-ms-transition: 2s ease;
transition: 2s ease;
}
.cursorDivMoved {
-o-transform:translate(100px, 200px);
-moz-transform:translate(100px, 200px);
-webkit-transform:translate(100px, 200px);
-ms-transform:translate(100px, 200px);
transform:translate(100px, 200px);
}
You can define initial postion (x,y), and then when user click the position will increase and set to the 'cursorDiv', such as:
var cursorDiv = document.createElement("img");
cursorDiv.className = "cursorDiv";
cursorDiv.src="https://cdn2.iconfinder.com/data/icons/windows-8-metro-style/512/cursor.png";
document.body.appendChild(cursorDiv);
var x = 100, y = 50;
setTimeout(function() {
cursorDiv.style.transform="translate(100px,50px)";
}, 1000);
$(document).click(function () {
x+= 20;
y += 50;
var str = "translate(" + x + "px," + y + "px)";
cursorDiv.style.transform=str;
});
Here is Demo

How to remove a div with fade out effect in JavaScript?

I want to remove a div element on click event but i want to remove it with a fade out effect. I have got some JQuery solution but i need pure JavaScript or css solution.
document.querySelector('.list').addEventListener("click", function(e){
if (e.target.localName === "span") {
var removeTarget = e.target.parentNode.parentNode;
removeTarget.parentNode.removeChild(removeTarget);
};
});
This code is removing the div element with no effect. How can i add a fade out effect?
I've made this function a while ago for a personal project:
function removeFadeOut( el, speed ) {
var seconds = speed/1000;
el.style.transition = "opacity "+seconds+"s ease";
el.style.opacity = 0;
setTimeout(function() {
el.parentNode.removeChild(el);
}, speed);
}
removeFadeOut(document.getElementById('test'), 2000);
There are two ways you can achieve this: CSS3 animation or jQuery animation.
CSS3 Animation
In your CSS document, add:
.list {
opacity: 1;
-webkit-transition: opacity 1000ms linear;
transition: opacity 1000ms linear;
}
This will make any change of opacity to your item fade by 1000ms.
Change line 4 of your JavaScript to:
removeTarget.style.opacity = '0';
setTimeout(() => removeTarget.remove(), 1000);
This will make your item change opacity to 0, thus making the transition from step 1 have an effect. Then it will remove the item with your code after 1000ms.
Note: Make sure the time of the CSS3 transition and the setTimeout are the same.
jQuery Animation
Get jQuery
Go to the jQuery Website and download it, or
Add ` in your HTML document before any jQuery code.
Change line 4 of your Javascript to:
removeTarget.fadeOut(1000)
This will Fade Out your item by 1000ms, you can change this time to whatever you want.
In 2020 you can forgo use of use setTimeout for the animationend event, removing the need to maintain the duration in two places:
.fade-out {
animation: fade 2s;
-webkit-animation: fade 2s;
-moz-animation: fade 2s;
}
/* Animate opacity */
#keyframes fade {
from { opacity: 1 }
to { opacity: 0 }
}
#-moz-keyframes fade {
from { opacity: 1 }
to { opacity: 0 }
}
#-webkit-keyframes fade {
from { opacity: 1 }
to { opacity: 0 }
}
const elementToFade = document.getElementById('my-element');
elementToFade.onanimationend = (e) => {
if (e.target.classList.contains('fade-out')) {
elementToFade.parentNode.removeChild(elementToFade);
}
};
// To fade away:
elementToFade.classList.add('fade-out');
It's a good question, but to animate some element in html, this element has to exist while it is animating. So, you have some ways to do this, a good way is hide this element with CSS and after the animation you remove this element. While you hiding you can animate, you can see this example:
<style>
.hide{
opacity: 0;
}
.fade-out {
transition:1s linear all;
}
</style>
<span class="list fade-out">
This is a List, click me to hide
</span>
<script>
document.querySelector('.list').addEventListener("click", function(e) {
if (e.target.localName === "span") {
//Add CSS hide and animate with fade out
var currentCSS = this.className;
this.className = currentCSS + ' hide';
var removeTarget = e.target.parentNode.parentNode;
setTimeout(function(){
removeTarget.parentNode.removeChild(removeTarget);
},1000);
};
});
</script>
Add the following CSS class to the element using elem.className="my-animation"; on click:
.my-animation {
animation: fade 3s steps(90) forwards;
-webkit-animation: fade 3s steps(90) forwards;
-moz-animation: fade 3s steps(90) forwards;
}
#keyframes fade {
from {
opacity: 1;
}
to {
opacity: 0.0;
}
}
You may control the speed of the animation by modifying the steps(number) as well.
Just goto jQuery source code, take out the fade code which is in pure javascript, and use it, no need to reinvent the wheel,
or a hint is reduce the height of div to 0 slowly using setTimeInterval()
or a css solution would be to use transform and transition properties

Categories