CFXIXI工作室首页
CF西西的博客 | Html5

图片(旋转/缩放/翻转)变换效果(ccs3/滤镜/canvas)

19. 十月 2012
 http://www.cnblogs.com/cloudgamer/archive/2010/08/16/ImageTrans.html 以前要实现图片的旋转或翻转,只能用ie的滤镜来实现,虽然canvas也实现,但ie不支持而且不是html标准。css3出来后,终于可以用标准的transform来实现变换,而canvas也已成为html5标准的一部分。css3和html5使web变得越来越强大,各种新奇的技术正等待我们发掘。本程序分别通过滤镜(ie)、ccs3和canvas来实现图片的旋转、缩放和翻转变换效果,可以用作图片查看器。有如下特色:1,用滤镜、ccs3和canvas实现相同的变换效果;2,可任意角度旋转;3,可任意角度翻转;4,可扩展滚轮缩放;5,可扩展拖动旋转。兼容:ie6/7/8, firefox 3.6.8, opera 10.6, safari 5.0.1, chrome 5.0 效果预览           程序说明 【基本原理】 变换主要是利用css3的变换样式transform的matrix方法来实现。ie不支持css3,但有Matrix滤镜也能实现类似的效果。程序还用canvas,通过画图实现相同的效果。 【模式设置】 程序包含三种模式:css3、filter和canvas,程序初始化时,会根据自定义模式进行模式设置。各个模式相关的属性和方法都存放在ImageTrans.modes中。每个模式对象都包含support属性,表示当前浏览器是否支持该模式,还有几个方法:init:初始化执行程序load:加载图片执行程序show:变换显示程序dispose:销毁程序 使用这样的格式来自定义模式:"css3|filter|canvas",判断过程主要在_initMode程序中: 代码 程序会按顺序逐个判断,当浏览器支持该模式时就会用该模式的方法设置程序函数。再用_support记录浏览器是否支持指定的模式。 如果浏览器支持,才执行_initContainer容器初始化程序和_init模式初始化程序。 【加载图片】 完成初始化设置后,再执行load方法加载图片。在load方法中,主要对图片进行设置: img.onload || ( img.onload = this._LOAD );img.onerror || ( img.onerror = function(){ oThis.onError("err image"); } ); 最后设置src加载图片。 图片加载成功后,会执行_LOAD程序,在里面会执行_load加载程序和reset方法。在reset中,会重置变换参数,并执行_show模式画图程序: this._y = this._x = 1; this._radian = 0;this._show(); 这时,图片会以初始状态显示。 【图片变换】 图片加载完成后,就可以对图片进行变换。 各种变换方法保存在ImageTrans.transforms中,包括旋转、垂直翻转、水平翻转、缩放等。变换结果是通过_y垂直变换参数、_x水平变换参数和_radian旋转变换参数计算得到的。变换方法就是用来修改这些参数的方法。 一般的翻转是通过把_y或_x取反来实现的,是以图片本身为坐标的翻转。但用户的习惯是按浏览器坐标来翻转的,当图片先旋转变换坐标后再翻转,就不符合用户习惯了。为了能按视觉习惯坐标来翻转,程序使用的方法是先旋转再翻转来实现。例如vertical垂直翻转是图片旋转180度,再进行一般的水平翻转: this._radian = Math.PI - this._radian; this._x *= -1; 而horizontal水平翻转也类似: this._radian = Math.PI - this._radian; this._y *= -1; 实际也是利用了一些坐标变换原理。 rotate旋转是以弧度为单位的,直接修改_radian参数。rotatebydegress是以角度为单位的旋转,其实是用degress * Math.PI/180公式把角度转换成弧度。left向左转90度是在原有弧度减Math.PI/2(即90度),而right向右转90度是加Math.PI/2。 scale缩放就是根据缩放比率分别对_y和_x进行修改。程序定义了一个getZoom修正缩放比率函数: function getZoom(scale, zoom) {    return    scale > 0 && scale >-zoom ? zoom :            scale < 0 && scale < zoom ?-zoom : 0;} 只有当比率不会导致结果是反值的情况才会返回正确的比率。这里主要是保证缩到最小时不会因为比率太大得到反值,导致图片翻转并放大。当垂直和水平比率都不是0,才会对参数进行修改: var hZoom = getZoom( this._x, zoom ), vZoom = getZoom( this._y, zoom );if ( hZoom && vZoom ) {    this._x += hZoom; this._y += vZoom;} 这样可以保证水平和垂直缩放同时进行,保持图片比例。要注意zoomin放大时要保证缩放比率为正数,zoomout缩小就要负数。 这些方法会在模式设置中扩展到程序中: $$A.forEach( ImageTrans.transforms, function(transform, name){    this[ name ] = function(){        transform.apply( this, [].slice.call(arguments) );        this._show();    }}, this ); 在执行完变换方法后,就会执行_show来显示变换。 【transform】 变换换流程介绍完,就进入主题,介绍三个变换方法了。先看看css3的transform,它包含以下变换方法:matrix:矩阵变形,使用它就可以做到后面所有的变换,但使用相对麻烦;translate/translateX/translateY:坐标变换,就是移动坐标的意思;scale/scaleX/scaleY:缩放变换,放大缩小,取负值可以做翻转;rotate:旋转变换,根据角度旋转;skew/skewX/skewY:拉扯变换,就是上下或左右向不同的方向扯开的效果。更详细的介绍请看w3c的CSS 2D Transforms或者MDC的-moz-transform。 要进行变换,首先要看看浏览器是否支持: 代码 由于程序运行时文档可能还没载入,所以要手动创建一个元素来测试。虽然w3c标准使用的是transform,但现阶段各浏览器还是需要各自的前缀。当元素样式包含其中一个变换样式,说明该浏览器支持,再用css3Transform记录样式名字。 在css3模式的init程序中,会执行initImg方法对图片进行设置: $$D.setStyle( img, {    position: "absolute",    border: 0, padding: 0, margin: 0, width: "auto", height: "auto",    visibility: "hidden"});container.appendChild( img ); 主要是设置绝对定位、隐藏和重置样式,最后插入容器。ps:图片对象虽然是用new Image()创建的,但也可以当作img元素来操作。 在load加载程序中,再对图片样式进行设置: $$D.setStyle( img, {    top: ( this._clientHeight - img.height ) / 2 + "px",    left: ( this._clientWidth - img.width ) / 2 + "px",    visibility: "visible"}); 设置left和top使图片在容器里居中,并显示图片。 关键的show程序,用来进行图片变换,这里用的是matrix变换。matrix有6个参数,前4个是矩阵变换参数,后两个是坐标变换参数。要根据弧度旋转,可以这样设置矩阵:cos(a) -sin(a)sin(a)  cos(a)而缩放变换就这样设置:sx 00  sy旋转同时缩放,矩阵相乘得到:cos(a)*sx -sin(a)*sysin(a)*sx  cos(a)*sy关于Matrix矩阵变换可以看w3c的Transform Matrix。 getMatrix函数就是通过以上矩阵计算matrix参数: var Cos = Math.cos(radian), Sin = Math.sin(radian);return {    M11: Cos * x, M12:-Sin * y,    M21: Sin * x, M22: Cos * y}; 在show程序里面,用getMatrix得到参数后,就可以设置样式: this._img.style[ css3Transform ] = "matrix("    + matrix.M11 + "," + matrix.M21 + ","    + matrix.M12 + "," + matrix.M22 + ", 0, 0)"; 在实际使用中,使用matrix可能要设置一堆可读性很差的数字,所以还是推荐用其他变换方法。 【Matrix滤镜】 ie的Matrix滤镜跟css3的matrix差不多,也能实现类似的变换。Matrix滤镜有以下属性:Dx/Dy:坐标变换参数;enabled:是否可用;FilterType:定义新内容的像素的方法;M11/M12/M21/M22:矩阵变换参数;SizingMethod:容器是否改变尺寸去适应目标图像。详细参考msdn的Matrix Filter和中文Matrix说明。 判断浏览器是否支持,也是创建一个div,看它有没有"filters"属性: function(){ return "filters" in document.createElement("div"); }() 在init程序中也用initImg方法对图片进行设置,此外还需要设置Matrix滤镜: this._img.style.filter = "progid:DXImageTransform.Microsoft.Matrix(SizingMethod='auto expand')"; 这里会设置SizingMethod属性,它有两个值,分别是:clip to original(容器不改变尺寸)和auto expand(容器改变尺寸以适应目标图像)。如果使用默认值clip to original,容器的大小不会变,那么变换时超出容器的部分就会隐藏不见,所以这里要设为'auto expand'才能完整显示图片。 在load程序中显示图片,为了防止ie重复加载gif的bug还要重置onload为null。ps:该bug的研究可以参考这里的显示预览部分。 而show程序也跟css3模式类似,通过getMatrix方法获取变换参数,并设置到滤镜中: $$.extend(    img.filters.item("DXImageTransform.Microsoft.Matrix"),    getMatrix( this._radian, this._x, this._y )); 滤镜使用了'auto expand'后,变换时图片元素尺寸会随着内容变化,所以要重新设置居中: img.style.top = ( this._clientHeight - img.offsetHeight ) / 2 + "px";img.style.left = ( this._clientWidth - img.offsetWidth ) / 2 + "px"; ie还有其他变换滤镜,例如FlipH(水平翻转)、FlipV(垂直翻转)、Wave(扭曲)等。 【canvas】 通过滤镜和css3已经能在主流的浏览器上兼容实现相同的变换,最后再用canvas来实现。canvas是一个用来绘制图形的元素,它最强大的地方在于结合js来绘制图形甚至制作动画和游戏。ps:这里推荐几个入门文章:Opera的HTML 5 canvas和深入了解canvas标签系列。 要知道浏览器是否支持canvas,可以创建一个canvas元素,看它是否有"getContext"方法来判断: function(){ return "getContext" in document.createElement('canvas'); }() getContext方法用来获取渲染空间(也叫上下文),之后会在这个空间绘图,相当于获取画布。 在init程序中,创建并设置canvas及其上下文context: 代码 程序中只需要2D canvas,所以用getContext('2d')就行了。ps:关于3D canvas在Opera的HTML 5 canvas有相关的介绍。还需要设置尺寸,这里要注意要用width和height来设置,我试过用样式来设置,结果画图不正常。 在show程序中进行变换和画图: 代码 这里用到了canvas几种方法:save:保存状态;clearRect:清除画布;translate:水平/垂直移动坐标;rotate:旋转坐标;scale:缩放坐标;drawImage:插入图像;restore:恢复状态。 canvas没有直接清除整个画布的方法,只能用clearRect来间接实现。它的四个参数用来定义一个矩形,只要定义一个画布大小的矩形就能清除整个画布了。 在canvas里面没有left/top,位置的变换只能用translate来设置,程序用它把坐标移到画布中心。canvas没有Matrix那样的东西,只能用rotate和scale来变换,用法跟css3的类似。canvas也没有css3的skew(拉扯)变换。 最后用drawImage画图,可以是img元素、Image对象或Canvas元素,另外两个参数是画图位置,程序用它来居中图像。 每次画图都可能会改变坐标,下次想还原坐标来画图要逐个恢复会很麻烦,这时应该用save和restore来保存和还原状态。save和restore能保存和还原包括translate、rotate、scale变换后的画布状态,常常配合clearRect来做动画。 除了以上方法,canvas还有很多属性和方法来绘图,详细可以看HTML DOM CanvasRenderingContext2D 对象。 【拖动旋转/滚轮缩放】 拖动旋转效果是在容器按下鼠标并拖动的过程中,图像会跟着鼠标转动。原理是以容器中点为中心,计算按下鼠标位置的弧度R1和拖动到达位置的弧度R2,两者的差就是根据鼠标要旋转的弧度,再加上原来的弧度R0,即R2-R1+R0,就能得到当前要设置的弧度了。关键的地方就在于如何获取这个弧度,如果要手动计算这个值会很复杂,好在js提供了Math.atan2(y,x)方法,可以返回由 X 轴到 (y,x) 点的弧度,这样直接用坐标就可以得到弧度。例如中心坐标是(x,y),某一点的坐标是(x1,y1),可以这样得到那个点相对中心坐标的弧度:Math.atan2(y1-y,x1-x)。 首先在鼠标的mousedown中记录容器的中心坐标: var rect = $$D.clientRect( this._container );this._mrX = rect.left + this._clientWidth / 2;this._mrY = rect.top + this._clientHeight / 2; 再根据clientX/clientY当前位置坐标计算弧度: this._mrRadian = Math.atan2( e.clientY - this._mrY, e.clientX - this._mrX ) - this._radian; 这里把原来的弧度也顺便计算了。在拖动的过程中,根据移动坐标获取弧度,并调用rotate来旋转: this.rotate( Math.atan2( e.clientY - this._mrY, e.clientX - this._mrX ) - this._mrRadian ); ps:拖动效果请看这里关于拖动的研究。 滚轮缩放效果就是在容器上滚动鼠标会自动实现缩放效果。这个比较简单,主要是一些兼容问题,相关研究可以参考这里的鼠标滚动缩放。 使用技巧 【模式选择】 模式设置中说明了自定义模式可以用这样的格式:"css3|filter|canvas"。程序会自动按优先顺序选择支持的模式。为了尽量保证浏览器支持选择的模式,可以把三个模式都用上。一般filter是必须的,因为目前ie只支持这个,而css3和canvas可以自行选择。我在自己的电脑做了效率测试(就是用鼠标狂转图片),看cpu的占用情况:ff css3 40%ff canvas 35%opera css3 30%opera canvas 35%chrome css3 25%chrome canvas 55%safari css3 20%safari canvas 55%看来在ff和opera是canvas好一点,在WebKit就是css3快得多。但canvas只能画静态图片,对于gif那样的动态图片只能显示一帧,所以还是选css3比较好。 还有css3的变换能用在所有元素中(ie8的滤镜也可以),适用在html的变换,而canvas就更适合做复杂的图形和动画。 【选择图片】 程序实例化之后,还需要调用load方法加载指定的图片。参数可以是图片的路径,data url(支持的话),ie6还可以用本地路径。如果是gif图片,就要注意不要用canvas,原因上面也说了,canvas只能显示一帧图片。 使用说明 实例化时,必须有容器对象或id作为参数: var trans = new ImageTrans( container ); 然后调用load方法加载图片: trans.load(img); 可选参数用来设置系统的默认属性,包括:属性:    默认值//说明mode:  "css3|filter|canvas",zoom:  .1,//缩放比率onPreLoad: function(){},//图片加载前执行onLoad:  function(){},//图片加载后执行onError: function(err){}//出错时执行其中zoom、onPreLoad、onLoad、onError属性可以在程序初始化后动态设置。 提供以下变换方法:vertical:垂直翻转horizontal:水平翻转rotate: 旋转left:向左转90度right:向右转90度rotatebydegress:根据角度旋转scale:缩放zoomin:放大zoomout:缩小 还提供了以下方法:load:加载图片;reset:重置图像为默认状态;dispose:销毁程序。 加入拖动旋转扩展程序或滚轮缩放扩展程序后,会自动启用,可以自定义mouseRotate或mouseZoom属性为false来取消。

Html5

一个仿ipod的css3网页

16. 十月 2012
http://inventikasolutions.com/1000-songs-in-your-pocket-now-in-html5

Html5

简单html5标记示例

16. 十月 2012
  <!DOCTYPE html> <meta charset="UTF-8"> <title>HTML 5标记示例</title> <p>这段代码是根据HTML 5语法 <br/>编写出来的。

Html5

html5 canvas设置画布的大小

16. 十月 2012
设置canvas大小 var imgTest=new Image(); imgTest.src=imageURI; var canvas = document.createElement("canvas"); canvas.setAttribute('width',1024); canvas.setAttribute("height",1024); var ctx = canvas.getContext("2d"); ctx.drawImage(imgTest,0,0); var dataURL = canvas.toDataURL("image/png"); document.getElementById("test_img").src=dataURL;

Html5

游览器保存canvas生成的图片

13. 十月 2012
http://www.nihilogic.dk/labs/canvas2image/

Html5

介绍个很强的3D引擎

10. 九月 2012
solq  22:12:51 介绍个很强的3D引擎  http://mrdoob.com

Html5

一个nb的html5赛车游戏

29. 八月 2012
http://hexgl.bkcore.com/

Html5

javascript清除游览器localstorage

26. 八月 2012
localStorage.clear(); 如果希望手动的,可以去chrome或者safari插件商店下载localstorage插件。 利用插件去清除localstorage的数据

Html5

Html5中JSON.parse()与JSON.stringfy()方法

20. 八月 2012
Html5中JSON.parse()与JSON.stringfy()方法 后者可以将一个对象转换成字符串的形式,方便我们保存。 前者则可以将这一字符串转换成对象的形式,方面我们使用。

Html5

很淫荡的动画效果

17. 八月 2012
原文:http://www.staggeringbeauty.com/

Html5

ipad、ios的起始图片设置

15. 八月 2012
原文:http://stackoverflow.com/questions/10322634/start-up-screen-for-mobile-website-on-ipad 用js控制可以这样: <script> (function(){ var a; if(navigator.platform === "iPad") { a = window.orientation!==90||window.orientation === -90 ? "/assets/img/startup/startup-tablet-landscape.png" : "/assets/img/startup/startup-tablet-portrait.png"; } else { a = window.devicePixelRatio === 2 ? "/assets/img/startup/startup-retina.png" : "/assets/img/startup/startup.png"; } document.write('<link rel="apple-touch-startup-image" href="' + a + '"/>'); })(); </script> 不需要用js另外iphone起始的图片必须是320x460尺寸。 <!-- For iPhone 4 with high-resolution Retina display: --> <link rel="apple-touch-icon-precomposed" sizes="114x114" href="apple-touch-icon-114x114-precomposed.png"> <!-- For first-generation iPad: --> <link rel="apple-touch-icon-precomposed" sizes="72x72" href="apple-touch-icon-72x72-precomposed.png"> <!-- For non-Retina iPhone, iPod Touch, and Android 2.1+ devices: --> <link rel="apple-touch-icon-precomposed" href="apple-touch-icon-precomposed.png"> <!-- 320x460 for iPhone 3GS --> <link rel="apple-touch-startup-image" media="(max-device-width: 480px) and not (-webkit-min-device-pixel-ratio: 2)" href="startup-iphone.png"> <!-- 640x920 for retina display --> <link rel="apple-touch-startup-image" media="(max-device-width: 480px) and (-webkit-min-device-pixel-ratio: 2)" href="startup-iphone4.png"> <!-- iPad Portrait 768x1004 --> <link rel="apple-touch-startup-image" media="(min-device-width: 768px) and (orientation: portrait)" href="startup-iPad-portrait.png"> <!-- iPad Landscape 1024x748 --> <link rel="apple-touch-startup-image" media="(min-device-width: 768px) and (orientation: landscape)" href="startup-iPad-landscape.png">

Html5

Html5开发腾讯微博如何实现发送一条微博功能

14. 八月 2012
和新浪微博同样的情况,腾讯微博也是需要以post方式提交发送微博的请求。 好了我们说下做法: 1.首先需要下载sdk http://wiki.open.t.qq.com/index.php/SDK%E4%B8%8B%E8%BD%BD(lz选择的是C#SDK) 2.需要查看api中发送微博的参数情况可以在这里 http://wiki.open.t.qq.com/index.php/%E5%BE%AE%E5%8D%9A%E7%9B%B8%E5%85%B3/%E5%8F%91%E8%A1%A8%E4%B8%80%E6%9D%A1%E5%BE%AE%E5%8D%9A 3.执行代码:   OauthKey oauthKey = new OauthKey(); oauthKey.customKey = "你的appkey"; oauthKey.customSecret = "你的appsecret"; oauthKey.tokenKey = "你的tokenkey"; oauthKey.tokenSecret = "你的tokenSecret"; t qqT = new t(oauthKey, "json"); qqT.add("我是天才1 from tecent weibo .net sdk", "112.65.180.174", "111", "222");     项目源代码可去qq群共享下载:224711028

Html5, 腾讯微博

html5开发新浪微博如何实现发送微博的功能

13. 八月 2012
在做微博功能的时候,html5通常都会用到jsonp的请求,但是jsonp的请求有个问题,貌似都是以get方式发送请求的,对于一些需要以post方式提交数据的接口就抓瞎了,怎么办。。。。万般无奈借助之下,lz借助了服务器端wcf的新浪微博sdk完美破解了不能发送微博的问题,也算是不幸中的大幸了。 做法: 1.首先下载.net sdk(不喜欢.net的还有java、php): http://weibosdk.codeplex.com/   2.在项目中调用的代码(因为token可以通过phonegap的子游览器插件获得这里传给服务器http://blog.csdn.net/xiaoguang44/article/details/7786045): var oauth = new OAuth("你的AppKey", "你的AppSecret", "你的access_token", null); TokenResult result = oauth.VerifierAccessToken(); if ("Success"==result.ToString()) { Console.WriteLine(oauth.AccessToken); //还是来打印下AccessToken看看与前面方式获取的是不是一样的 var Sina = new NetDimension.Weibo.Client(oauth); var uid = Sina.API.Entity.Account.GetUID(); //调用API中获取UID的方法 Sina.API.Entity.Statuses.Update(" Sencha Touch 交流 QQ 群 224711028 欢迎您的加入。Phonegap Andriod 交流 QQ 群 250395324欢迎您的加入 "); Console.WriteLine(uid); } 项目代码可去lz的qq群共享下载(224711028)

Html5

html5人脸识别

10. 八月 2012
http://www.html5china.com/course/20120528_3742.html http://miernicki.com/cam.html

Html5

如何用HTML5+PHONEGAP写个PATH出来?

9. 八月 2012
原文:http://ftqq.com/2011/12/30/how-to-build-a-path-like-app-using-html5-and-phonegap/ 最近Path这个应用很火爆,网上也出现了不少仿Path菜单的项目。即使在原生APP里边,Path的效果也是非常赞的。 我突然想,Web APP是不是也能做出类似Path那样的效果呢?于是就有了OPath这个项目,它的客户端部分是完全用PhoneGap+HTML5开发的。 坦白的讲,OPath比Path差得不是一点半点,但是比很多国产的原生应用体验要好,下边是演示视频。 http://you.video.sina.com.cn:8080/api/sinawebApi/outplayrefer.php/vid=68928297_1088413295_bx69HHcwCTPK+l1lHz2stqkP7KQNt6nkiWK8v1OnJwdcQ0/XM5GfatQF6CvfB9kEqDhAQpA2d/Yk3ho/s.swf 看完视频如果你对效果还满意的话,请接着往下看。我会和大家分享如何做一个这样的应用,包括整个前端(HTML5)和后端(PHP)。 这个项目也是在MIT协议下完全开源的(同样包括前端和后端),项目链接在文章最末尾。 PS:我只在iPod Touch4的iOS5系统上进行了测试,其他平台可能存在兼容性问题,需要自行测试和修复。 框架选择 PhoneGap就不用说了,有了它才能打包。我们要选的里边的前端框架。虽然之前我已经做了一个基于Jquery Mobile的Tab类模板,但是很明显,Path并没有采用Tab方式的菜单。 加上Path的控件都是自己的风格,所以自己渲染样式是逃不掉的,于是最后我选择了采用Mobile-boilerplate  + iScroll4 来做这个项目。 Mobile-boilerplate Mobile-boilerplate 是一个移动设备用的HTML5空白模板,它处理掉了非常多的兼容细节,比如viewport之类的。想了解详情的同学可以去看Mobile-boilerplate里边的注释,写得非常详细,还有相关issue的链接。 下载Mobile-boilerplate将解压出来的目录作为我们项目的根目录。Mobile-boilerplate已经包含了js和css目录,其中js下的libs里边有JQuery。   我首先在Mobile-boilerplate的模板基础上做了下登录页面,完成后的效果是这样的:   这个界面很简单,直接用CSS来实现就可以了,遵守Mobile-boilerplate的结构,在css/style.css中部200行左右的位置开始写入自己的css。   API接口的用户认证 接下来我们说说API方式用户认证的实现。在OPath项目中,我们采用用户名+密码换token,以后操作通过token鉴权的方式。 因为这种方式实现起来很方便。做PHP的同学都知道,PHP的Session机制是通过PHP SESSION ID来标示用户的,一般情况下这个标示通过Cookie存储在浏览器中。 我们的思路就是,将这个SESSION ID直接作为token就好啦。于是我们实现了get_token接口: 最核心的逻辑就这几行 session_start();$token = session_id(); // 将Session id作为token$_SESSION['token'] = $token; // 在Session中存储用户信息,供以后的操作认证使用。$_SESSION['uid'] = $user['id'];$_SESSION['name'] = $user['name'];$_SESSION['email'] = $user['email'];$_SESSION['level'] = $user['level']; token在生成后,通过json格式返回给客户端。 客户端发送AJAX请求和解析参数 现在回到客户端这边来,当用户在登录页面填好账号后,我们需要将这些数据发送到服务器端,换取token。使用JQuery,这个很简单: 我们用 jQuery.parseJSON 解析返回的JSON数据,然后在登录正确后,将账号和token保存到本地。这里的kset其实是我写的一个快捷函数,它只是简单封装了下HTML5的LocalStorage。 function kset( key , value ){window.localStorage.setItem( key , value );} function kget( key ){return window.localStorage.getItem( key );} function kremove( key ){window.localStorage.removeItem( key );} LocalStorage里边的数据是持久化的,在应用被关闭后依旧存在。顺便说下,在Chrome和Safari的调试工具里边,Resource的Tab里边可以直接看到当前应用的LocalStorage还有IndexedDB的数据,不用去找其他的工具来查看这些值。这在调试应用的时候非常方便。 由于开发的应用是HTML5的,我首先会实现标准浏览器支持的部分,用Safari来进行调试;在最后才实现需要PhoneGap的部分,进行真机调试,这样可以节省很多调试时间。 PATH主页面 Path的主页面很帅,实现细节也很多,我挑重点说。先放一张做完后的效果: 整体的布局上,其实我们可以直接沿用iScroll4的Demo,顶栏固定,将原来的Footer换成那个加号按钮就可以了。加号按钮的实现网上有CSS版本的,但是在Android上会出现严重的毛边,所以我直接用图片代替了。(Android上CSS圆角毛边的问题非常烦人,从这个地方可以一眼认出是否是WebAPP;iOS上则非常干净。)考虑到iPod Touch(我主要用这个)的杯具性能,我只简单做了个位置移动效果,觉得细节不够的同学可以自己加旋转和弹簧效果,用JQuery很容易做。说实话我觉得原版Path的那个加号按钮展开后很难按准 T__T 页面上方的Profile Picture部分放到iScroll的wrapper内,scroll最上方;下边的【加载更多】按钮,放到wrapper内,scroll最下方。均通过CSS指定固定高。 其他的布局细节可以查看path.html和style.css源文件。 RETINA屏幕下的图片模糊问题 在iScroll的基础上,我很快就完成了主页面的布局,但是当我放到头像和图片后,杯具发生了!在Android上看的时候很正常,但是在Touch上图片会变得非常模糊。 按Mobile-boilerplate的viewport设定,整个页面宽度应该会变成 设备宽,对Touch来说就是320px。 很快我就意识到这应该是Retina屏幕带来的问题,因为Retina屏将标准屏幕一个像素改用4个像素显示,所以图像和周围的矢量图对比起来就模糊了。 而在Android上都采用一个像素显示,所以没有这个问题。 Google了下,网上的解决方案是这样的: 对于直接的图片应用,比如说 <img src=”image.png”/> 采用Retina屏幕的iOS设备会去找同目录下的 image@2x.png进行显示。 对于通过CSS引用的图片,比如说 <div id=”avatar”></div> 则需要使用link标签按条件载入专用的CSS。 <link rel="stylesheet" media="only screen and (-webkit-min-device-pixel-ratio: 2)" type="text/css" href="../iphone4.css" /> 我测试了下,没有成功,更主要的还是觉得这个方案不爽,额外CSS什么的弱爆了。然后自己试出来了一个方案: 因为模糊的原理已经很清楚了,那么只要朝这个方向去想就行。 对于直接引用图片的情况,很容易想到解决方案:原本100*100的图片,我做成200*200,然后在img标签中指定高和宽为100*100。这样在Retina屏幕上可以按像素点进行显示,在其他屏幕的设备上,浏览器会自己先缩放后显示,测试效果很清晰。 通过CSS引用的情况比较麻烦,我睡了一觉才想出来,如果div#avatar要显示100*100的背景,那么将它的高和宽指定为200*200,配上200*200的背景图片,最后,Zoom:0.5。 其他页面需要注意的地方 其他页面基本上都是体力劳动了,Path Feed列表渲染时有两个需要注意的细节: 一是我们用的模板本身是用<script>标签的,所以模板里边就不能再有这个标签了。在显示每条Feed时,需要显示对应的用户头像,这个头像当做背景显示的,由于不能用script标签,只好把url先放到标签里,渲染完后统一处理。 二是当Feed里边有图片的时候,iScroll的高度会受影响。需要在图片加载完全后,再重新调用iScroll的refresh方法。在Feed中图片过多时,Feed页面会卡,这个问题可以通过串行载入图片资源的方式来解决,在当前这个版本里边,没有实现。 Thought页面这部分没有太多问题,采用了之前Tab模板的Div切换方式,从而逼近原生应用的切换速度。 通过PHONEGAP实现拍照和头像设置 头像和拍照使用PhoneGap调用了本地设备,按PhoneGap的说明,加载PhoneGap的JS文件并在页面初始化时注册好事件。 在点击了拍照按钮或者头像按钮后,调用摄像头,并通过PhoneGap提供的的文件传输对象FileTransfer进行上传。FileTransfer可以模拟一个完全的HTTP请求,所以服务器端并不需要特殊出来,按带file标签的标准From请求处理即可。 需要额外处理的是,iOS拍摄的图片方向很可能不对。这是因为iOS本地的相册在显示图片时,根据拍摄时的方向自动做了调整。要在服务器端正确的显示图像,必须根据图片中的Exif信息调整方向。在将家里的小浪摆好Pose并通过各个方向的拍摄后,我写好了调整方向的函数。 所有的代码,我已经放到google code上,大家可以下载。这些代码是MIT协议,可以随意商用。 开发以外 兼容性 由于各个平台对CSS和HTML5 的支持差异很大,所以很难在全部平台做到完美,像之前提到过的,Android的CSS圆角毛边问题,Div切换时部分图层不定期隐藏的问题;另外PhoneGap还有各种BUG和问题,比如iOS应用从后台呼出时有短暂的白屏闪烁问题;比如OPath里边我使用了1.2版本,这个版本在iOS下拍照正常,但是在Android下呼叫不出摄像头,换成1.0版本就可以,这说明PhoneGap在平台兼容性上问题依然不少。 个人感觉,在现阶段,一个PhoneGap应用要想做到完美的体验并在各个平台保持体验一致,难度非常大。不过如果能忍受一些小细节,或者能做好优雅降级的话,PhoneGap应用是能超过很多原生应用的。 代码安全性 采用PhoneGap打包的应用,不管是APK还是IPA,只要将扩展名改为zip,解压后在www目录就可以得到这个应用的全部源代码。 这使得盗版成本非常的低,必要的时候需要对js进行混淆。最可靠的方式是将部分核心逻辑放到云端,通过api使用。

Html5

Html5做的俄罗斯方块

7. 八月 2012
  Sencha Touch 交流 QQ 群 224711028 欢迎您的加入 项目下载地址:http://bbs.cfxixi.com/showtopic-25.aspx

Html5

flipboard的js实现

26. 七月 2012
原文:http://tympanus.net/codrops/2012/05/07/experimental-page-layout-inspired-by-flipboard/

Html5

Html5史无前例学习网站

24. 七月 2012
1.http://www.mangguo.org/the-ultimate-html5-resource-guide/ 教程网站 2.http://tympanus.net/codrops/ 源码 3.http://css.doyoe.com/ css3参考手册 4.http://www.cnblogs.com/lhb25/archive/2012/04/24/25-coolest-css3-effects-roundup.html 推荐css3网站

Html5

Html5制作一个简单网站

24. 七月 2012
原文:http://www.designzzz.com/website-layout-tutorial-html-5-css-3/ 项目源代码去我群共享下载: Sencha Touch 交流 QQ 群 224711028 欢迎您的加入 Starting HTML Tutorial Code: 框架: <!Doctype html> <html lang="en"> <head> <title>Your Page title</title> </head> <body> <!-- Define Header --> <header> </header> <!-- End Header --> <!-- Define Navigation/Menu --> <nav> </nav> <!-- End Navigation --> <!-- Main content area --> <section> </section> <!-- End of Main content area --> <!-- Sidebar --> <aside> </aside> <!-- End Sidebar --> <!-- Footer --> <footer></footer> <!-- End of Footer --> </body> </html>   定义 Header Tag: <header> <h1>HTML 5 Tutorial Sample </h1> </header>   定义导航栏区域 with Few links in it: <nav> <ul> <li><a href="#">Home</a></li> <li><a href="#">About Us</a></li> <li><a href="#">Feedback</a></li> <li><a href="#">Contact</a></li> </ul>   定义 CSS3 for Rounded Corners: nav { width:77%; height:40px; -moz-border-radius:10px; -webkit-border-radius:10px; border-radius:10px; //for opera background:#f3f3f3; border:1px solid #cccccc; position:absolute; } nav ul { list-style-image:none; list-style-position:outside; list-style-type:none; margin:0 auto; width:940px; } nav ul li { float:left; } nav ul li a{ margin-right:20px; display:block; line-height:40px; } 定义 the Footer: <footer> <section>Anything you want to put in footer goes here. </section> </footer>   footer样式 footer{background:#666666; border-top:1px solid #cccccc; padding:10px; -moz-border-radius-topleft:5px; -moz-border-radius-topright:5px; border-radius:5px; // for Opera text-align:center; color:#ffffff; }

Html5

jquery制作3d画廊功能

6. 七月 2012
Demo示例:http://3dgallery.sinaapp.com/#   lz我加了一个刷的功能用的是harmer.js 其中核心代码: 1.在$.Gallery.prototype的init函数中定义变量:   this.hammer=new Hammer(this.$el.find(".dg-wrapper").get(0));   2.在_loadEvents函数中定义事件: this.hammer.onswipe=function(event){ //alert(event.direction); if(event.direction=="left"){ if( _self.options.autoplay ) { clearTimeout( _self.slideshow ); _self.options.autoplay = false; } _self._navigate('next'); return false; }else if(event.direction=="right"){ if( _self.options.autoplay ) { clearTimeout( _self.slideshow ); _self.options.autoplay = false; } _self._navigate('prev'); return false; } }  

Html5, JQuery

css3图片旋转

3. 七月 2012
 -webkit-transform: rotate(5deg); 一行代码。。 

css3, Html5

websql突然无法查询到数据或id为undefined

16. 六月 2012
1.很可能是因为数据库类型为Integer 允许介于 -32,768 到 32,767 之间的数字。 2.还有一种可能是曾经定义过表结构,表中id的数据类型定义为int,之后改为text型但是没有清除cookie以至于情况1的发生,无法查到数据。

Html5

如何解决websql中的异步问题

4. 六月 2012
1.首先websql openDatabase()方法打开数据库的其结果必然以异步方式返回结果,openDatabaseSync()方法可以同步方式打开数据库,但是貌似safari游览器中找不到这样的一个方法。 原文:http://stackoverflow.com/questions/4052479/html5-database-api-synchronous-request To get an object implementing DatabaseSync you have to call openDatabaseSync(...) instead ofopenDatabase(...). I don't know about the iPhone, or what the oDB object you have is, but according to spec you only get the openDatabaseSync method in a WebWorker and not in the normal web browser window. Certainly XMLHttpRequest has demonstrated that potentially-length synchronous operations in the UI thread are not a good idea.   2.看了老外的另外一个方案:http://stackoverflow.com/questions/3903155/synchronous-query-to-web-sql-database 发现其实可以直接写在回调函数中不必拆分成多个函数,这样就可以解决异步的问题了,如下(所有代码逻辑都在回调函数中完成):   function getFolder(id, callback) { var data = []; ldb.transaction(function (tx) { tx.executeSql('SELECT * FROM folders where id=?', [id], function (tx, results) { if (results.rows && results.rows.length) { for (i = 0; i < results.rows.length; i++) { data.push(results.rows.item(i)); } } if ( typeof(callback) == 'function' ) callback(data); }, function (tx, error) { console.log(error); }); });  

Html5, WebSQL

html5将image本地转成base64格式

2. 六月 2012
方法: function getBase64Image() { alert("dsfdf"); var img =document.getElementById("aaa"); var canvas = document.createElement("canvas"); var ctx = canvas.getContext("2d"); ctx.drawImage(img, 0, 0); var dataURL = canvas.toDataURL("image/png"); //document.write(dataURL+"<br />"); alert(dataURL+"<br />"); } 调用: <input type="button" value="上传" onClick="javascript:getBase64Image()"/>

Html5

html5 客户端拖拽事件执行图片转base64

25. 五月 2012
    思路就是  在某个事件触发的时候   var files = e.dataTransfer.files var itemp = 0; for ( var i = 0; i < files.length; i++) { var file = files[i]; (function(file) { var oFReader = new FileReader(); oFReader.onload = function() { document.getElementById('txtbase64').value = (this.result); } oFReader.readAsDataURL(file); })(file); }    

Html5

HTML5 跨域信息交互技术之 postMessage

15. 五月 2012
原文:http://blog.csdn.net/jackiewell/article/details/7325132 我们知道传统的HTML 规范中对于跨域的请求有这严格的限制,如果没有这个限制,将会发生很可怕的事情,设想一个场景当你在公司上班打开公司内部的管理信息系统,同时你打开了另一个外部网页页面, 那个外部网页中的动态脚本比如JS 脚本可以嗅探到你公司内部管理信息系统的内容,假如你公司的信息系统是一些敏感的信息时,其实你在不知不觉中已经泄漏了公司的信息,由此可能将会造成给公司很大的损失,所以浏览器是阻止这些跨域访问。  但是现实生活中有一些合理的跨域名站点间的交互,读者可能知道 传统HTML 规范中关于跨域的解决方法,比如 iframe方式、jsonp方式等,今天我要说的是HTML5 中关于跨域数据交互方面的知识。    HTML5中引入了 一个新的API 称为 postMessage ,其实postMessage不管是否有跨域操作, 都建议使用postMessage 来传递消息。    废话不多说,看一个Demo 先。我们配置两个域名 http://www.yuetong.com/                 http://my.bbs.com/在 http://www.yuetong.com/ 域下新建 comm_main.html, 地址 为http://www.yuetong.com/comm_main.html文件内容如下 <!DOCTYPE html> <html> <head>         <meta charset="utf-8"/>     <title>跨站通信 当前域 http://www.yuetong.com</title>     <script type="text/javascript"> function sendMsg(){     if(typeof window.postMessage == undefined){         //         alert("对不起 您的浏览器不支持 postMessage 特性");         return false;     }     var msg = document.getElementById("message").value;     document.getElementsByTagName("iframe")[0].contentWindow.postMessage(msg,"http://my.bbs.com"); } var originWhiteList = ["http://my.bbs.com"]; function checkWhiteList(origin){          for(var i=0; i< originWhiteList.length; i++){         if(origin == originWhiteList[i]){             return true;         }     }     return false; } /** 接受消息 */ function messageHandler(e){     if(checkWhiteList(e.origin)){         processMessage(e.data);     }else{         // ignore message     } } function processMessage(d){     alert(d); } window.addEventListener("message", messageHandler, true);     </script> </head> <body> <h1>您好,我这里是http://www.yuetong.com/</h1> <input type="text" name="message" id="message" value=""/> <input type="button" name="handler" value="发生消息" onclick="sendMsg()"/> <br/> <iframe name="msg" src="http://my.bbs.com/comm_client.html" width="400" height="400"/> <div></div> </body> </html> 在 http://my.bbs.com/ 域下新建 comm_client.html, 地址 为http://my.bbs.com/comm_main.html,文件内容如下 <!DOCTYPE html> <html> <head>         <meta charset="utf-8"/>     <title>跨站通信 当前域 http://my.bbs.com</title> <script type="text/javascript"> var originWhiteList = ["http://www.yuetong.com"]; function checkWhiteList(origin){          for(var i=0; i< originWhiteList.length; i++){         if(origin == originWhiteList[i]){             return true;         }     }     return false; } function messageHandler(e){     if(checkWhiteList(e.origin)){         processMessage(e.data);     }else{         // ignore message     } } function processMessage(d){     var ta = document.getElementsByTagName("textarea")[0].value;     ta += d + "\n";          document.getElementsByTagName("textarea")[0].value = ta; } function sendMsg(){     var msg = document.getElementById("message").value;     window.top.postMessage(msg,"http://www.yuetong.com"); } window.addEventListener("message",messageHandler,true); </script> </head> <body> <h1>您好,我这里是 http://my.bbs.com/</h1> <input type="text" name="message" id="message" value=""/> <input type="button" name="handler" value="发生消息" onclick="sendMsg()"/> <textarea name="msg" rows="15" cols="40"></textarea> </body> </html>

Html5

Html DataBase示例

9. 五月 2012
原文:http://www.html5rocks.com/en/tutorials/webdatabase/todo/ 参考1:http://hi.baidu.com/aboutstudy/blog/item/fcbf728ba91e45dffd1f1037.html 交流群:224711028 现在不需要借助手机的数据库,网页也能够存储数据了      <!DOCTYPE html> <html> <head> <style> body { color: #222; font: 14px Arial; } body a { color: #3D5C9D; text-decoration: none; } </style> <script> var html5rocks = {}; html5rocks.webdb = {}; html5rocks.webdb.db = null; html5rocks.webdb.open = function() { var dbSize = 5 * 1024 * 1024; // 5MB html5rocks.webdb.db = openDatabase("Todo", "1.0", "Todo manager", dbSize); } html5rocks.webdb.createTable = function() { var db = html5rocks.webdb.db; db.transaction(function(tx) { tx.executeSql("CREATE TABLE IF NOT EXISTS todo(ID INTEGER PRIMARY KEY ASC, todo TEXT, added_on DATETIME)", []); }); } html5rocks.webdb.addTodo = function(todoText) { var db = html5rocks.webdb.db; db.transaction(function(tx){ var addedOn = new Date(); tx.executeSql("INSERT INTO todo(todo, added_on) VALUES (?,?)", [todoText, addedOn], html5rocks.webdb.onSuccess, html5rocks.webdb.onError); }); } html5rocks.webdb.onError = function(tx, e) { alert("There has been an error: " + e.message); } html5rocks.webdb.onSuccess = function(tx, r) { // re-render the data. html5rocks.webdb.getAllTodoItems(loadTodoItems); } html5rocks.webdb.getAllTodoItems = function(renderFunc) { var db = html5rocks.webdb.db; db.transaction(function(tx) { tx.executeSql("SELECT * FROM todo", [], renderFunc, html5rocks.webdb.onError); }); } html5rocks.webdb.deleteTodo = function(id) { var db = html5rocks.webdb.db; db.transaction(function(tx){ tx.executeSql("DELETE FROM todo WHERE ID=?", [id], html5rocks.webdb.onSuccess, html5rocks.webdb.onError); }); } function loadTodoItems(tx, rs) { var rowOutput = ""; var todoItems = document.getElementById("todoItems"); for (var i=0; i < rs.rows.length; i++) { rowOutput += renderTodo(rs.rows.item(i)); } todoItems.innerHTML = rowOutput; } function renderTodo(row) { return "<li>" + row.todo + " [<a href='javascript:void(0);' onclick='html5rocks.webdb.deleteTodo(" + row.ID +");'>Delete</a>]</li>"; } function init() { html5rocks.webdb.open(); html5rocks.webdb.createTable(); html5rocks.webdb.getAllTodoItems(loadTodoItems); } function addTodo() { var todo = document.getElementById("todo"); html5rocks.webdb.addTodo(todo.value); todo.value = ""; } </script> </head> <body onload="init();"> <ul id="todoItems"> </ul> <form type="post" onsubmit="addTodo(); return false;"> <input type="text" id="todo" name="todo" placeholder="What do you need to do?" style="width: 200px;" /> <input type="submit" value="Add Todo Item"/> </form> </body> </html>​

Html5