Activity › Forums › Adobe After Effects Expressions › animating text with expressions
-
animating text with expressions
Posted by Yair Neumann on March 6, 2009 at 8:18 pmHello
I have a project Im trying to make, I need text in random words to wrap around a building and in the background there is a song. from the random text on the building I need the word that is being sung in the background to be highlighted. Does anyone have suggestion how to approach this?
Filip Vandueren replied 17 years, 2 months ago 2 Members · 2 Replies -
2 Replies
-
Filip Vandueren
March 7, 2009 at 4:05 amI would place the text in text-boxes of fixed size so they wrap around. Probably set the paragraph mode to full justify.
Place those textlayers in 3D to create your building like world.If you don’t want to randomize the order of the words in the textlayer yourself, add this expression to the sourceText property…
// Source Text Randomize word order
// make sure teh randomization is timeless
seedRandom(1,true); // you can change the 1 for a different order.
txt=text.sourceText;
// split in to an Array, random sort, rejoin to a string.
txt.split(" ").sort(randOrd).join(" ");// helper function for random positive or negative numbers
function randOrd() {
return random(-1,1);
}
Then I would put layer-markers on the textlayers, naming each marker with the currently sung word, if there’s punctuation, be sure to include it in the markername.
Then create a Text-animator set to Units “index” based on “characters”. Select a part of your text this way and apply any effects you want to highlight the word. For example, try setting the Mode to Subtract, then adding an Opacity of 30 and a Blur of 2px, will cause all words to be grey and blurry except the currently selected range.
Add this expression to the start-property of the Range Selector
// Range start:// trim whitespace
String.prototype.trim = function() {
return this.replace(/^\\s+|\\s+$/g,"");
}
// find all occurences of a word
String.prototype.findAll = function(word) {
a=this.split(word);
all=[];
i=0;
for (j=0;j < a.length;j++) { //
i+=a[j].length;
all[j]=i;
i+=word.length;
}
all.pop();
return all;
}seedRandom(index,true);
// convert sourcetext to lowercase, trim, then add a space before and after
// to ensure all words have spaces at their boundaries
txt=" "+text.sourceText.value.toLowerCase().trim()+" ";// only execute if there are markers
if (marker.numKeys && time>=marker.key(1).time) {
// get the next marker
nm=marker.nearestKey(time);
nmi=nm.time>time ? nm.index-1 : nm.index;// add spaces to the trimmed markername to ensure proper boundaries
// a becomes " a " other wise the word 'a' would match every letter a.
word=" "+marker.key(nmi).comment.toLowerCase().trim() +" ";// if the word.length=2 (" "), then the markername was empty
if (word.length>2) {
// get the index of a random Occurence of the word
all=txt.findAll(word);
start=all[Math.floor(random(all.length))];
} else {
-1
}} else {
-1
}
Add this third expression to the end-property of the Range Selector
// Range End:start=propertyGroup().start.value;
txt=text.sourceText;// get the next space after the start of the word.
start>=0 ? txt.indexOf(" ",start+1) : -1;
OK, so now the textanimator will hi-light the current word from the marker-comment. It will work case-insensitive, and if the word occurs multiple times, a random occurence will be picked.
All you have to do by hand is put the markers on the correct layer, when you have different “walls” to your building.
An expression like this that would work over several text-layers, possibly having the same word occuring in multiple places and choosing only one layer to be active in at a time, would be (even more) complex. Let’s see if you can get this to work. -
Filip Vandueren
March 7, 2009 at 4:17 amupdate!
The second expression should be this:
// Range start:// trim whitespace
String.prototype.trim = function() {
return this.replace(/^\s+|\s+$/g,"");
}
// find all occurences of a word
String.prototype.findAll = function(word) {
a=this.split(word);
all=[];
i=0;
for (j=0;j < a.length;j++) { // i+=a[j].length; all[j]=i; i+=word.length; } all.pop(); return all; } // convert sourcetext to lowercase, trim, then add a space before and after // to ensure all words have spaces at their boundaries txt=" "+text.sourceText.value.toLowerCase().trim()+" "; // only execute if there are markers if (marker.numKeys && time>=marker.key(1).time) {
// get the next marker
nm=marker.nearestKey(time);
nmi=nm.time>time ? nm.index-1 : nm.index;// add spaces to the trimmed markername to ensure proper boundaries
// a becomes " a " other wise the word 'a' would match every letter a.
word=" "+marker.key(nmi).comment.toLowerCase().trim() +" ";// if the word.length=2 (" "), then the markername was empty
if (word.length>2) {
// get the index of a random Occurence of the word
seedRandom(nmi,true);
all=txt.findAll(word);
start=all[Math.floor(random(all.length))];
} else {
-1
}} else {
-1
}
just the location and seed of seedRandom had changed, otherwise it will always be the same random occurence for every time a wor is encountered, now the random occurence is based on the current marker key index.
Reply to this Discussion! Login or Sign Up