Reputation: 53
Essentially my ultimate goal was to get a fading text effect from left to right, and after a few days of trial and error I ended up here.
The function is supposed to grab all divs determined by class name, loops through the divs, and per each div assign the text out of it to a string, then iterate over each character in the string and apply opacity transition effects. I was trying to get it to work so I could tell if the transition would happen concurrent with for loop iterations, or does the loop wait until the transition is complete before going to the next character, which wouldnt get it to where I want. If somehow thats the case I was thinking of maybe a recursive algorithm if its possible javascript (have the loop go to the next character and begin transitioning when the 1st transition reached a certain percent so the original transition triggers the next etc etc)
<DOCTYPE! Html>
<html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<style> .text{opacity: 0;} </style>
<script>
function fadeDivs(){
var divs = document.getElementsByClassName("text");
for(i=0; i<divs.length(); i++){
var string = divs[i].text();
for(j=0; j<string.length(); j++){
var letter = string.charAt(j);
letter.style.transition = "opacity 1s ease 0s";
letter.style.opacity = 1;
}
}
}
</script>
</head>
<body onload="fadeDivs()">
<div class="text"> this text should appear from left to right </div>
<div class="text"> this text should appear from left to right </div>
</body>
</html>
Updated attempt: Will go from 1 to 0, but not 0 to 1.
<DOCTYPE! Html>
<html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<style>
.text{opacity:1;}
}</style>
<script>
function fadeDiv(string) {
$(string).each(function() {
var str = $(this).html();
str = str.trim().split("");
var newDiv = "";
for (var i = 0, end = str.length; i < end; i++) {
newDiv += '<span>' + str[i] + '</span>';}
$(this).html(newDiv);
});
}
$('document').ready(function() {
var str= $('.text');
fadeDiv(str);
$("span").each(function(i) {
$(this).animate({opacity:0},i*15);
});
});
</script>
</head>
<body>
<div class="text"> this text should appear from left to right </div>
<div class="text"> this text should appear from left to right </div>
</body>
</html>
Upvotes: 0
Views: 107
Reputation: 53
So based off the update above I ended up here, and it works perfectly. Thanks for everyone's efforts and inputs.
What this does is take all divs with the text class, and create a new string of characters wrapped in span tags in order to hide them individually and allow for a incremented fade in effect
<DOCTYPE! Html>
<html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<style>
span{display: none;}
}</style>
<script>
function fadeDiv(string) {
$(string).each(function() {
var str = $(this).html();
str = str.trim().split("");
var newDiv = "";
for (var i = 0, end = str.length; i < end; i++) {
newDiv += '<span>' + str[i] + '</span>';}
$(this).html(newDiv);
});
}
$('document').ready(function() {
var str = $('.text');
fadeDiv(str);
$("span").each(function(i) {
$(this).delay(i*50).fadeIn(300);
});
});
</script>
</head>
<body>
<div class="text"> this text should appear from left to right </div>
<div class="text"> this text should appear from left to right </div>
</body>
</html>
Upvotes: 1
Reputation: 22992
To animate each letter's opacity you would have to put all letters in a span
element, which is not very efficient if you have a large amount of text. I prefer defining an svg
linearGradient
, mask
the text and use JavaScript to animate the x1
and x2
values, which will give you exactly what you are trying to achieve.
Note: The CSS mask
property doesn't work on Chrome, checkout the workaround for Chrome below.
var grad = document.getElementById('gradient');
var animSpeed = 70;
for (i = 0; i < 50; i++) {
var anim = setTimeout(function() {
var x1 = (parseInt(grad.getAttribute('x1').slice(0, -1), 10) + 1) + '%';
var x2 = (parseInt(grad.getAttribute('x2').slice(0, -1), 10) + 1) + '%';
grad.setAttribute('x1', x1);
grad.setAttribute('x2', x2);
}, animSpeed * i);
}
.text {
mask: url(#mask);
}
<div class="text">This text should appear from left to right</div>
<div class="text">This text should appear from left to right</div>
<svg>
<defs>
<linearGradient id="gradient" x1="-15%" y1="0%" x2="0%" y2="0%">
<stop stop-color="white" offset="0" />
<stop stop-color="black" offset="1" />
</linearGradient>
<mask id="mask" maskUnits="objectBoundingBox" maskContentUnits="objectBoundingBox">
<rect y="0" width="1" height="1" fill="url(#gradient)" />
</mask>
</defs>
</svg>
The idea is not to use the CSS mask
property. To do that, I've removed the div
s and added the svg
text
elements and applied the mask
in the HTML itself.
var grad = document.getElementById('gradient');
var animSpeed = 25;
for (i = 0; i < 120; i++) {
var anim = setTimeout(function() {
var x1 = (parseInt(grad.getAttribute('x1').slice(0, -1), 10) + 1) + '%';
var x2 = (parseInt(grad.getAttribute('x2').slice(0, -1), 10) + 1) + '%';
grad.setAttribute('x1', x1);
grad.setAttribute('x2', x2);
}, animSpeed * i)
}
<svg>
<defs>
<linearGradient id="gradient" x1="-15%" y1="0%" x2="5%" y2="0%">
<stop stop-color="white" offset="0" />
<stop stop-color="black" offset="1" />
</linearGradient>
<mask id="mask" maskUnits="objectBoundingBox" maskContentUnits="objectBoundingBox">
<rect width="1" height="1" fill="url(#gradient)" />
</mask>
</defs>
<text x="2" y="12" mask="url(#mask)">This text should appear from left to right</text>
<text x="2" y="27" mask="url(#mask)">This text should appear from left to right</text>
</svg>
Upvotes: 1
Reputation: 28387
There are basic Javascript problems in your code along with your mixing of jQuery code with Javascript.
But that aside, you just can't do what you are trying to do that way. CSS styles cannot be applied per character basis for an element. CSS styles are applied to an entire element. So, that premise of your code itself is wrong.
You can do two things to achieve what you want.
span
of its own and then use JS to change opacity
on all one by one.Here is one crude example of using CSS3 animation:
.text {
position: relative; width: 320px; height: 32px;
-webkit-animation: fade 10s; animation: fade 10s;
}
.text::after {
content:''; position: absolute;
height: 100%; background-color: #fff;
-webkit-animation: slide 10s; animation: slide 10s;
}
@-webkit-keyframes slide {
0% { left: 0; width: 100%; }
100% { left: 100%; width: 0; }
}
@-webkit-keyframes fade {
0% { opacity: 0; }
100% { opacity: 1; }
}
@keyframes slide {
0% { left: 0; width: 100%; }
100% { left: 100%; width: 0; }
}
@keyframes fade {
0% { opacity: 0; }
100% { opacity: 1; }
}
<div class="text"> this text should appear from left to right </div>
<div class="text"> this text should appear from left to right </div>
Upvotes: 1
Reputation: 11859
UPDATED: your code have some error:
use divs.length
not divs.length();
& string.length
not string.length();
because length is the property
not method
.
use var string = divs[i].innerHTML;
instead of var string = divs[i].text();
but you should not go that far use simply:
function fadeDivs(){
var divs = document.getElementsByClassName("text");
for(i=0; i<divs.length; i++){
var string = divs[i];
string.style.transition = "opacity 1s ease 0s";
string.style.opacity = '1';
}
}
Upvotes: 1