随着智能手机的普及,大家已经习惯随手拍点照片传网上了。有时候传上去的照片方向会不对,甚至还有脑袋朝下的情况。为此,各大微博不约而同的给照片增加左右旋转的功能。这样能解决问题,但我们是否能更进一步,自动选择正确的照片方向呢?刚好最近我们有类似的场景,本文就讨论下这个问题。
实际上,数码设备拍摄照片时,会把许多属性附加在照片文件里,这些属性构成了大家常说的Exif信息。访问我的相册会发现照片下也有对应的Exif信息。Exif中有个Orientation字段,用来存放照片方向,这就是我们需要的,看下它的定义:
今天看到某大牛之前写的某段代码里,用到了"| 0"这种写法将字符串取整。这本来没什么,很多人都这样做,但他那段代码里处理的是一个时间戳。如:
"1325239449538" | 0;
结果是-1905444926,这显然不是我们想要的。这个问题产生的原因是:A | B是将A、B先ToInt32再运算,返回结果是32位符号型整数。只要A超过2147483647,也就是231-1,就杯具了。
另一个常用的parseInt函数也容易发生杯具,如:
parseInt(0.0000001);
在大部分浏览器上,结果是1(新版firefox会得到0),这也显然不符合预期。原因是parseInt(A)第一步会执行ToString(A)。上面的例子中,0.0000001会转成"1e-7",后面的事情应该都知道的。
本文链接:http://www.imququ.com/post/89.html
--EOF--
QWrap是一个BSD协议下的开源JS框架,前身是百度有啊WED团队内部使用的BBlib。关于她的设计理念、核心架构,JK和月影两位同学的博客上有很多文章。这里我简单介绍下实际项目中,如何用QWrap开发组件。
动手之前,建议先看下这几十篇QWrap介绍,对QWrap有个全面的了解。然后,通过git获取JK分支的QWrap,或者从这里下载最新主干的zip包。QWrap官方版暂时还没放组件,我们先选择有组件的JK版,两者核心库是一致的。做完这些准备工作后,进入正题~
Web中的JS动画原理并不复杂,JK前些时写过系列文章《动画组件(wagang版)》,讲解帧动画的原理以及QWrap版的实现,偷懒直接贴过来:
我们把动画抽象一下,它由以下几个组成部分:
时长(dur),即动画播放的时间总长。
进度(per),播放的进度,在区间[0,1]之内。
帧间隔时间(frameTime),即多长时间播放一帧。
动画函数(animFun),它是每一帧的渲染函数。定时器每隔frameTime来调用一下animFun(per)。也就是说按进度播放一帧动画。
这四个基本参数将动画抽象成为一个js类,系统的理解就是:
“在dur时间内,每隔frameTime时间,播放一次animFun(per)。”
随着页面上动画的使用越来越频繁,为了避免过多的定时器带来额外系统开销,一般的动画组件都会采用“统一帧管理”:只使用一个定时器,在每一动画帧依次调用所有注册的动画事件。
很多情况下,我们需要跨域读取数据,或者是调用别人json格式的api,都要用到js callback这种机制。通常做法是页面上定义一个A方法,再调用第三方的url并且把回调函数名A传过去。这样做固然没什么问题,但有没有更好的方法呢?
用过jQuery的同学肯定都知道,jQuery有一个getJSON的方法,只需要两个参数(callback地址和匿名函数)就能正常工作。摘录官方示例如下:
$.getJSON("http://api.flickr.com/services/feeds/photos_public.gne?tags=cat&tagmode=any&format=json&jsoncallback=?",
function(data){
$.each(data.items, function(i,item){
$("<img/>").attr("src", item.media.m).appendTo("#images");
if ( i == 3 ) return false;
});
}); 很神奇吧!在这个例子中,我们并不用指定callback函数名,回调也仅仅只是一个匿名函数而已,那么它是怎么完成函数调用的呢?去看下jQuery的源代码,你会发现其实原理很简单。如果懒得看太多代码,看看下面我写的山寨版loadJSON,也能明白。
function loadJSON(url,callback){
var cn = "jscallback"+(+new Date());
var s = document.createElement("script");
s.type = "text/javascript";
s.src = url+cn;
window[cn] = callback;
document.getElementsByTagName("head")[0].appendChild(s);
};
loadJSON("http://api.flickr.com/services/feeds/photos_public.gne?tags=cat&tagmode=any&format=json&jsoncallback=",function(o){
for(var i=0;i<3;i++){
var img = document.createElement("img");
img.src = o.items[i].media.m;
document.body.appendChild(img);
}
}); 本文链接:http://www.imququ.com/post/43.html
--EOF--
最近在Dron的UCRen网站看到一种很帅的JS写法,记录一下。
UCRen是下面这样引入widget的(摘自这个页面):
<script type="text/javascript" src="../../ucren-engine/cache-boot.js?skin=qq"> import webui.FileInput; import renderfactory.FormRenderer; </script>
第一眼看到这段代码,我还在想这样写JS语法分析器不报错才怪,难道是让window.onerror返回true干掉了浏览器的错误提示?这样也太不和谐了吧!今天仔细看了看才明白了,这个script标签是有src属性的,这样写标签里的内容会被忽略掉,不会执行也不会报错。在src链入的cache-boot.js里可以用:
var scripts = document.getElementsByTagName("script");
var code = scripts[scripts.length-1].innerHTML; 来得到那些神奇的代码,然后用正则解析成正常的script标签就OK了。原理不复杂,不过很有用。可以用它写出一些很有趣的代码来。
本文链接:http://www.imququ.com/post/54.html
--EOF--
众所周知,firefox的安全性比较高,但是安全带来的弊端就是很多功能不支持。比如说在IE下可以通过脚本来设当前网页为首页,firefox却不行。今天要讨论的是另外一个问题:怎么在firefox等不支持window.clipboardData的浏览器下实现复制呢?
首先,我们来看网易邮箱是怎么解决这个问题的。我们在firefox下进到写邮件页面,点击编辑器上的全部功能,然后点击左边的“复制”按钮,“您的浏览器安全设置不允许编辑器自动执行拷贝操作,请使用键盘快捷键(Ctrl C)来完成”,网易邮箱给了我们这么一个提示。我觉得这个解决方案可以得80分,因为它告诉了我们两个信息:其一,之所以复制操作没有完成是因为我的浏览器很安全,为了安全损失一点用户体验一般用户是可以接受的;其二,它还提示了我们可以通过键盘快捷键ctrl c来完成操作,这对刚上网的新手来说很人性化。但是,有没有更好的解决方案呢?
网上大致有两种解决方案,一种是需要修改firefox配置,其实firefox也是支持复制的,但是需要到about:config里去手动开启,这里不做介绍了;另外一种解决方案是本文要用到的flash。因为flash可以方便的把文字拷贝到系统剪切板中,所以我们利用flash来做跳板,只需要一行代码就能搞定:
System.setClipboard(clipboard);
这句代码的含义后面还会提到。有了这个swf的跳板,剩下的工作就简单了,如果浏览器不支持window.clipboardData,就在复制的时候把内容传给这个flash,就OK了,关键代码如下:
if (window.clipboardData){
window.clipboardData.setData("Text",str);
}else{
var flashId = '_clipboard_';
var flashContent = '<embed src="clipboard.swf" FlashVars="clipboard=' str.replace(/\ /g,"+") '" width="0" height="0" type="application/x-shockwave-flash"></embed>';
if(!document.getElementById(flashId)){
var flash = document.createElement("div");
flash.id = flashId;
flash.innerHTML = flashContent;
document.body.appendChild(flash);
}else{
document.getElementById(flashId).innerHTML = flashContent;
}
} adobe的文档中对setClipboard有如下解释:
setClipboard () 方法
public static function setClipboard(string:String):void
语言版本 : ActionScript 3.0
Player 版本 : Flash Player 9 用指定的文本字符串替换剪贴板的内容。
注意:出于安全方面的考虑,您无法读取系统剪贴板的内容。 换句话说,不存在相应的
System.getClipboard()方法。参数
string:String— 要放置在系统剪贴板上的纯文本字符串,用于替换系统剪贴板上的当前内容(如果有)。
由此可见,我们只能利用flash把文字复制到系统剪贴板中,而不能把系统剪切板中的内容拷贝出来。
本文链接:http://www.imququ.com/post/61.html
--EOF--
手册上对onkeydown的描述为“Fires when the user presses a key”,onkeyup的描述为“Fires when the user releases a key”,onkeypress的描述为”Fires when the user presses an alphanumeric key”,一个是键盘按键按下时触发,一个是按键弹起时触发,另一个是按下键盘的数字、字符键触发。为什么说要慎用keyup呢?
设想有这么一种情况,在web页面上有一个模拟的弹出窗口,很流行的那种,然后我们监听keyup事件,如果发现keyCode等于27,也就是说用户按了ESC键的时候隐藏窗口,这样能方便一部分高级用户,Google文档也这么做。但是如果弹出窗口中有一个输入框,情况就不那么妙了。因为我们通常用的输入法都有一个候选词的浮动窗口,有时候打错字了需要关闭这个浮动框口也会用到ESC,这个时候你会发现一旦按下ESC,输入法的候选词窗口连同那个弹出层一起消失了。
实际上,这个问题很好解决,我们只要把keyup换成keydown、keypress中的任何一个就可以了,在有候选词窗口出现的情况下按ESC是不会触发keydown/keypress事件的。这种错误监听事件的现象不仅仅在web上才有。以前的baidu hi在 选择表情时,鼠标在同一个表情上来回晃动,预览区的图片会一直跳动,这个很神奇的bug就是因为hi错误地监听了每个表情的mousemove事件,导致鼠标一移动,预览区图片就重新加载,如果图片是gif格式的就始终在前几帧播放,所以看上去好像在跳动。另外以前在ubuntu下用过一个第三方的msn客户端,这个客户端在聊天窗口中按ESC会关闭当前聊天窗口,这没什么,官方的msn也是这样,但是郁闷的是在有候选词窗口的时候按ESC,聊天窗口一样会关闭,而且再次打开 之前辛辛苦苦敲进去的内容全没了,这种bug让人很无奈。
keydown,keyup,keypress在有输入法窗口时对ESC处理的差异
本文链接:http://www.imququ.com/post/60.html
--EOF--