2010-05-14 25 views
2

如何爲HTML5中的頁面上的文本的單個字符製作動畫。就像Flash中的這個例子一樣。 http://www.greensock.com/splittextfield/如何用html5動畫字符文本

+0

重新標記。問題似乎不是關於閃光。 你爲什麼只限於HTML5? – Eric 2010-05-14 22:06:43

+1

@Eric:當然,這就是所有最酷的孩子最近都在談論的。 – 2010-05-14 22:07:15

+0

你不知道。 CSS和JavaScript這樣做,而不是HTML。 – Rob 2010-05-15 00:10:33

回答

3

你不得不包裹裏的每個字符<span>然後使用CSS position/top/left移動跨度。

您無法完全重現Flash示例的效果,因爲該示例使用了模糊效果。 CSS不能做到這一點; SVG可以,而IE的非標準filter可以,但這將意味着一個完整的代碼分支。

你可以通過設置font-size來改變每個字母的大小,但是爲了這樣剪切/旋轉效果,你必須使用CSS transform這個例子。這尚未標準化,瀏覽器支持存在漏洞。

這裏有一個驗證的概念,我只是砍死了主要針對Firefox(遺憾的碼長):

<p id="effect">I've got a lovely bunch of coconuts.</p> 
<button id="animate">Animate</button> 


// Add ECMA262-5 method binding if not supported natively 
// 
if (!('bind' in Function.prototype)) { 
    Function.prototype.bind= function(owner) { 
     var that= this; 
     if (arguments.length<=1) { 
      return function() { 
       return that.apply(owner, arguments); 
      }; 
     } else { 
      var args= Array.prototype.slice.call(arguments, 1); 
      return function() { 
       return that.apply(owner, arguments.length===0? args : args.concat(Array.prototype.slice.call(arguments))); 
      }; 
     } 
    }; 
} 

// Lightweight class/instance system 
// 
Function.prototype.makeSubclass= function() { 
    function Class() { 
     if (!(this instanceof Class)) 
      throw 'Constructor function requires new operator'; 
     if ('_init' in this) 
      this._init.apply(this, arguments); 
    } 
    if (this!==Object) { 
     Function.prototype.makeSubclass.nonconstructor.prototype= this.prototype; 
     Class.prototype= new Function.prototype.makeSubclass.nonconstructor(); 
    } 
    return Class; 
}; 
Function.prototype.makeSubclass.nonconstructor= function() {}; 

// Abstract base for animated linear sliding switch between 0 and 1 
// 
var Animation= Object.makeSubclass(); 
Animation.prototype._init= function(period, initial) { 
    this.period= period; 
    this.interval= null; 
    this.aim= initial || 0; 
    this.t= 0; 
}; 
Animation.prototype.set= function(aim) { 
    if (aim===this.aim) 
     return; 
    this.aim= aim; 
    var now= new Date().getTime(); 
    if (this.interval===null) { 
     this.t= now; 
     this.interval= window.setInterval(this.update.bind(this), 32); 
    } else { 
     this.t= now-this.t-this.period+now 
     this.update(); 
    } 
}; 
Animation.prototype.toggle= function() { 
    this.set(this.aim===0? 1 : 0); 
}; 
Animation.prototype.update= function() { 
    var now= new Date().getTime(); 
    var x= Math.min((now-this.t)/this.period, 1); 
    this.show(this.aim===0? 1-x : x); 
    if (x===1) { 
     window.clearInterval(this.interval); 
     this.interval= null; 
    } 
}; 
Animation.prototype.show= function(d) {}; 

// Animation that spins each character in a text node apart 
// 
var ExplodeAnimation= Animation.makeSubclass(); 
ExplodeAnimation.prototype._init= function(node, period) { 
    Animation.prototype._init.call(this, period, 0); 
    this.spans= []; 

    // Wrap each character in a <span> 
    // 
    for (var i= 0; i<node.data.length; i++) { 
     var span= document.createElement('span'); 
     span.style.position= 'relative'; 
     span.appendChild(document.createTextNode(node.data.charAt(i))); 
     node.parentNode.insertBefore(span, node); 
     this.spans.push(span); 
    } 

    // Make up random positions and speeds for each character. 
    // Possibly this should be re-randomised on each toggle? 
    // 
    this.randomness= []; 
    for (var i= this.spans.length; i-->0;) 
     this.randomness.push({ 
      dx: Math.random()*200-100, dy: Math.random()*200-150, 
      sx: Math.random()*1.5, sy: Math.random()*1.5, 
      dr: Math.random()*240-120, og: Math.random()+0.5 
     }); 

    node.parentNode.removeChild(node); 
}; 
ExplodeAnimation.prototype.show= function(d) { 
    for (var i= this.spans.length; i-->0;) { 
     var style= this.spans[i].style; 
     var r= this.randomness[i]; 

     style.left= d*r.dx+'px'; 
     style.top= d*r.dy+'px'; 
     var transform= 'rotate('+Math.floor(d*r.dr)+'deg) scale('+(d*r.sx+1-d)+', '+(d*r.sy+1-d)+')'; 
     if ('transform' in style) 
      style.transform= transform; 
     else if ('MozTransform' in style) 
      style.MozTransform= transform; 

     var o= 1-Math.pow(d, r.og); 
     if ('opacity' in style) 
      style.opacity= o+''; 
     else if ('filter' in style) 
      style.filter= 'opacity(alpha='+Math.ceil(o*100)+')'; 
    } 
}; 


var animation= new ExplodeAnimation(document.getElementById('effect').firstChild, 1000); 
document.getElementById('animate').onclick= animation.toggle.bind(animation); 

這可以通過增加控制當前的重心和更好的3D空間建模得到改善完全隨機轉換,加上更好的瀏覽器支持除Firefox以外的瀏覽器中的縮放/旋轉。

(IE有其自己的非標準CSS transform filters有可能支持;的Webkit和Opera已經webkitTransformoTransform風格,但他們拒絕改變相對定位內嵌跨度,所以你必須絕對位置各字符,這意味着讀取所有正常位置作爲基準線。)在這一點上我感到無聊。)

+1

很想看到這在行動! PS:你可以用'text-shadow:0 0 5px samecolorasfont' – meo 2010-05-14 23:38:05

+1

...與'color:rgba(0,0,0,0)'結合來僞造模糊,以停止文本本身的出現。聰明!但我要睡覺了。 – bobince 2010-05-14 23:51:44

+1

是啊好主意我已經嘗試了不透明度,但它會看起來更好與rgba! http://jsfiddle.net/GqTam/1/ – meo 2010-05-15 00:12:17