【疯狂的菊花系列】Canvas绘制Loading动画

Under: JS

上回说到用png图片来做帧动画, 总的来说也没什么大问题, 但是画个菊花, 按固定角度旋转N次做图实在是蛋疼.

既然怎么样都要画个菊花, 那不如就用canvas来画算了. 对于不支持canvas的浏览器, 可以用svg, 原理都差不多.

这个canvas动画的原理跟帧动画也类似, 先绘制第一帧的画面, 然后擦掉, 接着绘制第二帧, 以此循环. 时间间隔短的话看上去就变成动画了.

具体解释请看代码, 有足够的注释, 或者也可以点这里看看结果. canvas的api说明可以在这里找到.

window.onload = function(){
    var canvas = document.getElementById('canvas');
    var ctx = canvas.getContext('2d');
    if(!ctx){
        return;
    }
    ctx.clearRect(0,0,128,128);//擦除画布
    ctx.fillStyle = 'transparent';
    ctx.fillRect(0,0,128,128);
    ctx.fillStyle = 'black'; //定义点的颜色
    var base = 0;
    var update = function(){
        ctx.save(); //把当前的绘图状态保存起来(如旋转角度的初始位置, 填充颜色, 坐标原点等)
        ctx.clearRect(0,0,128,128);//擦除画布
        ctx.translate(64, 64);//把坐标原点移动到画布中央
        base = (++base === 13) ? (base - 12) : base;//使用base来指示最大的圆点所在的位置, 实现旋转动画的效果
        var angle = Math.PI / 6;//画12个点, 所以每个点之间的角度是 1/6 PI
        var beginAngle = angle * base ;
        for(var i = 1; i <= 12; i ++){
            ctx.beginPath();//开始一个路径
            if(i === 1){
                ctx.rotate(beginAngle);
            }else{
                ctx.rotate(angle);//每次调用rotate之后, 其旋转角度并不会还原, 而是接着上一次的位置
            }
            ctx.arc(0, -48, i * 0.8 + 1, 0, 2 * Math.PI, true);//绘制一个圆点
            ctx.closePath();//闭合路径
            //如果不是用beginPath和closePath, 在调用fill方法时, 会导致画布上的所有圆都重叠在一起了
            ctx.fill();//填充(使用上面最后定义的fillStyle)
        }
        ctx.restore();//还原绘图状态, 如果不还原, 则下一次调用rotate时会接着这次的位置旋转, 而不是初始位置
    }
    update();
    setInterval(update, 50);
};

菊花系列暂时就到这里了, 有时间再去用svg整个.

【疯狂的菊花系列】制作PNG帧动画Loading

Under: JS

话说上回说到使用css3的animation来制止png格式的菊花, 但是目前之后新版的firefox和webkit核心浏览器才支持该动画, 那其他浏览器也想用png动画怎么办呢?

这就要提到帧动画的概念了, 会flash的都知道, adobe flash软件里有个时间轴和帧的概念, 具体解释我就不说了, 可以自己google.其原理是事先把一个动画的所有动作的话出来, 然后在不同的时间点显示不同的动作, 切换的快的话看上去就动起来了.

制作菊花, 要先准备一张包含所有菊花状态的图,就像下面这张:

用一个固定大小的窗口显示这张图, 定时移动图片的位置, 就能让它动起来了. 简单的代码如下:

setInterval(function(){
    var left = parseInt(imgEl.style.left || 0) - 128;
    if(left <= -1280){
        left = 0;
    }
    imgEl.style.left = left + 'px';
}, 50);

活生生血淋淋的实例在这里.

PS: 画这10帧的菊花帧蛋疼~~

完美实现溢出文本省略

文本溢出展示省略号的需求经常都会用到,而对于新式的浏览器,这完全不是问题,因为css3里面已经有实现text-overflow:ellipsis,但是最新w3c文档中却移除了这个属性,即使这样,也有不少浏览器实现了这个特性。其浏览器支持情况如下:

IE	Firefox	Opera	Safari	Chrome
6+	-	11.0+	3.0+	1.0+

可以看到,只有firefox和opera11一下的版本不支持这个浏览器,以此也可以放心大胆的用了。但是遇到要求高的产品经理时(╮(╯_╰)╭),就不得不考虑firefox等不支持的浏览器了,唯有使用js进行字符截断。

比较简单的截断方式就是按字符个数截断,以一个中文宽度等于两个英文宽度为前提,根据给定字符个数进行截取。但是字符在页面显示的时候,其宽度并不是一定的,会根据不同的字体和字体大小的不同而不同,更何况字母i和A的宽度是不一样的,存在bug且不够精确。

Read More »

判断浏览器是否支持指定CSS属性

现在css3出来了, 添加了许多新特性,但由于并未全部浏览器都实现了这些特性,使用起来不太顺畅。因此,就想在使用的时候进行判断,如果有这个属性并且支持这种值,就css实现, 否者就用js实现。

比较明显的例子就是text-overflow这个属性,text-flow:clip是大部分浏览器都支持的,而text-flow:ellipsis则在firefox和10.6版本以下opera上工作不了,让人相当头疼。

废话少说,判断的代码如下:

var element = document.createElement('div');
if('textOverflow' in element.style){
    element.style['textOverflow'] = 'ellipsis';
    return element.style['textOverflow'] === 'ellipsis';
}else{
    return false;
}

这个判断的原理是:创建一个节点,判断其的style属性是否含有textOverflow属性,有则进一步判断是否支持ellipsis这个值。

判断是否支持ellipsis值依靠的是浏览器对于非法style值的处理,当遇到不支持的属性值时,浏览器会直接把这个值抛弃。因此这里就可以先给textOverflow赋值“ellipsis”,如果不支持,则其值肯定为空或者其它不等于“ellipsis”的值。因此只要判断赋值后的textOverflow是否等于“ellipsis”即可。

富文本兼容性问题归纳(ubuntu)

Under: JS

周五在ubuntu上测了一下重构后的富文本, 发现依然存在一个bug: 开启了中文输入法的话, 输入框就监听不到按钮事件了.

这个问题在webqq的聊天框一直存在着, 也有很多用户投诉, 具体表现为: 切换到中文输入法(ibus or other), 输入一段内容后, 第一次按下回车键可以发送消息, 之后的回车键都变成输入框的换行了.

花了一个中午排查了下, 总算找到原因了:

在ubuntu上面, 切换到中文输入法的时候, 只有第一次按下的keydown/keyup事件会被抛出, 之后都keydown和keyup事件都会被输入法接收且不会冒泡, 因此输入框没办法对按钮作出响应. 这个行为跟用什么浏览器无关, 我在firefox和chrome都发现有这个问题. 如果你的系统是ubuntu, 可以点击这里测试.

幸运的是, 经过测试, 发现keypress能响应回车键(以及其他ctrl+v等没触发出中文输入法的键盘行为), 因此可以把监听回车事件的代码转移到keypress中, 解决掉这个存留已久的bug.

注意: opera的keypress事件是没有charCode的, 且keyCode与keydown/keyup事件的keyCode一致, 无语…

2011-6-6 更新: Read More »

富文本兼容性问题归纳(win)

Under: JS

上周抽空把去年写的富文本重写了一下,  封装成基本UI组件, 就可以在聊天框之外的地方复用了. 个人觉得富文本是个兼容问题最多的模块之一, 尤其是文档也没几个, 把mozilla的api文档和IE的dom api关于selection和range的看了一个遍, 一个个试, 总算找到勉强能用的方法.

其实之前的富文本代码太乱, 而且还有不少bug, 只是产品经理不给时间改, O__O”…

这个富文本没有用iframe来做输入框, 原因有二:

  1. iframe是所有dom节点中消耗性能最大的, 开多几个ie6/7就会卡到不行了;
  2. 因为webqq是多窗口聊天的, 当光标点击到输入框时, iframe会捕获鼠标事件, 通知不了聊天窗设置样式;

所以就用了div, 设置contentEditable=”true”, 这个属性基本浏览器都支持, 除了firefox2.0(不过还真有用户还在用ff2.0⊙﹏⊙b汗)

这次修改发现了不少蛋疼的兼容性问题, 挑几个归纳一下:

Read More »

判断A节点是否包含B节点

Under: JS

发现实际项目中经常需要判断一个节点是否是另一个节点的子节点, google了一下以及在做富文本的时候顺便看了下mozilla的api文档, 发现个compareDocumentPosition方法, 可用来比较两个节点位置. ie则有更好用的方法contains, 只要传入的节点是其子孙节点就返回true. Read More »

动态获取图片宽高

Under: JS

由于网站服务器在国外, 国内访问有点慢

加上家里这烂鬼长城宽带, 打开页面时如果有图片,加载时间相当久

于是决定改为先拉小图片, 点击之后再异步拉取大图

原理是点击小图的时候创建一个img标签,设置onload事件,

在大图加载成功时显示大图 Read More »

blog