利用 DOM 特性的两个小技巧February 26, 2009

此类技巧还有很多,欢迎继续分享

解析 URL

从 James Padolsey 的 Blog中看到的个小技巧,就是利用 a 标签的 DOM 属性解析 URL 字符串。

// This function creates a new anchor element and uses location
// properties (inherent) to get the desired URL data. Some String
// operations are used (to normalize results across browsers).
 
function parseURL(url) {
    var a =  document.createElement('a');
    a.href = url;
    return {
        source: url,
        protocol: a.protocol.replace(':',''),
        host: a.hostname,
        port: a.port,
        query: a.search,
        params: (function(){
            var ret = {},
                seg = a.search.replace(/^\?/,'').split('&'),
                len = seg.length, i = 0, s;
            for (;i<len;i++) {
                if (!seg[i]) { continue; }
                s = seg[i].split('=');
                ret[s[0]] = s[1];
            }
            return ret;
        })(),
        file: (a.pathname.match(/\/([^\/?#]+)$/i) || [,''])[1],
        hash: a.hash.replace('#',''),
        path: a.pathname.replace(/^([^\/])/,'/$1'),
        relative: (a.href.match(/tp:\/\/[^\/]+(.+)/) || [,''])[1],
        segments: a.pathname.replace(/^\//,'').split('/')
    };
}

可对比下“传统的”正则解析方式(取自 Tbra 库),至少上面代码看起来更容易理解得多

parseURL: (function() {
    var keys = ['source', 
                'prePath', 
                'scheme', 
                'username', 
                'password', 
                'host', 
                'port', 
                'path', 
                'dir', 
                'file',
                'query', 
                'fragment'];
    var re = /^((?:([^:\/?#.]+):)?(?:\/\/)?(?:([^:@]*):?([^:@]*)?@)?([^:\/?#]*)(?::(\d*))?) \
               ((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*)) \
               (?:\?([^#]*))?(?:#(.*))?/;    
    return function(sourceUri) {
        var uri = {};
        var uriParts = re.exec(sourceUri);
        for(var i = 0; i < uriParts.length; ++i) {
            uri[keys[i]] = (uriParts[i] ? uriParts[i] : '');
        }
        return uri;
    }
})();

(反)转义 HTML

取自 Prototype 中的相应代码

escapeHTML: function(str) {
    var div  = document.createElement('div');
    var text = document.createTextNode(str);
    div.appendChild(text);
    return div.innerHTML;
}

unescapeHTML: function(str) {
    var div       = document.createElement('div');
    div.innerHTML = str.replace(/<\/?[^>]+>/gi, '');
    return div.childNodes[0] ? div.childNodes[0].nodeValue : '';
}

-- EOF --

动画初探(实现)February 2, 2009

说完了理论,我们来做点实事。这篇文章将介绍使用 Javascript 实现的动画组件。

下面记录下当时编写这个组件的考虑的些问题,对技术细节感兴趣的朋友,可以到这里参看源代码

  1. 需要几个回调函数控制初始化、动画运行时、动画完成的情况
  2. 将动画精确到运行了几帧
  3. 使用 setInterval 还是 setTimeout,最后还是选择了 setInterval(详细
  4. 不管元素需要更改那些属性,提供相应公式即可,但这可能带来性能问题
  5. 要可扩展、而且稳定

这个动画组件的用法简要的说明下,首先我们要确定元素从哪里移动(begin)到哪里(final),我们可以将两个信息绑定到一起,比如

var position = {from: 0, to: 100};

然后实例化个动画组件,指定动画的运行时长(duration)以及动画运行类型(tween)

var motion = new Motion(duration, tween);

另外,我们当然希望在动画初始化、开始以及进行和结束时候做额外的事情,那么加入相应 的回调:

// 初始化
motion.onInit = function() {
    // ...
};

// 开始
motion.onStart = function() {
    // ...
};

// 动画运行时
motion.onTweening = function() {
    // 需要获取某个时间点的坐标时,可以使用 this.equation 方法
    var p = this.equation(position.from, position.to);
};

// 动画完成时
motion.onComplete = function() {
    // ...
};

当一切准备就绪,那么就可以开始动画了

motion.start();

当然,任何时候我们都希望能停止动画,那么就

motion.stop();

那么我们就可以通过这个动画组件完成常见的动画效果了。这里有个 DEMO,看下这个动画组件的实际使用例子。按照传统,代码可以在这里打包下载

附,参考资源:YUI 的动画组件mootools 的动画组件

-- 全文完 --

动画初探(原理)February 1, 2009

哲学上有种说法,“运动是绝对的,静止是相对的”。我们在编写各样的效果时,时常会碰到动画。下面的章,将讨论动画的原理以及实现。

动画,简而言之就是物体在某时间段内,不断的改变自身的属性。这些属性有可能是位置、大小等。为了方便说明,在这里统一认定为位置(position)。

那么,动画就有了两个基本的变量,时间和位置。用直角坐标系来表示,将 x 轴定为时间(time),将 y 轴定为位置(position),就可以得到这样的坐标系

http://files.gracecode.com/2009_11_05/124506e8a53a.jpg

从这个坐标系可以获得更多的信息,比如动画运行的时间段(x 轴的区间)、动画开始试物体的位置(begin)以及结束时的位置(final)。

然后,动画的基本关系可初步抽象出来。时间(duration)和位置(position)存在函数关系

position = f(time)

在这里同时引入 fps (帧率)这个概念。fps 简单的说,就是一秒钟内物体变化了几帧。它抽象成坐标中的元素,就是 x 轴的粒度。

fps 是个常量(比如通常电影的 fps 为 25,即每秒 25 帧),通过 fps 以及时间段(duration),则可以计算出这个时间段内物体位移了几帧(frames),公式如下

frames = (duration/1000)*fps

上述公式中,时间段(duration)以毫秒计算,即一毫秒等于一千分之一秒。

综合起来,我们要获得某个时间点的位置时,就可以利用 当前时间点(time)、时间段(duration、x 轴的区间),以及开始的坐标(begin)和结束的坐标(final)等因素来完成,那么可以将第一个的公式细化成

position = f(time, begin, final, duration)

同时,根据 fps 计算出的帧数,则可以得知某动画在这个时间段内运行了几次。而此函数产生的曲线,则可以说明在指定时间段内,物体的运动情况。如曲线比较抖,则说明物体运动比较快,反之则慢。

例如上述函数图的 45 度曲线,如果不考虑区间因素则可以写成

position = time

然后加上函数区间,则用函数表示

postion = final * time / duration + begin

那么就可以说明物体随着时间的改变,位置进行匀速递增的运行。

至此,元素的动画问题,这时就可以抽象成具体的数学问题。仅通过改变函数的公式,就可以改变物体动画的运行效果。

附,相关参考资源:

维基百科:动画中文)、FPS/帧率中文

--未完待续--

  1. 1
  2. ...
  3. 3
  4. 4
  5. 5
  6. 6
  7. 7
  8. 8
  9. 9
  10. ...
  11. 25
Yahoo 统计