描述cookie,sessionstroage,localstrage的区别

HTML5 提供了两种在客户端存储数据的新方法(Web Storage):

  • localStorage - 没有时间限制的数据存储
  • sessionStorage - 针对一个 session 的数据存储

之前,这些都是由 cookie 完成的。但是 cookie 不适合大量数据的存储,因为它们由每个对服务器的请求来传递,这使得 cookie 速度很慢而且效率也不高。

localStorage 方法存储的数据没有时间限制。第二天、第二周或下一年之后,数据依然可用。

sessionStorage 方法针对一个 session 进行数据存储。当用户关闭浏览器窗口后,数据会被删除。

对比session和cookie的优点主要提现在一下三点:

1、容量大,IE8里是10M,不同浏览器支持大小不一致。

2、不会随着回话来传输。

3、读取和写入方便,有现成的sessionStorage.setItem(key,value),sessionStorage.getItem(key),localStorage.setItem(key,value),localStorage.getItem(key)方法。

http://www.w3school.com.cn/html5/html_5_webstorage.asp

http://www.cnblogs.com/xiaowei0705/archive/2011/04/19/2021372.html

原文地址:http://www.cnblogs.com/sunflower627/p/4873101.html

继续阅读 »

HTML5 提供了两种在客户端存储数据的新方法(Web Storage):

  • localStorage - 没有时间限制的数据存储
  • sessionStorage - 针对一个 session 的数据存储

之前,这些都是由 cookie 完成的。但是 cookie 不适合大量数据的存储,因为它们由每个对服务器的请求来传递,这使得 cookie 速度很慢而且效率也不高。

localStorage 方法存储的数据没有时间限制。第二天、第二周或下一年之后,数据依然可用。

sessionStorage 方法针对一个 session 进行数据存储。当用户关闭浏览器窗口后,数据会被删除。

对比session和cookie的优点主要提现在一下三点:

1、容量大,IE8里是10M,不同浏览器支持大小不一致。

2、不会随着回话来传输。

3、读取和写入方便,有现成的sessionStorage.setItem(key,value),sessionStorage.getItem(key),localStorage.setItem(key,value),localStorage.getItem(key)方法。

http://www.w3school.com.cn/html5/html_5_webstorage.asp

http://www.cnblogs.com/xiaowei0705/archive/2011/04/19/2021372.html

原文地址:http://www.cnblogs.com/sunflower627/p/4873101.html

收起阅读 »

html5 Canvas 拖拽

源码


//获取到舞台
var canvas=document.getElementById("stage");
//舞台2d绘图接口
var context=canvas.getContext("2d");
//获取中心点置
var centerX=canvas.width/2;
var centerY=canvas.height/2;
             /**
              * 球对象
              
*/
             var Ball=function(x,y,radius,color)
             {
//球的中心点位置
this.x=x;
this.y=y;
//球的半径
this.radius=radius;
//球的颜色
this.color=color;
//球的边框颜色
context.strokeStyle = color;
//球体颜色
context.fillStyle=color; 
/**
  * 绘制球
  
*/ 
this.draw=function()
{
context.clearRect(0,0,centerX*2,centerY*2);
context.beginPath(); 
                     context.arc(this.x, this.y, this.radius, 0, 2 * Math.PI, false); 
                     context.fill(); 
                     context.stroke();
                     context.closePath();
}
             } 
             //球的半径 
             var rd=20;
             //创建一个球对象,让球在马路的最左边
             var ball=new Ball(centerX*Math.random(),centerY*Math.random(),rd,"#ccc"); 
             //显示球
             ball.draw(); 
             canvas.addEventListener("mousedown",OnMouseDown,false);
             canvas.addEventListener("mousemove",OnMouseMove,false);
             canvas.addEventListener("mouseup",OnMouseUp,false);
             var isDown=false;
             function OnMouseDown(evt)
             {

var mouseX=evt.layerX;
                 var mouseY=evt.layerY;
                 var dx=mouseX-ball.x;
                 var dy=mouseY-ball.y;
                 //计算从圆心到鼠标点击的距离
var len=Math.sqrt(dx*dx+dy*dy);
if(Math.abs(len)<=rd)
{
isDown=true;

else
{
isDown=false;
}
             }
             function OnMouseMove(evt)
             {
if(isDown)
{
var mouseX=evt.layerX;
var mouseY=evt.layerY;
ball.x=mouseX;
ball.y=mouseY;
ball.draw(); 
}
             }
             function OnMouseUp(evt)
             {
isDown=false;

             } 

 作者:Louja

出处:http://loujady.cnblogs.com
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此声明,且在文章页面给出原文连接,否则保留追究法律责任的权利。 

 

原文地址:http://www.cnblogs.com/loujady/archive/2011/12/10/2283272.html

继续阅读 »

源码


//获取到舞台
var canvas=document.getElementById("stage");
//舞台2d绘图接口
var context=canvas.getContext("2d");
//获取中心点置
var centerX=canvas.width/2;
var centerY=canvas.height/2;
             /**
              * 球对象
              
*/
             var Ball=function(x,y,radius,color)
             {
//球的中心点位置
this.x=x;
this.y=y;
//球的半径
this.radius=radius;
//球的颜色
this.color=color;
//球的边框颜色
context.strokeStyle = color;
//球体颜色
context.fillStyle=color; 
/**
  * 绘制球
  
*/ 
this.draw=function()
{
context.clearRect(0,0,centerX*2,centerY*2);
context.beginPath(); 
                     context.arc(this.x, this.y, this.radius, 0, 2 * Math.PI, false); 
                     context.fill(); 
                     context.stroke();
                     context.closePath();
}
             } 
             //球的半径 
             var rd=20;
             //创建一个球对象,让球在马路的最左边
             var ball=new Ball(centerX*Math.random(),centerY*Math.random(),rd,"#ccc"); 
             //显示球
             ball.draw(); 
             canvas.addEventListener("mousedown",OnMouseDown,false);
             canvas.addEventListener("mousemove",OnMouseMove,false);
             canvas.addEventListener("mouseup",OnMouseUp,false);
             var isDown=false;
             function OnMouseDown(evt)
             {

var mouseX=evt.layerX;
                 var mouseY=evt.layerY;
                 var dx=mouseX-ball.x;
                 var dy=mouseY-ball.y;
                 //计算从圆心到鼠标点击的距离
var len=Math.sqrt(dx*dx+dy*dy);
if(Math.abs(len)<=rd)
{
isDown=true;

else
{
isDown=false;
}
             }
             function OnMouseMove(evt)
             {
if(isDown)
{
var mouseX=evt.layerX;
var mouseY=evt.layerY;
ball.x=mouseX;
ball.y=mouseY;
ball.draw(); 
}
             }
             function OnMouseUp(evt)
             {
isDown=false;

             } 

 作者:Louja

出处:http://loujady.cnblogs.com
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此声明,且在文章页面给出原文连接,否则保留追究法律责任的权利。 

 

原文地址:http://www.cnblogs.com/loujady/archive/2011/12/10/2283272.html

收起阅读 »

html5高级程序设计第二章之Canvas API上篇

  1. HTML5 Canvas概述:Canvas的概念最初是由苹果公司提出的,用于在Mac OS X WebKit中创建控制板部件(dashboard widget).在Canvas出现之前,开发人员若要在浏览器中使用绘图API,只能使用Adobe的Flash和SVG(Scalable Vector Graphics,可伸缩矢量图形)插件,或者只有IE才支持的VML(Vector Markup Language,矢量标记语言),以及其他一些稀奇古怪的JavaScript技巧。假设我们要在没有canvas元素的条件下绘制一条对角线--听起来似乎很简单,但实际上如果没有一套二维绘图API的话,这会是一项相当复杂的工作。HTML5 Canvas能够提供这样的功能,对浏览器端来说此功能非常有用,因此Canvas被纳入了HTML5规范。起初,苹果公司曾暗示可能会为WHATWG(Web Hypertext Application Technology Working Group,Web超文本应用技术工作组)草案中的Canvas规范申请知识产权,这在当时引起了一些Web标准化追随者的关注。不过,苹果公司最终还是按照W3C的免版税专利权许可条款公开了其专利。
  2. 基本的Canval元素:
  3. 使用Cancas编程,首先要获得其上下文(context)。接着在上下文中执行动作,最后将这些动作应用到上下文中
  4. Canvas坐标:从左上角开始,X轴沿水平方向(按像素向右延伸),Y轴沿垂直向下延伸。左上角坐标x=0,y=0的点称为坐标原点,坐标图如下:

  5. 使用HTML5 Canvas API
  • 检查浏览器支持情况:
    try{
    document.createElement("canvas").getContext("2d");
    document.getElementById("support").innerHTML = "HTML5 Canvas is support in your browser";//获取canvas元素及其绘图的上下文
    }
    catch(e){
      document.getElementById("support").innerHTML = "HTML5 Canvas is NOT support in your browser";
    }

     

  • 在页面中加入canvas:
    //显示出一块200*200像素的隐藏区域
    <canvas id="diagonal" style="border:1px solid;"  height="200" width="200">canvas>

     

  • 在canvas中绘制一条对角线:
    DOCTYPE html>
    <html>
      <title>Diagonal line exampletitle>
    
      <canvas id="diagonal" style="border: 1px solid;"  width="200" height="200"> canvas>
      <script>
            function drawDiagonal() {
                // 通过id取得canvas元素及其绘图上下文 
                var canvas = document.getElementById('diagonal');
                var context = canvas.getContext('2d');//获取一个二维上下文
    
                // 用绝对坐标来创建一条路径 
                context.beginPath();
                context.moveTo(70, 140);
                context.lineTo(140, 70);
    
                // 将这条直线绘制到canvas上
                context.stroke();
            }
    
            window.addEventListener("load", drawDiagonal, true);
      script>
    html>

    在画直线的过程中调用了三个方法-----beginPath moveTo和lineTo方法,传入这条线的起点和终点的坐标。从以上的例子中可以看出,canvas中所有的操作都是通过上下文对象来完成的。对上下文的很多操作都不会立即反映到页面上,beginPath,moveTo,以及lineTo这些函数都不会直接修改canvas的展示结果。canvas很多用于设置样式和外观的函数都不会直接修改显示结果。只有对路径应用绘制(stroke)或填充(fill)方法,结果才会显示出来。

     

 

原文地址:http://www.cnblogs.com/cnblogs-lin/archive/2012/05/11/2496560.html

继续阅读 »
  1. HTML5 Canvas概述:Canvas的概念最初是由苹果公司提出的,用于在Mac OS X WebKit中创建控制板部件(dashboard widget).在Canvas出现之前,开发人员若要在浏览器中使用绘图API,只能使用Adobe的Flash和SVG(Scalable Vector Graphics,可伸缩矢量图形)插件,或者只有IE才支持的VML(Vector Markup Language,矢量标记语言),以及其他一些稀奇古怪的JavaScript技巧。假设我们要在没有canvas元素的条件下绘制一条对角线--听起来似乎很简单,但实际上如果没有一套二维绘图API的话,这会是一项相当复杂的工作。HTML5 Canvas能够提供这样的功能,对浏览器端来说此功能非常有用,因此Canvas被纳入了HTML5规范。起初,苹果公司曾暗示可能会为WHATWG(Web Hypertext Application Technology Working Group,Web超文本应用技术工作组)草案中的Canvas规范申请知识产权,这在当时引起了一些Web标准化追随者的关注。不过,苹果公司最终还是按照W3C的免版税专利权许可条款公开了其专利。
  2. 基本的Canval元素:
  3. 使用Cancas编程,首先要获得其上下文(context)。接着在上下文中执行动作,最后将这些动作应用到上下文中
  4. Canvas坐标:从左上角开始,X轴沿水平方向(按像素向右延伸),Y轴沿垂直向下延伸。左上角坐标x=0,y=0的点称为坐标原点,坐标图如下:

  5. 使用HTML5 Canvas API
  • 检查浏览器支持情况:
    try{
    document.createElement("canvas").getContext("2d");
    document.getElementById("support").innerHTML = "HTML5 Canvas is support in your browser";//获取canvas元素及其绘图的上下文
    }
    catch(e){
      document.getElementById("support").innerHTML = "HTML5 Canvas is NOT support in your browser";
    }

     

  • 在页面中加入canvas:
    //显示出一块200*200像素的隐藏区域
    <canvas id="diagonal" style="border:1px solid;"  height="200" width="200">canvas>

     

  • 在canvas中绘制一条对角线:
    DOCTYPE html>
    <html>
      <title>Diagonal line exampletitle>
    
      <canvas id="diagonal" style="border: 1px solid;"  width="200" height="200"> canvas>
      <script>
            function drawDiagonal() {
                // 通过id取得canvas元素及其绘图上下文 
                var canvas = document.getElementById('diagonal');
                var context = canvas.getContext('2d');//获取一个二维上下文
    
                // 用绝对坐标来创建一条路径 
                context.beginPath();
                context.moveTo(70, 140);
                context.lineTo(140, 70);
    
                // 将这条直线绘制到canvas上
                context.stroke();
            }
    
            window.addEventListener("load", drawDiagonal, true);
      script>
    html>

    在画直线的过程中调用了三个方法-----beginPath moveTo和lineTo方法,传入这条线的起点和终点的坐标。从以上的例子中可以看出,canvas中所有的操作都是通过上下文对象来完成的。对上下文的很多操作都不会立即反映到页面上,beginPath,moveTo,以及lineTo这些函数都不会直接修改canvas的展示结果。canvas很多用于设置样式和外观的函数都不会直接修改显示结果。只有对路径应用绘制(stroke)或填充(fill)方法,结果才会显示出来。

     

 

原文地址:http://www.cnblogs.com/cnblogs-lin/archive/2012/05/11/2496560.html

收起阅读 »

HTML5 Web存储的localStorage和sessionStorage的使用方法【图文说明】

使用HTML5 Web存储的localStoragesessionStorage方式进行Web页面数据本地存储。

页面参考如下图,能将页面上的数据进行本地存储。并能读取存储的数据显示在页面上。

localStorage(本地存储),可以长期存储数据,没有时间限制,一天,一年,两年甚至更长,数据都可以使用。

sessionStorage(会话存储),只有在浏览器被关闭之前使用,创建另一个页面时同意可以使用,关闭浏览器之后数据就会消失。

 

某个博主的测试localStorage兼容情况,如下:
Chrome4+ 开始支持localStorage

Firefox3.5+开始支持localStorage
Firefox1.5+支持globalStorage

IE8+支持localStorage
IE7兼容模式支持localStorage
IE5.5+支持userdata

Safari 4+ 支持localStorage
Opera10.5+支持localStorage

 




    
    
    


    
    






 

原文地址:http://www.cnblogs.com/taoweiji/archive/2012/12/08/2808997.html

继续阅读 »

使用HTML5 Web存储的localStoragesessionStorage方式进行Web页面数据本地存储。

页面参考如下图,能将页面上的数据进行本地存储。并能读取存储的数据显示在页面上。

localStorage(本地存储),可以长期存储数据,没有时间限制,一天,一年,两年甚至更长,数据都可以使用。

sessionStorage(会话存储),只有在浏览器被关闭之前使用,创建另一个页面时同意可以使用,关闭浏览器之后数据就会消失。

 

某个博主的测试localStorage兼容情况,如下:
Chrome4+ 开始支持localStorage

Firefox3.5+开始支持localStorage
Firefox1.5+支持globalStorage

IE8+支持localStorage
IE7兼容模式支持localStorage
IE5.5+支持userdata

Safari 4+ 支持localStorage
Opera10.5+支持localStorage

 




    
    
    


    
    






 

原文地址:http://www.cnblogs.com/taoweiji/archive/2012/12/08/2808997.html

收起阅读 »

&#x4E00;&#x4E9B;&#x6709;&#x7528;&#x7684;HTML5 pattern[&#x8F6C;]

最近在做手机页面时,遇到数字输入的键盘的问题,之前的做法只是一刀切的使用 type="tel",不过一直觉得九宫格的电话号码键盘上的英文字母太碍事了。于是想要尝试其它的实现方案,最终的结论却令人沮丧。不过也趁机详细了解了下pattern这个属性。

type="tel" 和 type="number" 的区别

这里还是先那么先交代一下最初遇到的问题。其实无论是tel还是number都不是完美的:

type="tel"

  • 优点是iOS和Android的键盘表现都差不多
  • 缺点是那些字母好多余,虽然我没有强迫症但还是感觉怪怪的啊。

type="number"

  • 优点是Android下实现的一个真正的数字键盘
  • 缺点一:iOS下不是九宫格键盘,输入不方便
  • 缺点二:旧版Android(包括微信所用的X5内核)在输入框后面会有超级鸡肋的小尾巴,好在Android 4.4.4以后给去掉了。

不过对于缺点二,我们可以用webkit私有的伪元素给fix掉:

input[type=number]::-webkit-inner-spin-button,  
    input[type=number]::-webkit-outer-spin-button { 
        -webkit-appearance: none; 
        appearance: none; 
        margin: 0; 
    }

pattern属性

pattern用于验证表单输入的内容,通常HTML5的type属性,比如email、tel、number、data类、url等,已经自带了简单的数据格式验证功能了,加上pattern后,前端部分的验证更加简单高效了。

显而易见,pattern的属性值要用正则表达式。

实例

简单的数字验证

数字的验证有两个:

type="number" pattern="\d">  
type="number" pattern="[0-9]*">  

对表单验证来说,这两个正则的作用是一样的,表现的话差异就很大:

  • iOS中,只有[0-9]*才可以调起九宫格数字键盘,\d 无效
  • Android 4.4以下(包括X5内核),两者都调起数字键盘;
  • Android 4.4.4以上,只认 type 属性,也就是说,如果上面的代码将 type="number" 改为 type="text" ,将调起全键盘而不会是九宫格数字键盘。

常用的正则表达式

pattern的用法都一样,这里不再啰嗦各种详细写法了,只是列出来一些常用的正则就好了:

  • 信用卡 [0-9]{13,16}
  • 银联卡 ^62[0-5]\d{13,16}$
  • Visa: ^4[0-9]{12}(?:[0-9]{3})?$
  • 万事达:^5[1-5][0-9]{14}$
  • QQ号码: [1-9][0-9]{4,14}
  • 手机号码:^(13[0-9]|14[5|7]|15[0|1|2|3|5|6|7|8|9]|18[0|1|2|3|5|6|7|8|9])\d{8}$
  • 身份证:^([0-9]){7,18}(x|X)?$
  • 密码:^[a-zA-Z]\w{5,17}$ 字母开头,长度在6~18之间,只能包含字母、数字和下划线
  • 强密码:^(?=.\d)(?=.[a-z])(?=.*[A-Z]).{8,10}$ 包含大小写字母和数字的组合,不能使用特殊字符,长度在8-10之间
  • 7个汉字或14个字符:^[\u4e00-\u9fa5]{1,7}$|^[\dA-Za-z_]{1,14}$

浏览器支持

很不幸,pattern的浏览器支持很惨: via Can I Use

但是如果只是如文章开头提到的改数字键盘的话,iOS和Android都是没有问题的。

原文地址:http://www.cnblogs.com/drawill/articles/5861095.html

继续阅读 »

最近在做手机页面时,遇到数字输入的键盘的问题,之前的做法只是一刀切的使用 type="tel",不过一直觉得九宫格的电话号码键盘上的英文字母太碍事了。于是想要尝试其它的实现方案,最终的结论却令人沮丧。不过也趁机详细了解了下pattern这个属性。

type="tel" 和 type="number" 的区别

这里还是先那么先交代一下最初遇到的问题。其实无论是tel还是number都不是完美的:

type="tel"

  • 优点是iOS和Android的键盘表现都差不多
  • 缺点是那些字母好多余,虽然我没有强迫症但还是感觉怪怪的啊。

type="number"

  • 优点是Android下实现的一个真正的数字键盘
  • 缺点一:iOS下不是九宫格键盘,输入不方便
  • 缺点二:旧版Android(包括微信所用的X5内核)在输入框后面会有超级鸡肋的小尾巴,好在Android 4.4.4以后给去掉了。

不过对于缺点二,我们可以用webkit私有的伪元素给fix掉:

input[type=number]::-webkit-inner-spin-button,  
    input[type=number]::-webkit-outer-spin-button { 
        -webkit-appearance: none; 
        appearance: none; 
        margin: 0; 
    }

pattern属性

pattern用于验证表单输入的内容,通常HTML5的type属性,比如email、tel、number、data类、url等,已经自带了简单的数据格式验证功能了,加上pattern后,前端部分的验证更加简单高效了。

显而易见,pattern的属性值要用正则表达式。

实例

简单的数字验证

数字的验证有两个:

type="number" pattern="\d">  
type="number" pattern="[0-9]*">  

对表单验证来说,这两个正则的作用是一样的,表现的话差异就很大:

  • iOS中,只有[0-9]*才可以调起九宫格数字键盘,\d 无效
  • Android 4.4以下(包括X5内核),两者都调起数字键盘;
  • Android 4.4.4以上,只认 type 属性,也就是说,如果上面的代码将 type="number" 改为 type="text" ,将调起全键盘而不会是九宫格数字键盘。

常用的正则表达式

pattern的用法都一样,这里不再啰嗦各种详细写法了,只是列出来一些常用的正则就好了:

  • 信用卡 [0-9]{13,16}
  • 银联卡 ^62[0-5]\d{13,16}$
  • Visa: ^4[0-9]{12}(?:[0-9]{3})?$
  • 万事达:^5[1-5][0-9]{14}$
  • QQ号码: [1-9][0-9]{4,14}
  • 手机号码:^(13[0-9]|14[5|7]|15[0|1|2|3|5|6|7|8|9]|18[0|1|2|3|5|6|7|8|9])\d{8}$
  • 身份证:^([0-9]){7,18}(x|X)?$
  • 密码:^[a-zA-Z]\w{5,17}$ 字母开头,长度在6~18之间,只能包含字母、数字和下划线
  • 强密码:^(?=.\d)(?=.[a-z])(?=.*[A-Z]).{8,10}$ 包含大小写字母和数字的组合,不能使用特殊字符,长度在8-10之间
  • 7个汉字或14个字符:^[\u4e00-\u9fa5]{1,7}$|^[\dA-Za-z_]{1,14}$

浏览器支持

很不幸,pattern的浏览器支持很惨: via Can I Use

但是如果只是如文章开头提到的改数字键盘的话,iOS和Android都是没有问题的。

原文地址:http://www.cnblogs.com/drawill/articles/5861095.html

收起阅读 »

基于html5背景图片自适应代码是一款背景不随滚动条滚动,会根据分辨率不同自动匹配对应的背景图片

实现的代码。

css代码:

.jawbone-hero .jawbone-hero-image {
    position:absolute;
    background:transparent none no-repeat scroll 50% 0;
    background-size:cover;
    top:0;
    bottom:0;
    left:0;
    right:0;
    width:100%;
    margin:0 auto;
    z-index:-1
}
.jawbone-hero {
    height:100%;
    min-height:550px
}
.jawbone-hero .jawbone-hero-image {
    position:fixed
}
#h1.jawbone-takeover-minimulti .jawbone-hero-image {
    background-image:url(../images/hero-600.jpg)
}
@media (min-width: 600px) {
    #h1.jawbone-takeover-minimulti .jawbone-hero-image {
    background-image:url(../images/hero-1280.jpg)
}
}@media (min-width: 1016px) {
    #h1.jawbone-takeover-minimulti .jawbone-hero-image {
    background-image:url(../images/hero-2000.jpg)
}

 

原文地址:http://www.cnblogs.com/sprine/p/4692111.html

继续阅读 »

实现的代码。

css代码:

.jawbone-hero .jawbone-hero-image {
    position:absolute;
    background:transparent none no-repeat scroll 50% 0;
    background-size:cover;
    top:0;
    bottom:0;
    left:0;
    right:0;
    width:100%;
    margin:0 auto;
    z-index:-1
}
.jawbone-hero {
    height:100%;
    min-height:550px
}
.jawbone-hero .jawbone-hero-image {
    position:fixed
}
#h1.jawbone-takeover-minimulti .jawbone-hero-image {
    background-image:url(../images/hero-600.jpg)
}
@media (min-width: 600px) {
    #h1.jawbone-takeover-minimulti .jawbone-hero-image {
    background-image:url(../images/hero-1280.jpg)
}
}@media (min-width: 1016px) {
    #h1.jawbone-takeover-minimulti .jawbone-hero-image {
    background-image:url(../images/hero-2000.jpg)
}

 

原文地址:http://www.cnblogs.com/sprine/p/4692111.html

收起阅读 »

用h5中的canvas 绘制八卦图

 1 doctype html>
 2 <html>
 3  <head>
 4   <meta charset="UTF-8">
 5   <title>canvas绘制八卦图title>
 6  head>
 7 
 8  <body>
 9   <canvas id="canvas" width="600" height="500">canvas>
10   <script>
11     var canvas=document.getElementById("canvas");
12     var context=canvas.getContext('2d');
13     
14     //1.先绘制一个完整的空心圆
15     context.beginPath();
16     context.arc(250,250,200,0,Math.PI*2);
17     context.stroke();
18 
19     //2.绘制半黑半白  默认为黑色
20     context.beginPath();
21     context.arc(250,250,200,Math.PI*3/2,Math.PI/2,true);
22     context.fill();
23 
24     //3.绘制一黑一白两个半圆
25     context.fillStyle="white";
26     context.beginPath();
27     context.arc(250,150,100,0,Math.PI*2);
28     context.fill();
29 
30     context.fillStyle="black";
31     context.beginPath();
32     context.arc(250,350,100,0,Math.PI*2);
33     context.fill();
34     
35     //4.绘制两个小圆
36     context.fillStyle="black";
37     context.beginPath();
38     context.arc(250,150,30,0,Math.PI*2);
39     context.fill();
40 
41     context.fillStyle="white";
42     context.beginPath();
43     context.arc(250,350,30,0,Math.PI*2);
44     context.fill();
45   script>
46  body>
47 html>

效果图:

原文地址:http://www.cnblogs.com/--silence/p/4999061.html

继续阅读 »
 1 doctype html>
 2 <html>
 3  <head>
 4   <meta charset="UTF-8">
 5   <title>canvas绘制八卦图title>
 6  head>
 7 
 8  <body>
 9   <canvas id="canvas" width="600" height="500">canvas>
10   <script>
11     var canvas=document.getElementById("canvas");
12     var context=canvas.getContext('2d');
13     
14     //1.先绘制一个完整的空心圆
15     context.beginPath();
16     context.arc(250,250,200,0,Math.PI*2);
17     context.stroke();
18 
19     //2.绘制半黑半白  默认为黑色
20     context.beginPath();
21     context.arc(250,250,200,Math.PI*3/2,Math.PI/2,true);
22     context.fill();
23 
24     //3.绘制一黑一白两个半圆
25     context.fillStyle="white";
26     context.beginPath();
27     context.arc(250,150,100,0,Math.PI*2);
28     context.fill();
29 
30     context.fillStyle="black";
31     context.beginPath();
32     context.arc(250,350,100,0,Math.PI*2);
33     context.fill();
34     
35     //4.绘制两个小圆
36     context.fillStyle="black";
37     context.beginPath();
38     context.arc(250,150,30,0,Math.PI*2);
39     context.fill();
40 
41     context.fillStyle="white";
42     context.beginPath();
43     context.arc(250,350,30,0,Math.PI*2);
44     context.fill();
45   script>
46  body>
47 html>

效果图:

原文地址:http://www.cnblogs.com/--silence/p/4999061.html

收起阅读 »

html5 canvas 前端生成缩略图

html5 canvas 前端生成缩略图

更新
2013/08/01: 解决了后面遇到的bug: 图片被压扁(IOS6); 图片被旋转; 
整个源码放在: https://github.com/kairyou/html5-make-thumb 
新方案需要后面实现的, 就是下面的旧版本里的功能(水印/是否强制拉伸以适应目标尺寸等功能).

w3ctech长沙站交流会, 里面分享的PPT: http://www.slideshare.net/99leon/html5-create-thumbnail

之前有bug的版本放在分支old里(不推荐使用), 请使用更新的方案~

2013/01/07:
11年做的公司的移动页面, 上传图片时缩略图是靠后端生成, 但是随着现在的手机越来越牛X(摄像头比数码相机还厉害~), 图片体积也越来越大.
一个几M的图, 也许我们只是用来生成一个100*100的小图, 上传到后端再生成缩略图就大大的浪费了, 而且提交表单的等待时间也非长久, 对用户体验也不好.
普通的web表单, 上传图片靠后端来生成缩略图很平常, 但有了HTML5, 针对移动Web开发可以考虑使用前端生成缩略图了.

写了个生成缩略图的jquery的插件, 主要参数:

  1. width:生成缩略图的宽; height:生成缩略图的高;
  2. fill:图片小于缩略图尺寸时,是否填充(false:缩略图宽高自动缩放到适应图片,true:缩略图尺寸不变)
  3. background:生成图片填充背景(默认#fff, 设置null时, 背景透明)
  4. type:生成图片类型('image/jpeg''image/png')
  5. size:生成缩略图方式,生成缩略图的效果主要参考了CSS3background-size属性:
  6.   contain:等比缩放并拉伸,图片全部显示;
  7.   cover:等比缩放并拉伸,图片把容器完全覆盖;
  8.   auto:图片不拉伸,居中显示.
  9. mark:水印
  10.   文字水印: mark ={padding:5, height:18, text:'test', color:'#000', font:'400 18px Arial'}
  11.   图片水印: mark ={padding:5, src:'mark.png', width:34, height:45};
  12. stretch:小图是否强制拉伸以适应缩略图的尺寸(size =auto/contain时)
  13. success:生成缩略图后 callback

大体思路如下:
首先判断是否支持fileReader(支持fileReader, canvas就不在话下了)
不支持的话: 不做任何操作, 默认的input type="file"上传, 靠后端生成缩略图.
支持的情况: input change时, 判断选择的文件是图片, 就创建一个隐藏的canvas, 并把图片画到canvas里,
因为要生成缩略图, 所以在canvas里画图的时候, 控制剪切坐标和被剪切的宽高就OK了.
另外可以加上水印, 图片水印或者文字水印加到canvas上面也是比较方便的.
最后 canvas.toDataURL 转成base64, post到后端(先把input type="file"移除, 再生成个新的input type="hidden"储存图片数据), 后端接收后直接保存为图片就OK了.
主要用到: FileReader和canvas, 一个用来读取本地图片, 一个用来生成缩略图.

做移动网页开发的同学可以考虑下.

转自:http://www.fantxi.com/blog/archives/create-thumbnail-images-html5/

原文地址:http://www.cnblogs.com/mrxia/p/3729663.html

继续阅读 »

html5 canvas 前端生成缩略图

更新
2013/08/01: 解决了后面遇到的bug: 图片被压扁(IOS6); 图片被旋转; 
整个源码放在: https://github.com/kairyou/html5-make-thumb 
新方案需要后面实现的, 就是下面的旧版本里的功能(水印/是否强制拉伸以适应目标尺寸等功能).

w3ctech长沙站交流会, 里面分享的PPT: http://www.slideshare.net/99leon/html5-create-thumbnail

之前有bug的版本放在分支old里(不推荐使用), 请使用更新的方案~

2013/01/07:
11年做的公司的移动页面, 上传图片时缩略图是靠后端生成, 但是随着现在的手机越来越牛X(摄像头比数码相机还厉害~), 图片体积也越来越大.
一个几M的图, 也许我们只是用来生成一个100*100的小图, 上传到后端再生成缩略图就大大的浪费了, 而且提交表单的等待时间也非长久, 对用户体验也不好.
普通的web表单, 上传图片靠后端来生成缩略图很平常, 但有了HTML5, 针对移动Web开发可以考虑使用前端生成缩略图了.

写了个生成缩略图的jquery的插件, 主要参数:

  1. width:生成缩略图的宽; height:生成缩略图的高;
  2. fill:图片小于缩略图尺寸时,是否填充(false:缩略图宽高自动缩放到适应图片,true:缩略图尺寸不变)
  3. background:生成图片填充背景(默认#fff, 设置null时, 背景透明)
  4. type:生成图片类型('image/jpeg''image/png')
  5. size:生成缩略图方式,生成缩略图的效果主要参考了CSS3background-size属性:
  6.   contain:等比缩放并拉伸,图片全部显示;
  7.   cover:等比缩放并拉伸,图片把容器完全覆盖;
  8.   auto:图片不拉伸,居中显示.
  9. mark:水印
  10.   文字水印: mark ={padding:5, height:18, text:'test', color:'#000', font:'400 18px Arial'}
  11.   图片水印: mark ={padding:5, src:'mark.png', width:34, height:45};
  12. stretch:小图是否强制拉伸以适应缩略图的尺寸(size =auto/contain时)
  13. success:生成缩略图后 callback

大体思路如下:
首先判断是否支持fileReader(支持fileReader, canvas就不在话下了)
不支持的话: 不做任何操作, 默认的input type="file"上传, 靠后端生成缩略图.
支持的情况: input change时, 判断选择的文件是图片, 就创建一个隐藏的canvas, 并把图片画到canvas里,
因为要生成缩略图, 所以在canvas里画图的时候, 控制剪切坐标和被剪切的宽高就OK了.
另外可以加上水印, 图片水印或者文字水印加到canvas上面也是比较方便的.
最后 canvas.toDataURL 转成base64, post到后端(先把input type="file"移除, 再生成个新的input type="hidden"储存图片数据), 后端接收后直接保存为图片就OK了.
主要用到: FileReader和canvas, 一个用来读取本地图片, 一个用来生成缩略图.

做移动网页开发的同学可以考虑下.

转自:http://www.fantxi.com/blog/archives/create-thumbnail-images-html5/

原文地址:http://www.cnblogs.com/mrxia/p/3729663.html

收起阅读 »

Android开发HTML5应用-总结

在做这个总结之前呢看过一些优秀文章和文档,在此时间过于久远原因,引用了原作者大段的摘抄而没有写明出处

原因别无其他,享受这么好社区文献,饮水思源一把。呵呵。

在Android上做HTML5应用用到了Webkit这个浏览器内核,这里具体不讨论Webkit for Android。

HTML5如何在安卓上开发HTML5应用

Android开发HTML5应用实际项目面临的问题1:

Android的HTML5应用程序概述 如何适配多分辨率的Android设备?

如何在Android中构建HTML5应用程序?

如何在Android中调试HTML5应用程序?

如何在Android中使用HTML5的本地储存?

如何在Android中使用HTML5的本地数据库?

如何在Android中使用HTML5的地理定位?

如何在Android中构建HTML5离线应用?

如何使用Canvas进行绘图?

上述问题这里提供一个ppt和参考代码

package com.example.androidwebview;

import android.os.Bundle;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;

import android.view.KeyEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;

import android.webkit.GeolocationPermissions;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebStorage;
import android.webkit.WebView;
import android.webkit.WebSettings.RenderPriority;
import android.webkit.WebViewClient;

public class MainActivity extends Activity {

    private WebView mWebView;

    private WebViewClient mWebViewClient = new WebViewClient() {
        // 处理页面导航
        @Override
        public boolean shouldOverrideUrlLoading(WebView view, String url) {
            mWebView.loadUrl(url);
            // 记得消耗掉这个事件。给不知道的朋友再解释一下,
            // Android中返回True的意思就是到此为止吧,事件就会不会冒泡传递了,我们称之为消耗掉
            return true;
        }

        @Override
        public void onPageFinished(WebView view, String url) {
            super.onPageFinished(view, url);
        }

        @Override
        public void onPageStarted(WebView view, String url, Bitmap favicon) {
            super.onPageStarted(view, url, favicon);
        }
    };

    // 浏览网页历史记录
    // goBack()和goForward()
    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if ((keyCode == KeyEvent.KEYCODE_BACK) && mWebView.canGoBack()) {
            mWebView.goBack();
            return true;
        }

        return super.onKeyDown(keyCode, event);
    }

    private WebChromeClient mChromeClient = new WebChromeClient() {

        private View myView = null;
        private CustomViewCallback myCallback = null;

        // 配置权限 (在WebChromeClinet中实现)
        @Override
        public void onGeolocationPermissionsShowPrompt(String origin,
                GeolocationPermissions.Callback callback) {
            callback.invoke(origin, true, false);
            super.onGeolocationPermissionsShowPrompt(origin, callback);
        }

        // 扩充数据库的容量(在WebChromeClinet中实现)
        @Override
        public void onExceededDatabaseQuota(String url,
                String databaseIdentifier, long currentQuota,
                long estimatedSize, long totalUsedQuota,
                WebStorage.QuotaUpdater quotaUpdater) {

            quotaUpdater.updateQuota(estimatedSize * 2);
        }

        // 扩充缓存的容量
        @Override
        public void onReachedMaxAppCacheSize(long spaceNeeded,
                long totalUsedQuota, WebStorage.QuotaUpdater quotaUpdater) {

            quotaUpdater.updateQuota(spaceNeeded * 2);
        }

        // Android 使WebView支持HTML5 Video(全屏)播放的方法
        @Override
        public void onShowCustomView(View view, CustomViewCallback callback) {
            if (myCallback != null) {
                myCallback.onCustomViewHidden();
                myCallback = null;
                return;
            }

            ViewGroup parent = (ViewGroup) mWebView.getParent();
            parent.removeView(mWebView);
            parent.addView(view);
            myView = view;
            myCallback = callback;
            mChromeClient = this;
        }

        @Override
        public void onHideCustomView() {
            if (myView != null) {
                if (myCallback != null) {
                    myCallback.onCustomViewHidden();
                    myCallback = null;
                }

                ViewGroup parent = (ViewGroup) myView.getParent();
                parent.removeView(myView);
                parent.addView(mWebView);
                myView = null;
            }
        }
    };

    @SuppressLint("SetJavaScriptEnabled")
    @SuppressWarnings("deprecation")
    private void initSettings() {

        requestWindowFeature(Window.FEATURE_NO_TITLE); //设置标题栏样式
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); //全屏
        
        setContentView(R.layout.activity_main);
        mWebView = (WebView) findViewById(R.id.webview);

        WebSettings webSettings = mWebView.getSettings();
        // 开启Javascript脚本
        webSettings.setJavaScriptEnabled(true);

        // 启用localStorage 和 essionStorage
        webSettings.setDomStorageEnabled(true);

        // 开启应用程序缓存
        webSettings.setAppCacheEnabled(true);
        String appCacheDir = this.getApplicationContext()
                .getDir("cache", Context.MODE_PRIVATE).getPath();
        webSettings.setAppCachePath(appCacheDir);
        webSettings.setCacheMode(WebSettings.LOAD_DEFAULT);
        webSettings.setAppCacheMaxSize(1024 * 1024 * 10);// 设置缓冲大小,我设的是10M
        webSettings.setAllowFileAccess(true);

        // 启用Webdatabase数据库
        webSettings.setDatabaseEnabled(true);
        String databaseDir = this.getApplicationContext()
                .getDir("database", Context.MODE_PRIVATE).getPath();
        webSettings.setDatabasePath(databaseDir);// 设置数据库路径

        // 启用地理定位
        webSettings.setGeolocationEnabled(true);
        // 设置定位的数据库路径
        webSettings.setGeolocationDatabasePath(databaseDir);

        // 开启插件(对flash的支持)
        webSettings.setPluginsEnabled(true);
        webSettings.setRenderPriority(RenderPriority.HIGH);
        webSettings.setJavaScriptCanOpenWindowsAutomatically(true);

        mWebView.setWebChromeClient(mChromeClient);
        mWebView.setWebViewClient(mWebViewClient);
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        this.initSettings();

        mWebView.loadUrl("http://192.168.1.14/Heaven");
    }
}

上述代码仅作参考,因为有些应用不用开启地理定位什么的,就可不用开启(这不是废话吗?呵呵)

Android开发HTML5应用实际项目面临的问题2:

1.支持视频流的播放,如果要求更具体点就是通过IPC直接或间接的在平板上或手机上呈现监控摄像,包括断线重连、支持分屏 、固定屏幕横竖屏、硬件加速和大小屏幕的切换(手机屏太小可以再智能电视上或大一点屏幕的PC机上显示,手机当遥控器用)。

2.目前Android上不支持HTML5部分特性 WebSockets、WebWorkers。

3.Android上js执行效率慢;比iphone、ipad慢很多,需要长时间等待。 用户体验度无线趋近于0,有木有。

4.Webview不支持多点触摸

 

支持视频流的播放

大致主流做法是:

1.有一台高吞吐量的流媒体服务器可以将视频流或视频文件转码以适应各种客户端播放视频流

2.就android而言需要做到 断线重连、支持分屏、固定屏幕横竖屏、硬件加速、大小屏幕的切换等。

 

流媒体服务器现在主流是linux做服务器,C++编写服务端

android平板针对特殊的功能也会用到JNI调用邮件、截屏、录像等 Webkit是提供了js代码与android的java代码互相调用的接口 所以这些可以通过js调用java可以通过JNI调用C++写特殊的功能代码。

 

这里就请大家参考其他文章。如果有机会会补充这块内容。

 

Android上不支持HTML5部分特性 WebSockets、WebWorkers

1.HTML5应用程序开发的硬伤呀!WebWorkers基本没辙,只能改成单线程的了 >|<

2.WebSockets 不支持 这个硬伤 找到一个很好的通讯框架socket.io可以弥补这个缺陷。

 这个有socket.io(客户端js) +  socketio-netty(socket.io服务器端JAVA实现)

当然原本socket.io 是Node.js中的一套框架轻量级支持通讯多种协议 使用方便,不得不推荐一下。

这里就请大家参考其他文章。如果有机会会补充这块内容。

 

 

Android上js执行效率慢

硬伤!精简代码,写一些轻量级的应用,期待android越做越好 也可以写一些重型火炮型的HTML5应用

像这样的

加载渲染超过一分钟 

 

Webview不支持多点触摸

硬伤! hammer.js可以模拟多点触摸 但是支持不是太好,不过能用。

 

 

当然在Android开发HTML5应用实际项目面临的问题还有很多 比如一个很简单的问题用户缩放页面禁用 Canvas重画频率过高 图形型渲染不出来,SVG的内存占用过大等问题,都要给出一个解决方案。

这里就大致总结这么多了。希望有你的好的做法介绍一下 也可以吐槽 如果关于我的,会轻微回击。

有好的做法请一定留言 请不吝赐教。您的热心的一句话,就可以帮到我很多。

原文地址:http://www.cnblogs.com/GhostHorse/archive/2013/01/30/Android_HTML5_WebView.html

继续阅读 »

在做这个总结之前呢看过一些优秀文章和文档,在此时间过于久远原因,引用了原作者大段的摘抄而没有写明出处

原因别无其他,享受这么好社区文献,饮水思源一把。呵呵。

在Android上做HTML5应用用到了Webkit这个浏览器内核,这里具体不讨论Webkit for Android。

HTML5如何在安卓上开发HTML5应用

Android开发HTML5应用实际项目面临的问题1:

Android的HTML5应用程序概述 如何适配多分辨率的Android设备?

如何在Android中构建HTML5应用程序?

如何在Android中调试HTML5应用程序?

如何在Android中使用HTML5的本地储存?

如何在Android中使用HTML5的本地数据库?

如何在Android中使用HTML5的地理定位?

如何在Android中构建HTML5离线应用?

如何使用Canvas进行绘图?

上述问题这里提供一个ppt和参考代码

package com.example.androidwebview;

import android.os.Bundle;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;

import android.view.KeyEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;

import android.webkit.GeolocationPermissions;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebStorage;
import android.webkit.WebView;
import android.webkit.WebSettings.RenderPriority;
import android.webkit.WebViewClient;

public class MainActivity extends Activity {

    private WebView mWebView;

    private WebViewClient mWebViewClient = new WebViewClient() {
        // 处理页面导航
        @Override
        public boolean shouldOverrideUrlLoading(WebView view, String url) {
            mWebView.loadUrl(url);
            // 记得消耗掉这个事件。给不知道的朋友再解释一下,
            // Android中返回True的意思就是到此为止吧,事件就会不会冒泡传递了,我们称之为消耗掉
            return true;
        }

        @Override
        public void onPageFinished(WebView view, String url) {
            super.onPageFinished(view, url);
        }

        @Override
        public void onPageStarted(WebView view, String url, Bitmap favicon) {
            super.onPageStarted(view, url, favicon);
        }
    };

    // 浏览网页历史记录
    // goBack()和goForward()
    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if ((keyCode == KeyEvent.KEYCODE_BACK) && mWebView.canGoBack()) {
            mWebView.goBack();
            return true;
        }

        return super.onKeyDown(keyCode, event);
    }

    private WebChromeClient mChromeClient = new WebChromeClient() {

        private View myView = null;
        private CustomViewCallback myCallback = null;

        // 配置权限 (在WebChromeClinet中实现)
        @Override
        public void onGeolocationPermissionsShowPrompt(String origin,
                GeolocationPermissions.Callback callback) {
            callback.invoke(origin, true, false);
            super.onGeolocationPermissionsShowPrompt(origin, callback);
        }

        // 扩充数据库的容量(在WebChromeClinet中实现)
        @Override
        public void onExceededDatabaseQuota(String url,
                String databaseIdentifier, long currentQuota,
                long estimatedSize, long totalUsedQuota,
                WebStorage.QuotaUpdater quotaUpdater) {

            quotaUpdater.updateQuota(estimatedSize * 2);
        }

        // 扩充缓存的容量
        @Override
        public void onReachedMaxAppCacheSize(long spaceNeeded,
                long totalUsedQuota, WebStorage.QuotaUpdater quotaUpdater) {

            quotaUpdater.updateQuota(spaceNeeded * 2);
        }

        // Android 使WebView支持HTML5 Video(全屏)播放的方法
        @Override
        public void onShowCustomView(View view, CustomViewCallback callback) {
            if (myCallback != null) {
                myCallback.onCustomViewHidden();
                myCallback = null;
                return;
            }

            ViewGroup parent = (ViewGroup) mWebView.getParent();
            parent.removeView(mWebView);
            parent.addView(view);
            myView = view;
            myCallback = callback;
            mChromeClient = this;
        }

        @Override
        public void onHideCustomView() {
            if (myView != null) {
                if (myCallback != null) {
                    myCallback.onCustomViewHidden();
                    myCallback = null;
                }

                ViewGroup parent = (ViewGroup) myView.getParent();
                parent.removeView(myView);
                parent.addView(mWebView);
                myView = null;
            }
        }
    };

    @SuppressLint("SetJavaScriptEnabled")
    @SuppressWarnings("deprecation")
    private void initSettings() {

        requestWindowFeature(Window.FEATURE_NO_TITLE); //设置标题栏样式
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); //全屏
        
        setContentView(R.layout.activity_main);
        mWebView = (WebView) findViewById(R.id.webview);

        WebSettings webSettings = mWebView.getSettings();
        // 开启Javascript脚本
        webSettings.setJavaScriptEnabled(true);

        // 启用localStorage 和 essionStorage
        webSettings.setDomStorageEnabled(true);

        // 开启应用程序缓存
        webSettings.setAppCacheEnabled(true);
        String appCacheDir = this.getApplicationContext()
                .getDir("cache", Context.MODE_PRIVATE).getPath();
        webSettings.setAppCachePath(appCacheDir);
        webSettings.setCacheMode(WebSettings.LOAD_DEFAULT);
        webSettings.setAppCacheMaxSize(1024 * 1024 * 10);// 设置缓冲大小,我设的是10M
        webSettings.setAllowFileAccess(true);

        // 启用Webdatabase数据库
        webSettings.setDatabaseEnabled(true);
        String databaseDir = this.getApplicationContext()
                .getDir("database", Context.MODE_PRIVATE).getPath();
        webSettings.setDatabasePath(databaseDir);// 设置数据库路径

        // 启用地理定位
        webSettings.setGeolocationEnabled(true);
        // 设置定位的数据库路径
        webSettings.setGeolocationDatabasePath(databaseDir);

        // 开启插件(对flash的支持)
        webSettings.setPluginsEnabled(true);
        webSettings.setRenderPriority(RenderPriority.HIGH);
        webSettings.setJavaScriptCanOpenWindowsAutomatically(true);

        mWebView.setWebChromeClient(mChromeClient);
        mWebView.setWebViewClient(mWebViewClient);
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        this.initSettings();

        mWebView.loadUrl("http://192.168.1.14/Heaven");
    }
}

上述代码仅作参考,因为有些应用不用开启地理定位什么的,就可不用开启(这不是废话吗?呵呵)

Android开发HTML5应用实际项目面临的问题2:

1.支持视频流的播放,如果要求更具体点就是通过IPC直接或间接的在平板上或手机上呈现监控摄像,包括断线重连、支持分屏 、固定屏幕横竖屏、硬件加速和大小屏幕的切换(手机屏太小可以再智能电视上或大一点屏幕的PC机上显示,手机当遥控器用)。

2.目前Android上不支持HTML5部分特性 WebSockets、WebWorkers。

3.Android上js执行效率慢;比iphone、ipad慢很多,需要长时间等待。 用户体验度无线趋近于0,有木有。

4.Webview不支持多点触摸

 

支持视频流的播放

大致主流做法是:

1.有一台高吞吐量的流媒体服务器可以将视频流或视频文件转码以适应各种客户端播放视频流

2.就android而言需要做到 断线重连、支持分屏、固定屏幕横竖屏、硬件加速、大小屏幕的切换等。

 

流媒体服务器现在主流是linux做服务器,C++编写服务端

android平板针对特殊的功能也会用到JNI调用邮件、截屏、录像等 Webkit是提供了js代码与android的java代码互相调用的接口 所以这些可以通过js调用java可以通过JNI调用C++写特殊的功能代码。

 

这里就请大家参考其他文章。如果有机会会补充这块内容。

 

Android上不支持HTML5部分特性 WebSockets、WebWorkers

1.HTML5应用程序开发的硬伤呀!WebWorkers基本没辙,只能改成单线程的了 >|<

2.WebSockets 不支持 这个硬伤 找到一个很好的通讯框架socket.io可以弥补这个缺陷。

 这个有socket.io(客户端js) +  socketio-netty(socket.io服务器端JAVA实现)

当然原本socket.io 是Node.js中的一套框架轻量级支持通讯多种协议 使用方便,不得不推荐一下。

这里就请大家参考其他文章。如果有机会会补充这块内容。

 

 

Android上js执行效率慢

硬伤!精简代码,写一些轻量级的应用,期待android越做越好 也可以写一些重型火炮型的HTML5应用

像这样的

加载渲染超过一分钟 

 

Webview不支持多点触摸

硬伤! hammer.js可以模拟多点触摸 但是支持不是太好,不过能用。

 

 

当然在Android开发HTML5应用实际项目面临的问题还有很多 比如一个很简单的问题用户缩放页面禁用 Canvas重画频率过高 图形型渲染不出来,SVG的内存占用过大等问题,都要给出一个解决方案。

这里就大致总结这么多了。希望有你的好的做法介绍一下 也可以吐槽 如果关于我的,会轻微回击。

有好的做法请一定留言 请不吝赐教。您的热心的一句话,就可以帮到我很多。

原文地址:http://www.cnblogs.com/GhostHorse/archive/2013/01/30/Android_HTML5_WebView.html

收起阅读 »

html5 Canvas画图6:曲线之arcTo

上一篇文章讲了canvas的arc方法,这一篇讲和他有关的arcTo方法。

arc与arcTo,从名字都能看出来相似。arcTo也是画曲线的方法,而且他画出的曲线也是正圆的一段弧线。但他的参数和arc简直是不共戴天~

ctx.arcTo(x1,y1,x2,y2,radius);

arcTo的参数中包括两个点,而且这两个点中并没有表示圆心的点,仅仅最后的参数是圆的半径,表示arcTo和圆有那么点关系。

网上关于arcTo的文章很少,好不容易找到一篇还是外国的;而且canvas画图木有直观工具,只能靠猜,arcTo害我猜了半天。。

为了直观的描述,我采取了一种辅助办法:arcTo画到哪里,我就用lineTo也画到相应的点,以查看他们的关系。就是画辅助线。

var x0=100,
y0=400,
x1 = 500,
y1 = 400,
x2 = 450,
y2 = 450;
ctx.beginPath();
ctx.moveTo(x0,y0);
ctx.strokeStyle = "#f00";
ctx.lineWidth = 2;
ctx.arcTo(x1,y1,x2,y2,20);
ctx.stroke();
ctx.beginPath();
ctx.strokeStyle = "rgba(0,0,0,0.5)";
ctx.lineWidth = 1;
ctx.moveTo(x0,y0);
ctx.lineTo(x1,y1);
ctx.fillText('x1,y1',x1+10,y1+10)
ctx.lineTo(x2,y2);
ctx.fillText('x2,y2',x2+10,y2)
ctx.stroke();

看起来代码有点多,其实很简单。我用了几个变量来保存坐标值,其余的都是canvas的操作了。

变量说明:x0,y0是起点坐标,x1,y1是第一个点坐标,x2,y2就是第二个点坐标。其中lineTo画的直线是半透明的1px黑线,arcTo画的线条是2px的红线

刷新页面,即可看到下图。

canvas arcTo

不得不说这条红线很像一个钩子。
于是arcTo的规律就找到了,他其实是通过起点,第1点,第2点的两条直线,组成了一个夹角,而这两条线,也是参数圆的切线

其中圆的半径决定了圆会在什么位置与线条发生切边。就像一个球往一个死角里面滚,球越小就滚得越进去,越靠近死角;球大则反之。

这是一个很严肃的学术问题,大家可不要YY。

让我们把球球变大吧!

ctx.arcTo(x1,y1,x2,y2,50); //半径改成50

canvas arcTo

如图,你可以看到圆弧变得很大,甚至都不和直线相切了。

当然,实际上他们还是相切的,因为切线是无限延长的。

我们继续探索,把圆继续变大,把起点与第1点的距离缩短。

var x0=400; //起点x坐标从100变400
...
ctx.arcTo(x1,y1,x2,y2,100); //圆的半径变大到100

然后你就会看到这么个奇特的图形。

canvas arcTo

本来是个钩子,现在被硬生生的掰弯了,还掰到反方向了!有点像酒瓶架了。

不过,大家注意看,这个圆依然是和两条线相切的!只是现在两条线的长度都满足不了这个圆了!他已经把两条线都无线延长了!

这个钩子柄什么时候会发生反转呢?如果你几何学的好,你可以试着理解一下点与圆的切线方程。。

arcTo方法中有个很重要的点,这个重要的点就是代码中的(x1,y1),只要他到圆的切点的距离,超过了他到起点(x0,y0)的距离,就会发生反转。

从图中我们可以看到,(x2,y2)这个点的坐标可以无限变化,只要他始终是切线上的一个点,那么在圆的半径不变的情况下,arcTo画出的图形不会有任何变化。这点需要特别注意。

让我用我拿不上台面的几何知识来验证下这个命题吧。为了方便计算,我先把两条线的夹角改成90度。

var x0=100,
y0=400,
x1 = 500,
y1 = 400,
x2 = 500,
y2 = 450;

更改后就是90度张开了哟!我们保持球的半径不变。刷新后:

canvas arcTo
我们把y2变大,也就是延长了一条切线,把他变成550,刷新后:

canvas arcTo
切线是延长了,但arcTo画出的红线没有任何变化。

原文

原文地址:http://www.cnblogs.com/lixlib/archive/2012/12/17/2821338.html

继续阅读 »

上一篇文章讲了canvas的arc方法,这一篇讲和他有关的arcTo方法。

arc与arcTo,从名字都能看出来相似。arcTo也是画曲线的方法,而且他画出的曲线也是正圆的一段弧线。但他的参数和arc简直是不共戴天~

ctx.arcTo(x1,y1,x2,y2,radius);

arcTo的参数中包括两个点,而且这两个点中并没有表示圆心的点,仅仅最后的参数是圆的半径,表示arcTo和圆有那么点关系。

网上关于arcTo的文章很少,好不容易找到一篇还是外国的;而且canvas画图木有直观工具,只能靠猜,arcTo害我猜了半天。。

为了直观的描述,我采取了一种辅助办法:arcTo画到哪里,我就用lineTo也画到相应的点,以查看他们的关系。就是画辅助线。

var x0=100,
y0=400,
x1 = 500,
y1 = 400,
x2 = 450,
y2 = 450;
ctx.beginPath();
ctx.moveTo(x0,y0);
ctx.strokeStyle = "#f00";
ctx.lineWidth = 2;
ctx.arcTo(x1,y1,x2,y2,20);
ctx.stroke();
ctx.beginPath();
ctx.strokeStyle = "rgba(0,0,0,0.5)";
ctx.lineWidth = 1;
ctx.moveTo(x0,y0);
ctx.lineTo(x1,y1);
ctx.fillText('x1,y1',x1+10,y1+10)
ctx.lineTo(x2,y2);
ctx.fillText('x2,y2',x2+10,y2)
ctx.stroke();

看起来代码有点多,其实很简单。我用了几个变量来保存坐标值,其余的都是canvas的操作了。

变量说明:x0,y0是起点坐标,x1,y1是第一个点坐标,x2,y2就是第二个点坐标。其中lineTo画的直线是半透明的1px黑线,arcTo画的线条是2px的红线

刷新页面,即可看到下图。

canvas arcTo

不得不说这条红线很像一个钩子。
于是arcTo的规律就找到了,他其实是通过起点,第1点,第2点的两条直线,组成了一个夹角,而这两条线,也是参数圆的切线

其中圆的半径决定了圆会在什么位置与线条发生切边。就像一个球往一个死角里面滚,球越小就滚得越进去,越靠近死角;球大则反之。

这是一个很严肃的学术问题,大家可不要YY。

让我们把球球变大吧!

ctx.arcTo(x1,y1,x2,y2,50); //半径改成50

canvas arcTo

如图,你可以看到圆弧变得很大,甚至都不和直线相切了。

当然,实际上他们还是相切的,因为切线是无限延长的。

我们继续探索,把圆继续变大,把起点与第1点的距离缩短。

var x0=400; //起点x坐标从100变400
...
ctx.arcTo(x1,y1,x2,y2,100); //圆的半径变大到100

然后你就会看到这么个奇特的图形。

canvas arcTo

本来是个钩子,现在被硬生生的掰弯了,还掰到反方向了!有点像酒瓶架了。

不过,大家注意看,这个圆依然是和两条线相切的!只是现在两条线的长度都满足不了这个圆了!他已经把两条线都无线延长了!

这个钩子柄什么时候会发生反转呢?如果你几何学的好,你可以试着理解一下点与圆的切线方程。。

arcTo方法中有个很重要的点,这个重要的点就是代码中的(x1,y1),只要他到圆的切点的距离,超过了他到起点(x0,y0)的距离,就会发生反转。

从图中我们可以看到,(x2,y2)这个点的坐标可以无限变化,只要他始终是切线上的一个点,那么在圆的半径不变的情况下,arcTo画出的图形不会有任何变化。这点需要特别注意。

让我用我拿不上台面的几何知识来验证下这个命题吧。为了方便计算,我先把两条线的夹角改成90度。

var x0=100,
y0=400,
x1 = 500,
y1 = 400,
x2 = 500,
y2 = 450;

更改后就是90度张开了哟!我们保持球的半径不变。刷新后:

canvas arcTo
我们把y2变大,也就是延长了一条切线,把他变成550,刷新后:

canvas arcTo
切线是延长了,但arcTo画出的红线没有任何变化。

原文

原文地址:http://www.cnblogs.com/lixlib/archive/2012/12/17/2821338.html

收起阅读 »

HTML5&#x4F60;&#x5FC5;&#x987B;&#x77E5;&#x9053;&#x7684;28&#x4E2A;&#x65B0;&#x7279;&#x6027;

1. 新的Doctype
尽管使用,即使浏览器不懂这句话也会按照标准模式去渲染
2. Figure元素

来语义化地表示带标题的图片

”About

This is an image of something interesting.




3. 重新定义的
已经被重新定义了,现在被用来表示小的排版,如网站底部的版权声明
4. 去掉link和script标签里面的type属性
5. 加/不加 括号
HTML5没有严格的要求属性必须加引号,闭合不闭合,但是建议加上引号和闭合标签
6. 让你的内容可编辑,只需要加一个contenteditable属性
7. Email Inputs
如果我们给Input的type设置为email,浏览器就会验证这个输入是否是email类型,当然不能只依赖前端的校验,后端也得有相应的校验
8. Placeholders
这个input属性的意义就是不必通过javascript来做placeholder的效果了
9. Local Storage
使用Local Storage可以永久存储大的数据片段在客户端(除非主动删除),目前大部分浏览器已经支持,在使用之前可以检测一下window.localStorage是否存在
10. 语义化的header和footer
11. 更多的HTML5表单特性
12. IE和HTML5
默认的,HTML5新元素被以inline的方式渲染,不过可以通过下面这种方式让
其以block方式渲染
header, footer, article, section, nav, menu, hgroup {
display: block;
}
不幸的是IE会忽略这些样式,可以像下面这样fix:
document.createElement(”article”);
document.createElement(”footer”);
document.createElement(”header”);
document.createElement(”hgroup”);
document.createElement(”nav”);
document.createElement(”menu”);
13. hgroup
一般在header里面用来将一组标题组合在一起,如


Recall Fan Page


Only for people who want the memory of a lifetime.




14. Required属性
required属性定义了一个input是否是必须的,你可以像下面这样声明

或者

15. Autofocus属性
正如它的词义,就是聚焦到输入框里面

16. Audio支持
HTML5提供了

1. 新的Doctype
尽管使用,即使浏览器不懂这句话也会按照标准模式去渲染
2. Figure元素

来语义化地表示带标题的图片

”About

This is an image of something interesting.




3. 重新定义的
已经被重新定义了,现在被用来表示小的排版,如网站底部的版权声明
4. 去掉link和script标签里面的type属性
5. 加/不加 括号
HTML5没有严格的要求属性必须加引号,闭合不闭合,但是建议加上引号和闭合标签
6. 让你的内容可编辑,只需要加一个contenteditable属性
7. Email Inputs
如果我们给Input的type设置为email,浏览器就会验证这个输入是否是email类型,当然不能只依赖前端的校验,后端也得有相应的校验
8. Placeholders
这个input属性的意义就是不必通过javascript来做placeholder的效果了
9. Local Storage
使用Local Storage可以永久存储大的数据片段在客户端(除非主动删除),目前大部分浏览器已经支持,在使用之前可以检测一下window.localStorage是否存在
10. 语义化的header和footer
11. 更多的HTML5表单特性
12. IE和HTML5
默认的,HTML5新元素被以inline的方式渲染,不过可以通过下面这种方式让
其以block方式渲染
header, footer, article, section, nav, menu, hgroup {
display: block;
}
不幸的是IE会忽略这些样式,可以像下面这样fix:
document.createElement(”article”);
document.createElement(”footer”);
document.createElement(”header”);
document.createElement(”hgroup”);
document.createElement(”nav”);
document.createElement(”menu”);
13. hgroup
一般在header里面用来将一组标题组合在一起,如


Recall Fan Page


Only for people who want the memory of a lifetime.




14. Required属性
required属性定义了一个input是否是必须的,你可以像下面这样声明

或者

15. Autofocus属性
正如它的词义,就是聚焦到输入框里面

16. Audio支持
HTML5提供了

HTML5学习笔记简明版(5):input的type超级类型

HTML5为input的type类型增加了多种枚举值,用来表达不同的意思,同事具有验证功能,如果格式不对,浏览器将原始提供错误提示,堪称超级牛X啊,具体如下:

 

Keyword

Data type

hidden

任意字符

text

单行文本

search

单行文本

tel

单行文本

url

绝对地址

email

一个或多个email地址

password

单行文本

datetime

带有时区的时间

date

无时区的年月日时间

month

无时区的年月

week

无时区的周数

time

无时区的时间(小时,分钟,秒,毫秒)

datetime-local

无时区的日期与时间

number

数字值

range

范围:

color

8-bit表示的颜色

checkbox

checkbox

radio

radio

file

文件

submit

提交按钮

image

图片按钮

reset

n/a

button

n/a

 参考资料:http://www.mhtml5.com/resources/html5%E6%95%99%E7%A8%8B%EF%BC%88%E5%85%AD%EF%BC%89-html5-input%E7%B1%BB%E5%9E%8B

 

学习至此,大叔发现mhtml5网站上已经有很多现成的资料了,所以如下的一些新元素请大家自行参考该网站的资料学习,大叔将着重继续学习HTML5在现有元素上的更新改变。

  1. figure元素
  2. figcaption元素
  3. track元素
  4. embed元素
  5. mark元素
  6. progress元素
  7. time元素
  8. ruby, rt和rp元素
  9. bdi元素
  10. wbr元素
  11. canvas元素
  12. command元素
  13. details元素

原文地址:http://www.cnblogs.com/TomXu/archive/2011/12/12/2269079.html

继续阅读 »

HTML5为input的type类型增加了多种枚举值,用来表达不同的意思,同事具有验证功能,如果格式不对,浏览器将原始提供错误提示,堪称超级牛X啊,具体如下:

 

Keyword

Data type

hidden

任意字符

text

单行文本

search

单行文本

tel

单行文本

url

绝对地址

email

一个或多个email地址

password

单行文本

datetime

带有时区的时间

date

无时区的年月日时间

month

无时区的年月

week

无时区的周数

time

无时区的时间(小时,分钟,秒,毫秒)

datetime-local

无时区的日期与时间

number

数字值

range

范围:

color

8-bit表示的颜色

checkbox

checkbox

radio

radio

file

文件

submit

提交按钮

image

图片按钮

reset

n/a

button

n/a

 参考资料:http://www.mhtml5.com/resources/html5%E6%95%99%E7%A8%8B%EF%BC%88%E5%85%AD%EF%BC%89-html5-input%E7%B1%BB%E5%9E%8B

 

学习至此,大叔发现mhtml5网站上已经有很多现成的资料了,所以如下的一些新元素请大家自行参考该网站的资料学习,大叔将着重继续学习HTML5在现有元素上的更新改变。

  1. figure元素
  2. figcaption元素
  3. track元素
  4. embed元素
  5. mark元素
  6. progress元素
  7. time元素
  8. ruby, rt和rp元素
  9. bdi元素
  10. wbr元素
  11. canvas元素
  12. command元素
  13. details元素

原文地址:http://www.cnblogs.com/TomXu/archive/2011/12/12/2269079.html

收起阅读 »

canvas API ,通俗的canvas基础知识(五)

前几期讲的都是路径图形的绘图,这节我们要讲的是如何在画布上操作图片,因为图形画不了漂亮妹子(画图高手忽略不计),想画美女怎么办?跟我来:

想要在画布中插入一张图片,我们需要的方法是这位大侠:

drawImage()  在画布上绘制图像,画布或视频

这位大侠可谓是武功高强啊,其绝学之多,内力之深,堪称高手中的高手,那我们来看看它都有些什么绝学:

秘籍一:

drawImage(img,x,y) 在画布上定位一张图片

参数:img 表示引入的图片对象,x,y表示引入的坐标

ps:img在这里表示的是图片的对象而不是图片的路径,说明不能直接来引用图片,而是需要操作DOM的方式来引用

上面的提示说了图片的特殊性,那我们该如何来获取图片呢?我们先来一个最简单的:

<canvas width="500" height="400" id="canvas">
        <span>亲,您的浏览器不支持canvas,换个浏览器试试吧!span>
canvas>
<img src="2.jpg" alt="" id="img">

 

我们在页面上放一张图(当年的奶茶妹,当年的哦),然后获取这张图,再放到画布上

var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var oImg = document.getElementById("img");
ctx.drawImage(oImg,10,10);

看,在画布外的奶茶妹就到我们的画布上去了,可惜的是,现在的奶茶妹已经不是当前的奶茶妹了,有同学会说,我只想让我的奶茶妹在我的画布上(怎么是我的奶茶妹),不想让她在别的地方被看见,我要怎么做呢?机灵的同学一定想得到,我把外面的图片隐藏起来不就行了吗?直接隐藏行不行呢?

<img src="2.jpg" alt="" id="img" style="display:none;">

右边的奶茶妹不见了,只有我的画布上有可以的奶茶妹,恩恩,这是我想要的,说明这样有这个图片在页面上,能够获取到这个DOM元素即可,至于图片到底显不显示,不重要,那图片的隐藏方式就很多了,自身隐藏,放到一个div中div隐藏,放到canvas标签中(因为支持canvas的浏览器里面的东西是不显示的)等等,也可以用纯js的方式来添加图片:

var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var aImg = new Image();
aImg.src = '2.jpg';
ctx.onload = function(){
    ctx.drawImage(aImg,10,10,400,300);
}

 

秘籍二:

drawImage(img,x,y,w,h)  在画布上定位图片,并规定图片的宽高

参数:img 表示引入的图片对象,x,y表示引入的坐标 ,w,h表示规定图片的大小

有同学会说,奶茶妹是好,但是我的画布太小,奶茶妹太大(哪里大了),图片太大,都基本上把我的画布都占满了,如果我在画布上画别的图形,岂不是玷污了奶茶妹了,能把她变小吗?哈哈,drawImage具备孙悟空的变换本领,能大能小,不信,看这里:

var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var oImg = document.getElementById("img");
ctx.drawImage(oImg,10,10,200,150);

看,上面的奶茶妹一下子就变小了,哎呀,太小了,看不清楚,而且我只想看奶茶妹,不想看到别的糟同学,可以吗?当然可以

秘籍三

drawImage(img,sX,sY,sWidth,sHeight,x,y,width,height)  剪切画布,并在画布上定位被剪切的部分

参数:img 表示引入的图片对象,sX,sY表示剪切的其实坐标,sWidth,sHeight表示剪切的宽度和高度,x,y表示在画布上放置图片的坐标 ,width,height表示需要使用的图片的宽高

上面的参数虽多,但是还是很好理解的,我们来看看如何将奶茶妹剪切下来:

var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var oImg = document.getElementById("img");
ctx.drawImage(oImg,150,0,150,300,10,10,400,300);

 

纳里,奶茶妹怎么变成了胖子?再看一下参数,发现此时最后面的width和height已和前面的w,h代表的意思不一样了,现在的表示裁剪下来的图片需要显示多大,如果比裁剪的宽高大,则会被拉伸,比裁剪的宽高小,则会被缩小,恩,我们调成跟裁剪尺寸一样看一下:

var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var oImg = document.getElementById("img");
ctx.drawImage(oImg,150,0,150,300,10,10,150,300);

对对,就是这样的,后面的x,y表示裁剪的图片显示的位置,我们调到中间看看

ctx.drawImage(oImg,150,0,150,300,150,10,150,300);

所以在使用裁剪功能的时候,要特别注意,图片的坐标和宽高和原来的意思有区别了

秘籍四

drawImage(video,x,y,w,h)  在画布上定位视频,并规定视频的宽高

参数:video表示引入是视频对象 ,x,y表示视频引入的坐标 ,w,h表示规定视频的大小

其实这里跟引入图片是一样的,只不过它是可以引入视频的,但是这里的引入只是视频的某一帧,所以,当我们直接引入时,是没有什么反应的:

<canvas width="500" height="400" id="canvas">
        <span>亲,您的浏览器不支持canvas,换个浏览器试试吧!span>
    canvas>
    <video id="video1" controls width="270">
      <source src="http://www.w3school.com.cn/example/html5/mov_bbb.mp4" type='video/mp4'>
      <source src="http://www.w3school.com.cn/example/html5/mov_bbb.ogg" type='video/ogg'>
      <source src="http://www.w3school.com.cn/example/html5/mov_bbb.webm" type='video/webm'>
    video>
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var oVideo = document.getElementById("video1");
ctx.drawImage(oVideo,10,10,270,135);

当视频设置为autoplay时:

可以看到,右侧视频在播放,左侧没有什么反应,那怎么来播放视频呢?我们可以加一个定时器,然后每隔20秒执行一次绘画,这样一帧一帧的执行,连续起来就是一个视频了,其实视频的原理也是如此:

var canvas = document.getElementById("canvas");
        var ctx = canvas.getContext("2d");
        var oImg = document.getElementById("img");
        var oVideo = document.getElementById("video1");
        var timer = setInterval(function(){
            ctx.drawImage(oVideo,10,10,270,135);
        },20)

不想让画布外的视频显示的方法跟图片是一样的,这里我就不细说了

 

除了drawImage具有裁剪功能外,还有一个方法可以裁剪——clip(),不同的是drawImage是裁剪图片,而clip只能裁剪图形,我们具体来看一下clip吧:

clip() 从原始画布中剪切任意形状和尺寸

ps:一旦剪切了某个区域,则所有之后的绘图都会被限制在被剪切的区域内(不能访问画布上的其他区域)。您也可以在使用 clip() 方法前通过使用 save() 方法对当前画布区域进行保存,并在以后的任意时间对其进行恢复(通过 restore() 方法)。

提示这里很重要,一定要看清楚,就好比是一张很大的油画布,现在我们用一个木框架子框一部分,然后就只能在这个框里画画了,框外面的就不能来画,恩,就是这个意思,当我们用restore()方法恢复画布是时候,就好比是把木框架子取掉了,这样就可以在别的地方画了,当然画好的这部分就不要动了

举个栗子:

不用clip裁剪:

ctx.arc(200, 200, 80, (Math.PI/180)*0, (Math.PI/180)*360, false);
ctx.fill();
ctx.beginPath();
ctx.fillStyle = 'green';
ctx.arc(150, 150, 100, (Math.PI/180)*0, (Math.PI/180)*360, false);
ctx.fill();

使用clip裁剪:

ctx.arc(200, 200, 80, (Math.PI/180)*0, (Math.PI/180)*360, false);
ctx.clip();
ctx.fill();
ctx.beginPath();
ctx.fillStyle = 'green';
ctx.arc(150, 150, 100, (Math.PI/180)*0, (Math.PI/180)*360, false);
ctx.fill();

可以比较看出,后面画的圆只显示在裁剪的圆的范围中,其他的都不见了,再看一个例子:

ctx.fillRect(50,50,200,100);
ctx.clip();
ctx.beginPath();
ctx.fillStyle = 'green';
ctx.fillRect(100,100,200,100);

 

我们将圆改成实心的矩形,且是用的fillRect,而不是用fill,rect,结果是:

只显示第一个矩形,第二个矩形貌似不见了,而我们分开写:

//不用clip裁剪
ctx.rect(50,50,200,100);
ctx.fill();
ctx.beginPath();
ctx.fillStyle = 'green';
ctx.fillRect(100,100,200,100);
//使用clip裁剪
ctx.rect(50,50,200,100);
ctx.fill();
ctx.clip();
ctx.beginPath();
ctx.fillStyle = 'green';
ctx.fillRect(100,100,200,100);
//第一个矩形不填充,只画路径
ctx.rect(50,50,200,100);
ctx.clip();
ctx.beginPath();
ctx.fillStyle = 'green';
ctx.fillRect(100,100,200,100);
//将clip放在第二个矩形
ctx.rect(50,50,200,100);
ctx.fill();
ctx.beginPath();
ctx.fillStyle = 'green';
ctx.rect(100,100,200,100);
ctx.clip();
ctx.fill();

      

上面的4张图分别代码上面的4段代码的效果,从这4组对比我们可以看出:

第一:裁剪的路径必须在被裁剪图形的前面申明,如果在后面申明,则会没有效果或只有第一个图形显示;

第二:如果前面的裁剪区域要是没有填充的话,显示的部分就要2图形相交的部分,但是绘图区域还是裁剪部分的区域

 

下面要讲的是像素操作,相对来说比较复杂,需要大家的强大大脑来脑补和理解,何为像素操作?我们说任何在屏幕上显示的图形,图片,画面等等都是由像素构成的,最好理解的就是户外大屏幕的画面了,因为户外大屏幕分辨率比较小,相比之下像素的颗粒就比较大,可以清晰的看到画面是又密密麻麻的像素来显示的,当户外大屏幕的屏幕有部分花了的话,会看到呈现的画面就会在花掉的部分显示成别的颜色,很明显,对于我们的电脑显示器也是一个原理!

那么像素是通过什么来获取的呢?我们来一一介绍:

getImageData(x,y,w,h)  拷贝画布指定矩形的像素数据 

参数:x,y表示开始复制的左上角的坐标  w,h表示将要复制的区域大小

参数很好理解,就是在什么地方复制多大一个地方,而且它返回一个ImageData对象,ImageData对象里面包含了几个参数:

data:数组集合  width :对象的宽度  height:对象的高度

后面2个好理解,这个data集合到底是什么呢?我们来举个栗子:

ctx.fillRect(0,0,100,100);
//获取矩形框的像素
var oImg = ctx.getImageData(0,0,100,100);
console.log(oImg);
console.log(oImg.data)
console.log(oImg.data.length)

      

我们画了一个100*100的实现矩形,然后获取它的像素,然后分别查看了他们代表的意思,可以看到一个很有意思的东西,就是100*100的矩形的像素点应该是10000个像素,为什么它的长度是40000,这个我们可以在data数组中可以看到端倪,一个像素点是由rgba构成的:

r : 0-255  黑-白  

g : 0-255 黑-白  

b : 0-255  黑-白  

a : 0-255 透明-不透明

也就是说,一个像素是用这4个值组成的,那么10000个像素的长度自然就是40000了,而且对应的值在console中也能看到,好了,理解了这一点,那么就里像素操作不远了!

除了我们在已知的地方去获取像素外,我们能不能自己来创造像素区域呢?答案是肯定的:

createImageData(w,h)  表示创建一个规定尺寸的ImageData对象

createImageData(ImageData)  表示创建与指定的另一个 ImageData 对象尺寸相同的新 ImageData 对象(不会复制图像数据)

我们也来写一个例子:

var oImg = ctx.createImageData(100,100);
console.log(oImg);
console.log(oImg.data)
console.log(oImg.data.length)

恩,跟前面的是一样的,创建了一个ImageData对象,当然画布是没有任何的效果的,因为我们只是创建了一个对象,那么我们怎么将我们创建的对象放到画布上呢?那就要用到这个方法:

putImageData(imageData,x,y,dirtyX,dirtyY,dirtyWidth,dirtyHeight)  方法将图像数据(从指定的 ImageData 对象)放回画布上

参数: 

imageData指创建或获取的imageData对象 

x,y表示imageData对象的左上角坐标  

dirtyX,dirtyY 表示在画布上放置图像的坐标,以像素计,可选

dirtyWidth,dirtyHeight 表示在画布上放置的图形大小,可选

我们也举2个例子:

ctx.fillRect(0,0,100,100);
//获取矩形框的像素
var oImg = ctx.getImageData(0,0,100,100);
ctx.putImageData(oImg,100,100);

 

ctx.fillRect(0,0,100,100);
//获取矩形框的像素
var oImg = ctx.getImageData(0,0,100,100);
ctx.putImageData(oImg,100,100);
ctx.putImageData(oImg,100,0,10,10,50,50);

看,这么一对比,就知道这些参数是什么意思了,其中第二个我还得解释一下,如图小矩形,x,y依然是表示大的ImageData对象的起始坐标,dirtyX,dirtyY,dirtyWidth,dirtyHeight表示是相对于现在的x,y的起始坐标再来定义位置和大小,这么解释应该就明白了!

这就是操作像素的方法,看着很简单,也挺好理解,但是真正用起来,还是蛮费脑子的,我们先来看第一个小实例,改变像素的颜色:

实例效果,改变100*100的黑色矩形框中的第10行第10列的颜色,颜色为红色,先画个图分析一下:

从上面的console中也可以看出,像素点是从0开始的,如果上图就是矩形的像素点的分布(画的有点烂,将就看一下),第10行,也就是第11行,第10列也就是第11列,那么前十列的像素就是矩形的宽度*10,剩下的就是11个像素,二者相加就是所有的像素,然后每个像素用4个值表示,就是总和乘以4,好具体我们看代码:

ctx.fillRect(0,0,100,100);
//获取矩形框的像素
var oImg = ctx.getImageData(0,0,100,100);
setXY(oImg,10,10,[255,0,0,255]);
//设置目标像素点的颜色
function setXY(obj,x,y,color){
    var w = obj.width;
    var h = obj.height;
    obj.data[4*(w*y+x)] = color[0];
    obj.data[4*(w*y+x)+1] = color[1];
    obj.data[4*(w*y+x)+2] = color[2];
    obj.data[4*(w*y+x)+3] = color[3];    
}
ctx.putImageData(oImg,100,100);

看,(10,10)坐标点的颜色就变成了红色,一个点还是不太明显,如果是一条横向的或者的纵向的,就跟明显了:

ctx.fillRect(0,0,100,100);
//获取矩形框的像素
var oImg = ctx.getImageData(0,0,100,100);
for(var i=0;i){
    setXY(oImg,i,10,[255,0,0,255]);
}
for(var i=0;i){
    setXY(oImg,10,i,[255,0,0,255]);
}
//设置目标像素点的颜色
function setXY(obj,x,y,color){
    var w = obj.width;
    var h = obj.height;
    obj.data[4*(w*y+x)] = color[0];
    obj.data[4*(w*y+x)+1] = color[1];
    obj.data[4*(w*y+x)+2] = color[2];
    obj.data[4*(w*y+x)+3] = color[3];    
}
ctx.putImageData(oImg,100,100);

我们经常看到那种很炫酷的粒子文字,图形的效果,既然我们可以操作像素,如果我们只显示一部分的像素点,不就是粒子效果吗?看下面的例子:

ctx.fillStyle = 'red';
        ctx.arc(150,150,100,0,360*Math.PI/180,false);
        ctx.fill();
        //获取矩形框的像素
        var oImg = ctx.getImageData(50,50,200,200);
        ctx.clearRect(0,0,canvas.width,canvas.height);
        var w = oImg.width;
        var h = oImg.height;
        var arr = randomNum(w*h,w*h/10);
        var newImg = ctx.createImageData(oImg);
        for(var i=0;i){
            newImg.data[4*arr[i]] = oImg.data[4*arr[i]];
            newImg.data[4*arr[i]+1] = oImg.data[4*arr[i]+1];
            newImg.data[4*arr[i]+2] = oImg.data[4*arr[i]+2];
            newImg.data[4*arr[i]+3] = oImg.data[4*arr[i]+3];
        }
        ctx.putImageData(newImg,50,50);

        
        //某区域的部分随机数
        function randomNum(iAll,iNow){
            var arr = [];
            var newArr = [];
            for(var i=1;i<=iAll;i++){
                arr.push(i);    
            }
            for(var i=0;i){
                newArr.push(arr.splice(Math.random()*(arr.length),1));    
            }    
            return newArr;
        }

上面的例子表示,我只显示当前的十分之一的像素,具体效果看这里——粒子图形

像素操作不仅仅只能操作图形,图片我们一样可以操作,这样我们就能做出更多的效果,看看下面的例子,我们将图像换成图片,看看能不能做出粒子图片:

var aImg = new Image();
        aImg.src = '3.jpg';
        
        //当图片加载完毕才能进行下面的操作
        aImg.onload = function(){
            draw(this);    
        }
        function draw(obj){
            ctx.drawImage(obj,0,0,400,400);    
            //获取矩形框的像素
            var oImg = ctx.getImageData(0,0,400,400);
            var w = oImg.width;
            var h = oImg.height;
            var arr = randomNum(w*h,w*h/2);
            var newImg = ctx.createImageData(oImg);
            for(var i=0;i){
                newImg.data[4*arr[i]] = oImg.data[4*arr[i]];
                newImg.data[4*arr[i]+1] = oImg.data[4*arr[i]+1];
                newImg.data[4*arr[i]+2] = oImg.data[4*arr[i]+2];
                newImg.data[4*arr[i]+3] = oImg.data[4*arr[i]+3];
            }
            ctx.putImageData(newImg,0,0);
        }

        //某区域的部分随机数
        function randomNum(iAll,iNow){
            var arr = [];
            var newArr = [];
            for(var i=1;i<=iAll;i++){
                arr.push(i);    
            }
            for(var i=0;i){
                newArr.push(arr.splice(Math.random()*(arr.length),1));    
            }    
            return newArr;
        }

这里我用的是二分之一的像素点,十分之一太少了,看得不明显,由此我们可以知道,也是可以来操作图片的像素点的,具体效果看这里 —— 图片粒子化

既然我们可以操作图片,那可以做的事就太多了,先看看下面这个例子,图片反色(即将原图片的像素颜色用相反的颜色替代):

var aImg = new Image();
        aImg.src = '1.jpg';
        aImg.onload = function(){
            draw(this);
            
        }
        
        function draw(obj){
            ctx.drawImage(obj,0,0,400,400);
            var oImg = ctx.getImageData(0,0,400,400);
            var w = oImg.width;
            var h = oImg.height;
            
            for(var i=0;i){
                for(var j=0;j){
                    var result = [];
                    var color = getXY(oImg,j,i);
                    result[0] = 255 - color[0];    
                    result[1] = 255 - color[1];    
                    result[2] = 255 - color[2];    
                    result[3] = 255;    
                    setXY(oImg,j,i,result);
                }    
            }
            ctx.putImageData(oImg,w,0);
        }
        
        function getXY(obj,x,y){
            var w = obj.width;
            var h = obj.height;
            var d = obj.data;
            var color = [];
            color[0] =     obj.data[4*(y*w+x)];
            color[1] =     obj.data[4*(y*w+x)+1];
            color[2] =     obj.data[4*(y*w+x)+2];
            color[3] =     obj.data[4*(y*w+x)+3];
            return color;
        }
        
        function setXY(obj,x,y,color){
            var w = obj.width;
            var h = obj.height;
            var d = obj.data;
            obj.data[4*(y*w+x)] = color[0];
            obj.data[4*(y*w+x)+1] = color[1];
            obj.data[4*(y*w+x)+2] = color[2];
            obj.data[4*(y*w+x)+3] = color[3];
        }

是不是很有意思,具体效果可以看这里—— canvas图片反色

用这个例子,我们还可以延伸一下,让它反色后,我们再加一个倒影,美女不明显,我们用山峰那张:

var aImg = new Image();
        aImg.src = '3.jpg';
        aImg.onload = function(){
            draw(this);
            
        }
        function draw(obj){
            ctx.drawImage(obj,0,0,obj.width,obj.height);
            var oImg = ctx.getImageData(0,0,obj.width,obj.height);
            var w = oImg.width;
            var h = oImg.height;
            
            var newImg = ctx.createImageData(obj.width,obj.height)
            
            for(var i=0;i){
                for(var j=0;j){
                    var result = [];
                    var color = getXY(oImg,j,i);
                    result[0] = 255 - color[0];    
                    result[1] = 255 - color[1];    
                    result[2] = 255 - color[2];    
                    result[3] = 255;    
                    setXY(newImg,j,h-i,result);
                }    
            }
            ctx.putImageData(newImg,0,h);
        }
        
        function getXY(obj,x,y){
            var w = obj.width;
            var h = obj.height;
            var d = obj.data;
            var color = [];
            color[0] =     obj.data[4*(y*w+x)];
            color[1] =     obj.data[4*(y*w+x)+1];
            color[2] =     obj.data[4*(y*w+x)+2];
            color[3] =     obj.data[4*(y*w+x)+3];
            return color;
        }
        
        function setXY(obj,x,y,color){
            var w = obj.width;
            var h = obj.height;
            var d = obj.data;
            obj.data[4*(y*w+x)] = color[0];
            obj.data[4*(y*w+x)+1] = color[1];
            obj.data[4*(y*w+x)+2] = color[2];
            obj.data[4*(y*w+x)+3] = color[3];
        }

细心的同学一定能看出它的原理,没错,就是在设置像素的时候,将它的像素方向反向,即此处“h-i”,具体效果看这里——canvas图片反色倒影

我们还可以做一些延伸,我们可以通过像素的透明度的参数,给它设置投影渐变,我们来看看:

var aImg = new Image();
        aImg.src = '3.jpg';
        aImg.onload = function(){
            draw(this);
            
        }
        function draw(obj){
            ctx.drawImage(obj,0,0,obj.width,obj.height);
            var oImg = ctx.getImageData(0,0,obj.width,obj.height);
            var w = oImg.width;
            var h = oImg.height;
            
            var newImg = ctx.createImageData(obj.width,obj.height);
            
            for(var i=0;i){
                for(var j=0;j){
                    var result = [];
                    var color = getXY(oImg,j,i);
                    result[0] = 255 - color[0];    
                    result[1] = 255 - color[1];    
                    result[2] = 255 - color[2];    
                    result[3] = 255*i/h;    
                    setXY(newImg,j,h-i,result);
                }    
            }
            ctx.putImageData(newImg,0,h);
        }
        
        function getXY(obj,x,y){
            var w = obj.width;
            var h = obj.height;
            var d = obj.data;
            var color = [];
            color[0] =     obj.data[4*(y*w+x)];
            color[1] =     obj.data[4*(y*w+x)+1];
            color[2] =     obj.data[4*(y*w+x)+2];
            color[3] =     obj.data[4*(y*w+x)+3];
            return color;
        }
        
        function setXY(obj,x,y,color){
            var w = obj.width;
            var h = obj.height;
            var d = obj.data;
            obj.data[4*(y*w+x)] = color[0];
            obj.data[4*(y*w+x)+1] = color[1];
            obj.data[4*(y*w+x)+2] = color[2];
            obj.data[4*(y*w+x)+3] = color[3];
        }

核心代码就一个地方,255*i/h 给透明度乘以一个百分比的值,从0-255,也是很巧妙啊,具体效果看这里——canvas图片反色投影渐变

总结一下吧:虽然像素操作的方法不多,但是其功能之强大,是很多人都要望其项背的,关键在于人的想象力和深入的理解,要理解这样一个概念,掌握了像素操作,就好比是掌握了物体的核心本质,你就是造物者,你想造出什么东西,全凭你的想法,这里只是展示了一个很低劣的效果,旨在给大家展示一下canvas像素操作的魅力,抛砖引玉而已,后期会单独发一下canvas的像素操作的实例给大家参考,这个东西实在是太重要了!

好了,弄了几天了,终于写完了,本来想多写一点的,想想,后面再扩展吧!谢谢大家!

 

原文地址:http://www.cnblogs.com/liugang-vip/p/5421583.html

继续阅读 »

前几期讲的都是路径图形的绘图,这节我们要讲的是如何在画布上操作图片,因为图形画不了漂亮妹子(画图高手忽略不计),想画美女怎么办?跟我来:

想要在画布中插入一张图片,我们需要的方法是这位大侠:

drawImage()  在画布上绘制图像,画布或视频

这位大侠可谓是武功高强啊,其绝学之多,内力之深,堪称高手中的高手,那我们来看看它都有些什么绝学:

秘籍一:

drawImage(img,x,y) 在画布上定位一张图片

参数:img 表示引入的图片对象,x,y表示引入的坐标

ps:img在这里表示的是图片的对象而不是图片的路径,说明不能直接来引用图片,而是需要操作DOM的方式来引用

上面的提示说了图片的特殊性,那我们该如何来获取图片呢?我们先来一个最简单的:

<canvas width="500" height="400" id="canvas">
        <span>亲,您的浏览器不支持canvas,换个浏览器试试吧!span>
canvas>
<img src="2.jpg" alt="" id="img">

 

我们在页面上放一张图(当年的奶茶妹,当年的哦),然后获取这张图,再放到画布上

var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var oImg = document.getElementById("img");
ctx.drawImage(oImg,10,10);

看,在画布外的奶茶妹就到我们的画布上去了,可惜的是,现在的奶茶妹已经不是当前的奶茶妹了,有同学会说,我只想让我的奶茶妹在我的画布上(怎么是我的奶茶妹),不想让她在别的地方被看见,我要怎么做呢?机灵的同学一定想得到,我把外面的图片隐藏起来不就行了吗?直接隐藏行不行呢?

<img src="2.jpg" alt="" id="img" style="display:none;">

右边的奶茶妹不见了,只有我的画布上有可以的奶茶妹,恩恩,这是我想要的,说明这样有这个图片在页面上,能够获取到这个DOM元素即可,至于图片到底显不显示,不重要,那图片的隐藏方式就很多了,自身隐藏,放到一个div中div隐藏,放到canvas标签中(因为支持canvas的浏览器里面的东西是不显示的)等等,也可以用纯js的方式来添加图片:

var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var aImg = new Image();
aImg.src = '2.jpg';
ctx.onload = function(){
    ctx.drawImage(aImg,10,10,400,300);
}

 

秘籍二:

drawImage(img,x,y,w,h)  在画布上定位图片,并规定图片的宽高

参数:img 表示引入的图片对象,x,y表示引入的坐标 ,w,h表示规定图片的大小

有同学会说,奶茶妹是好,但是我的画布太小,奶茶妹太大(哪里大了),图片太大,都基本上把我的画布都占满了,如果我在画布上画别的图形,岂不是玷污了奶茶妹了,能把她变小吗?哈哈,drawImage具备孙悟空的变换本领,能大能小,不信,看这里:

var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var oImg = document.getElementById("img");
ctx.drawImage(oImg,10,10,200,150);

看,上面的奶茶妹一下子就变小了,哎呀,太小了,看不清楚,而且我只想看奶茶妹,不想看到别的糟同学,可以吗?当然可以

秘籍三

drawImage(img,sX,sY,sWidth,sHeight,x,y,width,height)  剪切画布,并在画布上定位被剪切的部分

参数:img 表示引入的图片对象,sX,sY表示剪切的其实坐标,sWidth,sHeight表示剪切的宽度和高度,x,y表示在画布上放置图片的坐标 ,width,height表示需要使用的图片的宽高

上面的参数虽多,但是还是很好理解的,我们来看看如何将奶茶妹剪切下来:

var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var oImg = document.getElementById("img");
ctx.drawImage(oImg,150,0,150,300,10,10,400,300);

 

纳里,奶茶妹怎么变成了胖子?再看一下参数,发现此时最后面的width和height已和前面的w,h代表的意思不一样了,现在的表示裁剪下来的图片需要显示多大,如果比裁剪的宽高大,则会被拉伸,比裁剪的宽高小,则会被缩小,恩,我们调成跟裁剪尺寸一样看一下:

var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var oImg = document.getElementById("img");
ctx.drawImage(oImg,150,0,150,300,10,10,150,300);

对对,就是这样的,后面的x,y表示裁剪的图片显示的位置,我们调到中间看看

ctx.drawImage(oImg,150,0,150,300,150,10,150,300);

所以在使用裁剪功能的时候,要特别注意,图片的坐标和宽高和原来的意思有区别了

秘籍四

drawImage(video,x,y,w,h)  在画布上定位视频,并规定视频的宽高

参数:video表示引入是视频对象 ,x,y表示视频引入的坐标 ,w,h表示规定视频的大小

其实这里跟引入图片是一样的,只不过它是可以引入视频的,但是这里的引入只是视频的某一帧,所以,当我们直接引入时,是没有什么反应的:

<canvas width="500" height="400" id="canvas">
        <span>亲,您的浏览器不支持canvas,换个浏览器试试吧!span>
    canvas>
    <video id="video1" controls width="270">
      <source src="http://www.w3school.com.cn/example/html5/mov_bbb.mp4" type='video/mp4'>
      <source src="http://www.w3school.com.cn/example/html5/mov_bbb.ogg" type='video/ogg'>
      <source src="http://www.w3school.com.cn/example/html5/mov_bbb.webm" type='video/webm'>
    video>
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var oVideo = document.getElementById("video1");
ctx.drawImage(oVideo,10,10,270,135);

当视频设置为autoplay时:

可以看到,右侧视频在播放,左侧没有什么反应,那怎么来播放视频呢?我们可以加一个定时器,然后每隔20秒执行一次绘画,这样一帧一帧的执行,连续起来就是一个视频了,其实视频的原理也是如此:

var canvas = document.getElementById("canvas");
        var ctx = canvas.getContext("2d");
        var oImg = document.getElementById("img");
        var oVideo = document.getElementById("video1");
        var timer = setInterval(function(){
            ctx.drawImage(oVideo,10,10,270,135);
        },20)

不想让画布外的视频显示的方法跟图片是一样的,这里我就不细说了

 

除了drawImage具有裁剪功能外,还有一个方法可以裁剪——clip(),不同的是drawImage是裁剪图片,而clip只能裁剪图形,我们具体来看一下clip吧:

clip() 从原始画布中剪切任意形状和尺寸

ps:一旦剪切了某个区域,则所有之后的绘图都会被限制在被剪切的区域内(不能访问画布上的其他区域)。您也可以在使用 clip() 方法前通过使用 save() 方法对当前画布区域进行保存,并在以后的任意时间对其进行恢复(通过 restore() 方法)。

提示这里很重要,一定要看清楚,就好比是一张很大的油画布,现在我们用一个木框架子框一部分,然后就只能在这个框里画画了,框外面的就不能来画,恩,就是这个意思,当我们用restore()方法恢复画布是时候,就好比是把木框架子取掉了,这样就可以在别的地方画了,当然画好的这部分就不要动了

举个栗子:

不用clip裁剪:

ctx.arc(200, 200, 80, (Math.PI/180)*0, (Math.PI/180)*360, false);
ctx.fill();
ctx.beginPath();
ctx.fillStyle = 'green';
ctx.arc(150, 150, 100, (Math.PI/180)*0, (Math.PI/180)*360, false);
ctx.fill();

使用clip裁剪:

ctx.arc(200, 200, 80, (Math.PI/180)*0, (Math.PI/180)*360, false);
ctx.clip();
ctx.fill();
ctx.beginPath();
ctx.fillStyle = 'green';
ctx.arc(150, 150, 100, (Math.PI/180)*0, (Math.PI/180)*360, false);
ctx.fill();

可以比较看出,后面画的圆只显示在裁剪的圆的范围中,其他的都不见了,再看一个例子:

ctx.fillRect(50,50,200,100);
ctx.clip();
ctx.beginPath();
ctx.fillStyle = 'green';
ctx.fillRect(100,100,200,100);

 

我们将圆改成实心的矩形,且是用的fillRect,而不是用fill,rect,结果是:

只显示第一个矩形,第二个矩形貌似不见了,而我们分开写:

//不用clip裁剪
ctx.rect(50,50,200,100);
ctx.fill();
ctx.beginPath();
ctx.fillStyle = 'green';
ctx.fillRect(100,100,200,100);
//使用clip裁剪
ctx.rect(50,50,200,100);
ctx.fill();
ctx.clip();
ctx.beginPath();
ctx.fillStyle = 'green';
ctx.fillRect(100,100,200,100);
//第一个矩形不填充,只画路径
ctx.rect(50,50,200,100);
ctx.clip();
ctx.beginPath();
ctx.fillStyle = 'green';
ctx.fillRect(100,100,200,100);
//将clip放在第二个矩形
ctx.rect(50,50,200,100);
ctx.fill();
ctx.beginPath();
ctx.fillStyle = 'green';
ctx.rect(100,100,200,100);
ctx.clip();
ctx.fill();

      

上面的4张图分别代码上面的4段代码的效果,从这4组对比我们可以看出:

第一:裁剪的路径必须在被裁剪图形的前面申明,如果在后面申明,则会没有效果或只有第一个图形显示;

第二:如果前面的裁剪区域要是没有填充的话,显示的部分就要2图形相交的部分,但是绘图区域还是裁剪部分的区域

 

下面要讲的是像素操作,相对来说比较复杂,需要大家的强大大脑来脑补和理解,何为像素操作?我们说任何在屏幕上显示的图形,图片,画面等等都是由像素构成的,最好理解的就是户外大屏幕的画面了,因为户外大屏幕分辨率比较小,相比之下像素的颗粒就比较大,可以清晰的看到画面是又密密麻麻的像素来显示的,当户外大屏幕的屏幕有部分花了的话,会看到呈现的画面就会在花掉的部分显示成别的颜色,很明显,对于我们的电脑显示器也是一个原理!

那么像素是通过什么来获取的呢?我们来一一介绍:

getImageData(x,y,w,h)  拷贝画布指定矩形的像素数据 

参数:x,y表示开始复制的左上角的坐标  w,h表示将要复制的区域大小

参数很好理解,就是在什么地方复制多大一个地方,而且它返回一个ImageData对象,ImageData对象里面包含了几个参数:

data:数组集合  width :对象的宽度  height:对象的高度

后面2个好理解,这个data集合到底是什么呢?我们来举个栗子:

ctx.fillRect(0,0,100,100);
//获取矩形框的像素
var oImg = ctx.getImageData(0,0,100,100);
console.log(oImg);
console.log(oImg.data)
console.log(oImg.data.length)

      

我们画了一个100*100的实现矩形,然后获取它的像素,然后分别查看了他们代表的意思,可以看到一个很有意思的东西,就是100*100的矩形的像素点应该是10000个像素,为什么它的长度是40000,这个我们可以在data数组中可以看到端倪,一个像素点是由rgba构成的:

r : 0-255  黑-白  

g : 0-255 黑-白  

b : 0-255  黑-白  

a : 0-255 透明-不透明

也就是说,一个像素是用这4个值组成的,那么10000个像素的长度自然就是40000了,而且对应的值在console中也能看到,好了,理解了这一点,那么就里像素操作不远了!

除了我们在已知的地方去获取像素外,我们能不能自己来创造像素区域呢?答案是肯定的:

createImageData(w,h)  表示创建一个规定尺寸的ImageData对象

createImageData(ImageData)  表示创建与指定的另一个 ImageData 对象尺寸相同的新 ImageData 对象(不会复制图像数据)

我们也来写一个例子:

var oImg = ctx.createImageData(100,100);
console.log(oImg);
console.log(oImg.data)
console.log(oImg.data.length)

恩,跟前面的是一样的,创建了一个ImageData对象,当然画布是没有任何的效果的,因为我们只是创建了一个对象,那么我们怎么将我们创建的对象放到画布上呢?那就要用到这个方法:

putImageData(imageData,x,y,dirtyX,dirtyY,dirtyWidth,dirtyHeight)  方法将图像数据(从指定的 ImageData 对象)放回画布上

参数: 

imageData指创建或获取的imageData对象 

x,y表示imageData对象的左上角坐标  

dirtyX,dirtyY 表示在画布上放置图像的坐标,以像素计,可选

dirtyWidth,dirtyHeight 表示在画布上放置的图形大小,可选

我们也举2个例子:

ctx.fillRect(0,0,100,100);
//获取矩形框的像素
var oImg = ctx.getImageData(0,0,100,100);
ctx.putImageData(oImg,100,100);

 

ctx.fillRect(0,0,100,100);
//获取矩形框的像素
var oImg = ctx.getImageData(0,0,100,100);
ctx.putImageData(oImg,100,100);
ctx.putImageData(oImg,100,0,10,10,50,50);

看,这么一对比,就知道这些参数是什么意思了,其中第二个我还得解释一下,如图小矩形,x,y依然是表示大的ImageData对象的起始坐标,dirtyX,dirtyY,dirtyWidth,dirtyHeight表示是相对于现在的x,y的起始坐标再来定义位置和大小,这么解释应该就明白了!

这就是操作像素的方法,看着很简单,也挺好理解,但是真正用起来,还是蛮费脑子的,我们先来看第一个小实例,改变像素的颜色:

实例效果,改变100*100的黑色矩形框中的第10行第10列的颜色,颜色为红色,先画个图分析一下:

从上面的console中也可以看出,像素点是从0开始的,如果上图就是矩形的像素点的分布(画的有点烂,将就看一下),第10行,也就是第11行,第10列也就是第11列,那么前十列的像素就是矩形的宽度*10,剩下的就是11个像素,二者相加就是所有的像素,然后每个像素用4个值表示,就是总和乘以4,好具体我们看代码:

ctx.fillRect(0,0,100,100);
//获取矩形框的像素
var oImg = ctx.getImageData(0,0,100,100);
setXY(oImg,10,10,[255,0,0,255]);
//设置目标像素点的颜色
function setXY(obj,x,y,color){
    var w = obj.width;
    var h = obj.height;
    obj.data[4*(w*y+x)] = color[0];
    obj.data[4*(w*y+x)+1] = color[1];
    obj.data[4*(w*y+x)+2] = color[2];
    obj.data[4*(w*y+x)+3] = color[3];    
}
ctx.putImageData(oImg,100,100);

看,(10,10)坐标点的颜色就变成了红色,一个点还是不太明显,如果是一条横向的或者的纵向的,就跟明显了:

ctx.fillRect(0,0,100,100);
//获取矩形框的像素
var oImg = ctx.getImageData(0,0,100,100);
for(var i=0;i){
    setXY(oImg,i,10,[255,0,0,255]);
}
for(var i=0;i){
    setXY(oImg,10,i,[255,0,0,255]);
}
//设置目标像素点的颜色
function setXY(obj,x,y,color){
    var w = obj.width;
    var h = obj.height;
    obj.data[4*(w*y+x)] = color[0];
    obj.data[4*(w*y+x)+1] = color[1];
    obj.data[4*(w*y+x)+2] = color[2];
    obj.data[4*(w*y+x)+3] = color[3];    
}
ctx.putImageData(oImg,100,100);

我们经常看到那种很炫酷的粒子文字,图形的效果,既然我们可以操作像素,如果我们只显示一部分的像素点,不就是粒子效果吗?看下面的例子:

ctx.fillStyle = 'red';
        ctx.arc(150,150,100,0,360*Math.PI/180,false);
        ctx.fill();
        //获取矩形框的像素
        var oImg = ctx.getImageData(50,50,200,200);
        ctx.clearRect(0,0,canvas.width,canvas.height);
        var w = oImg.width;
        var h = oImg.height;
        var arr = randomNum(w*h,w*h/10);
        var newImg = ctx.createImageData(oImg);
        for(var i=0;i){
            newImg.data[4*arr[i]] = oImg.data[4*arr[i]];
            newImg.data[4*arr[i]+1] = oImg.data[4*arr[i]+1];
            newImg.data[4*arr[i]+2] = oImg.data[4*arr[i]+2];
            newImg.data[4*arr[i]+3] = oImg.data[4*arr[i]+3];
        }
        ctx.putImageData(newImg,50,50);

        
        //某区域的部分随机数
        function randomNum(iAll,iNow){
            var arr = [];
            var newArr = [];
            for(var i=1;i<=iAll;i++){
                arr.push(i);    
            }
            for(var i=0;i){
                newArr.push(arr.splice(Math.random()*(arr.length),1));    
            }    
            return newArr;
        }

上面的例子表示,我只显示当前的十分之一的像素,具体效果看这里——粒子图形

像素操作不仅仅只能操作图形,图片我们一样可以操作,这样我们就能做出更多的效果,看看下面的例子,我们将图像换成图片,看看能不能做出粒子图片:

var aImg = new Image();
        aImg.src = '3.jpg';
        
        //当图片加载完毕才能进行下面的操作
        aImg.onload = function(){
            draw(this);    
        }
        function draw(obj){
            ctx.drawImage(obj,0,0,400,400);    
            //获取矩形框的像素
            var oImg = ctx.getImageData(0,0,400,400);
            var w = oImg.width;
            var h = oImg.height;
            var arr = randomNum(w*h,w*h/2);
            var newImg = ctx.createImageData(oImg);
            for(var i=0;i){
                newImg.data[4*arr[i]] = oImg.data[4*arr[i]];
                newImg.data[4*arr[i]+1] = oImg.data[4*arr[i]+1];
                newImg.data[4*arr[i]+2] = oImg.data[4*arr[i]+2];
                newImg.data[4*arr[i]+3] = oImg.data[4*arr[i]+3];
            }
            ctx.putImageData(newImg,0,0);
        }

        //某区域的部分随机数
        function randomNum(iAll,iNow){
            var arr = [];
            var newArr = [];
            for(var i=1;i<=iAll;i++){
                arr.push(i);    
            }
            for(var i=0;i){
                newArr.push(arr.splice(Math.random()*(arr.length),1));    
            }    
            return newArr;
        }

这里我用的是二分之一的像素点,十分之一太少了,看得不明显,由此我们可以知道,也是可以来操作图片的像素点的,具体效果看这里 —— 图片粒子化

既然我们可以操作图片,那可以做的事就太多了,先看看下面这个例子,图片反色(即将原图片的像素颜色用相反的颜色替代):

var aImg = new Image();
        aImg.src = '1.jpg';
        aImg.onload = function(){
            draw(this);
            
        }
        
        function draw(obj){
            ctx.drawImage(obj,0,0,400,400);
            var oImg = ctx.getImageData(0,0,400,400);
            var w = oImg.width;
            var h = oImg.height;
            
            for(var i=0;i){
                for(var j=0;j){
                    var result = [];
                    var color = getXY(oImg,j,i);
                    result[0] = 255 - color[0];    
                    result[1] = 255 - color[1];    
                    result[2] = 255 - color[2];    
                    result[3] = 255;    
                    setXY(oImg,j,i,result);
                }    
            }
            ctx.putImageData(oImg,w,0);
        }
        
        function getXY(obj,x,y){
            var w = obj.width;
            var h = obj.height;
            var d = obj.data;
            var color = [];
            color[0] =     obj.data[4*(y*w+x)];
            color[1] =     obj.data[4*(y*w+x)+1];
            color[2] =     obj.data[4*(y*w+x)+2];
            color[3] =     obj.data[4*(y*w+x)+3];
            return color;
        }
        
        function setXY(obj,x,y,color){
            var w = obj.width;
            var h = obj.height;
            var d = obj.data;
            obj.data[4*(y*w+x)] = color[0];
            obj.data[4*(y*w+x)+1] = color[1];
            obj.data[4*(y*w+x)+2] = color[2];
            obj.data[4*(y*w+x)+3] = color[3];
        }

是不是很有意思,具体效果可以看这里—— canvas图片反色

用这个例子,我们还可以延伸一下,让它反色后,我们再加一个倒影,美女不明显,我们用山峰那张:

var aImg = new Image();
        aImg.src = '3.jpg';
        aImg.onload = function(){
            draw(this);
            
        }
        function draw(obj){
            ctx.drawImage(obj,0,0,obj.width,obj.height);
            var oImg = ctx.getImageData(0,0,obj.width,obj.height);
            var w = oImg.width;
            var h = oImg.height;
            
            var newImg = ctx.createImageData(obj.width,obj.height)
            
            for(var i=0;i){
                for(var j=0;j){
                    var result = [];
                    var color = getXY(oImg,j,i);
                    result[0] = 255 - color[0];    
                    result[1] = 255 - color[1];    
                    result[2] = 255 - color[2];    
                    result[3] = 255;    
                    setXY(newImg,j,h-i,result);
                }    
            }
            ctx.putImageData(newImg,0,h);
        }
        
        function getXY(obj,x,y){
            var w = obj.width;
            var h = obj.height;
            var d = obj.data;
            var color = [];
            color[0] =     obj.data[4*(y*w+x)];
            color[1] =     obj.data[4*(y*w+x)+1];
            color[2] =     obj.data[4*(y*w+x)+2];
            color[3] =     obj.data[4*(y*w+x)+3];
            return color;
        }
        
        function setXY(obj,x,y,color){
            var w = obj.width;
            var h = obj.height;
            var d = obj.data;
            obj.data[4*(y*w+x)] = color[0];
            obj.data[4*(y*w+x)+1] = color[1];
            obj.data[4*(y*w+x)+2] = color[2];
            obj.data[4*(y*w+x)+3] = color[3];
        }

细心的同学一定能看出它的原理,没错,就是在设置像素的时候,将它的像素方向反向,即此处“h-i”,具体效果看这里——canvas图片反色倒影

我们还可以做一些延伸,我们可以通过像素的透明度的参数,给它设置投影渐变,我们来看看:

var aImg = new Image();
        aImg.src = '3.jpg';
        aImg.onload = function(){
            draw(this);
            
        }
        function draw(obj){
            ctx.drawImage(obj,0,0,obj.width,obj.height);
            var oImg = ctx.getImageData(0,0,obj.width,obj.height);
            var w = oImg.width;
            var h = oImg.height;
            
            var newImg = ctx.createImageData(obj.width,obj.height);
            
            for(var i=0;i){
                for(var j=0;j){
                    var result = [];
                    var color = getXY(oImg,j,i);
                    result[0] = 255 - color[0];    
                    result[1] = 255 - color[1];    
                    result[2] = 255 - color[2];    
                    result[3] = 255*i/h;    
                    setXY(newImg,j,h-i,result);
                }    
            }
            ctx.putImageData(newImg,0,h);
        }
        
        function getXY(obj,x,y){
            var w = obj.width;
            var h = obj.height;
            var d = obj.data;
            var color = [];
            color[0] =     obj.data[4*(y*w+x)];
            color[1] =     obj.data[4*(y*w+x)+1];
            color[2] =     obj.data[4*(y*w+x)+2];
            color[3] =     obj.data[4*(y*w+x)+3];
            return color;
        }
        
        function setXY(obj,x,y,color){
            var w = obj.width;
            var h = obj.height;
            var d = obj.data;
            obj.data[4*(y*w+x)] = color[0];
            obj.data[4*(y*w+x)+1] = color[1];
            obj.data[4*(y*w+x)+2] = color[2];
            obj.data[4*(y*w+x)+3] = color[3];
        }

核心代码就一个地方,255*i/h 给透明度乘以一个百分比的值,从0-255,也是很巧妙啊,具体效果看这里——canvas图片反色投影渐变

总结一下吧:虽然像素操作的方法不多,但是其功能之强大,是很多人都要望其项背的,关键在于人的想象力和深入的理解,要理解这样一个概念,掌握了像素操作,就好比是掌握了物体的核心本质,你就是造物者,你想造出什么东西,全凭你的想法,这里只是展示了一个很低劣的效果,旨在给大家展示一下canvas像素操作的魅力,抛砖引玉而已,后期会单独发一下canvas的像素操作的实例给大家参考,这个东西实在是太重要了!

好了,弄了几天了,终于写完了,本来想多写一点的,想想,后面再扩展吧!谢谢大家!

 

原文地址:http://www.cnblogs.com/liugang-vip/p/5421583.html

收起阅读 »

-_-#【Canvas】绘制文本

DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>title>
head>
<body>
    <canvas id="drawing" width="200" height="200" style="background:gray;">A drawing of somethingcanvas>
    <script>
        var drawing = document.getElementById('drawing')
        if (drawing.getContext) {
            var context = drawing.getContext('2d')

            context.font = 'bold 14px arial'
            context.textAlign = 'center'
            context.textBaseline = 'middle'
            context.fillText('12', 100, 20)

            // 如果将 textAlign 设置为"start",则 x 坐标表示的是文本左端的位置
            context.textAlign = 'start'
            context.fillStyle = 'rgba(0,0,255,0.5)'
            context.fillText('12', 100, 40)

            // 则 x 坐标表示的是文本右端的位置
            context.textAlign = 'end'
            context.fillStyle = 'rgba(255,0,0,0.5)'
            context.fillText('12', 100, 60)

            context.textAlign = 'start'
            var fontSize = 100
            context.font = fontSize + 'px arial'

            // 返回一个 TextMetrics 对象。返回的对象目前只有一个 width 属性,但将来还会增加更多度量属性
            while (context.measureText('Hello world!').width > 140) {
                fontSize--
                context.font = fontSize + 'px arial'
            }
            context.fillText('Hello world!', 10, 10)
        }
    script>
body>
html>

 

原文地址:http://www.cnblogs.com/jzm17173/p/3624639.html

继续阅读 »
DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>title>
head>
<body>
    <canvas id="drawing" width="200" height="200" style="background:gray;">A drawing of somethingcanvas>
    <script>
        var drawing = document.getElementById('drawing')
        if (drawing.getContext) {
            var context = drawing.getContext('2d')

            context.font = 'bold 14px arial'
            context.textAlign = 'center'
            context.textBaseline = 'middle'
            context.fillText('12', 100, 20)

            // 如果将 textAlign 设置为"start",则 x 坐标表示的是文本左端的位置
            context.textAlign = 'start'
            context.fillStyle = 'rgba(0,0,255,0.5)'
            context.fillText('12', 100, 40)

            // 则 x 坐标表示的是文本右端的位置
            context.textAlign = 'end'
            context.fillStyle = 'rgba(255,0,0,0.5)'
            context.fillText('12', 100, 60)

            context.textAlign = 'start'
            var fontSize = 100
            context.font = fontSize + 'px arial'

            // 返回一个 TextMetrics 对象。返回的对象目前只有一个 width 属性,但将来还会增加更多度量属性
            while (context.measureText('Hello world!').width > 140) {
                fontSize--
                context.font = fontSize + 'px arial'
            }
            context.fillText('Hello world!', 10, 10)
        }
    script>
body>
html>

 

原文地址:http://www.cnblogs.com/jzm17173/p/3624639.html

收起阅读 »

WP7 Mango HTML5开发体验(二)PhoneGap运行机制

 一、前言

PhoneGap是一个开源的开发框架,用来构建跨平台的使用HTML,CSS和JavaScript的移动应用程序

二、前期准备

下载PhoneGap: http://phonegap.com/ 点击右上角的

获得压缩包,解压到任意目录。

三、运行example和tests

1.打开,选择GapExample.sln用vs2010打开。

2.观察目录结构如下图所示:

3.编译并在模拟器中运行,运行结果如下所示:

我们可以看到PhoneGap当前版本有很多基础特色功能,包括JS API去使用WP7 Mango特性,例如:报警或提醒框(alert,confirm)媒体捕获(图片和视频)等。

4.打开,选择MobileSpecUnitTests.sln用vs2010打开。

5.编译并在模拟器中运行,运行结果如下所示:

我们可以在PhoneGap单元测试中看到PhoneGap使开发者能够利用Windows Phone智能手机的核心功能——包括地理定位,加速器,联系人等。

四、运行机制

在www文件夹下的HTML / JS / CSS包括图片等所有的资源都将被打包成XAP部署到手机上,但不能在运行时直接访问,因为需要一个额外的unpackaging步骤。
当应用程序首次运行时,www文件夹下的所有资源都从XAP IsolatedStorage转化成二进制数据。(IsolatedStorage是每个应用程序存储数据的位置。 IsolatedStorage由应用程序管理,不同的应用程序的IsolatedStorage彼此隔离。)

unpackaging www文件夹的内容之后,www / index.html文件加载到嵌入式无头的IE9浏览器中。由IE9执行HTML和JS代码。

1.在GapExample项目中双击打开

可以清楚的看到PhoneGap添加了一个无头的IE9浏览器:

2.PhoneGap如何得知资源信息

xml文件GapSourceDictionary.xml存储了所有资源的位置和名称。下面的代码负责读取GapSourceDictionary.xml的内容

 StreamResourceInfo streamInfo = Application.GetResourceStream(new Uri("GapSourceDictionary.xml", UriKind.Relative));

                if (streamInfo != null)
                {
                    StreamReader sr = new StreamReader(streamInfo.Stream);
                    //This will Read Keys Collection for the xml file

                    XDocument document = XDocument.Parse(sr.ReadToEnd());

                    var files = from results in document.Descendants("FilePath")
                                 select new
                                 {
                                     path = (string)results.Attribute("Value")
                                 };
                    StreamResourceInfo fileResourceStreamInfo;



                    using (IsolatedStorageFile appStorage = IsolatedStorageFile.GetUserStoreForApplication())
                    {

                        foreach (var file in files)
                        {
                            fileResourceStreamInfo = Application.GetResourceStream(new Uri(file.path, UriKind.Relative));

                            if (fileResourceStreamInfo != null)
                            {
                                using (BinaryReader br = new BinaryReader(fileResourceStreamInfo.Stream))
                                {
                                    byte[] data = br.ReadBytes((int)fileResourceStreamInfo.Stream.Length);

                                    string strBaseDir = file.path.Substring(0, file.path.LastIndexOf(System.IO.Path.DirectorySeparatorChar));
                                    appStorage.CreateDirectory(strBaseDir);

                                    // This will truncate/overwrite an existing file, or 
                                    using (IsolatedStorageFileStream outFile = appStorage.OpenFile(file.path, FileMode.Create))
                                    {
                                        Debug.WriteLine("Writing data for " + file.path + " and length = " + data.Length);
                                        using (var writer = new BinaryWriter(outFile))
                                        {
                                            writer.Write(data);
                                        }
                                    }

                                }
                            }
                            else
                            {
                                Debug.WriteLine("Failed to write file :: " + file.path + " did you forget to add it to the project?");
                            }
                        }
                    }
                }

3.为什么启动页面必须是www/index.html

通过

  Uri indexUri = new Uri("www/index.html", UriKind.Relative);
this.GapBrowser.Navigate(indexUri);


得知PhoneGap采用硬编码的方式将启动页面写死了,相信以后的版本会通过配置文件更改吧,现在大家还是按它写的来吧!

版权所有欢迎转载

 

 

 

 

 

 





原文地址:http://www.cnblogs.com/ootwooo/archive/2011/11/14/2246423.html

继续阅读 »

 一、前言

PhoneGap是一个开源的开发框架,用来构建跨平台的使用HTML,CSS和JavaScript的移动应用程序

二、前期准备

下载PhoneGap: http://phonegap.com/ 点击右上角的

获得压缩包,解压到任意目录。

三、运行example和tests

1.打开,选择GapExample.sln用vs2010打开。

2.观察目录结构如下图所示:

3.编译并在模拟器中运行,运行结果如下所示:

我们可以看到PhoneGap当前版本有很多基础特色功能,包括JS API去使用WP7 Mango特性,例如:报警或提醒框(alert,confirm)媒体捕获(图片和视频)等。

4.打开,选择MobileSpecUnitTests.sln用vs2010打开。

5.编译并在模拟器中运行,运行结果如下所示:

我们可以在PhoneGap单元测试中看到PhoneGap使开发者能够利用Windows Phone智能手机的核心功能——包括地理定位,加速器,联系人等。

四、运行机制

在www文件夹下的HTML / JS / CSS包括图片等所有的资源都将被打包成XAP部署到手机上,但不能在运行时直接访问,因为需要一个额外的unpackaging步骤。
当应用程序首次运行时,www文件夹下的所有资源都从XAP IsolatedStorage转化成二进制数据。(IsolatedStorage是每个应用程序存储数据的位置。 IsolatedStorage由应用程序管理,不同的应用程序的IsolatedStorage彼此隔离。)

unpackaging www文件夹的内容之后,www / index.html文件加载到嵌入式无头的IE9浏览器中。由IE9执行HTML和JS代码。

1.在GapExample项目中双击打开

可以清楚的看到PhoneGap添加了一个无头的IE9浏览器:

2.PhoneGap如何得知资源信息

xml文件GapSourceDictionary.xml存储了所有资源的位置和名称。下面的代码负责读取GapSourceDictionary.xml的内容

 StreamResourceInfo streamInfo = Application.GetResourceStream(new Uri("GapSourceDictionary.xml", UriKind.Relative));

                if (streamInfo != null)
                {
                    StreamReader sr = new StreamReader(streamInfo.Stream);
                    //This will Read Keys Collection for the xml file

                    XDocument document = XDocument.Parse(sr.ReadToEnd());

                    var files = from results in document.Descendants("FilePath")
                                 select new
                                 {
                                     path = (string)results.Attribute("Value")
                                 };
                    StreamResourceInfo fileResourceStreamInfo;



                    using (IsolatedStorageFile appStorage = IsolatedStorageFile.GetUserStoreForApplication())
                    {

                        foreach (var file in files)
                        {
                            fileResourceStreamInfo = Application.GetResourceStream(new Uri(file.path, UriKind.Relative));

                            if (fileResourceStreamInfo != null)
                            {
                                using (BinaryReader br = new BinaryReader(fileResourceStreamInfo.Stream))
                                {
                                    byte[] data = br.ReadBytes((int)fileResourceStreamInfo.Stream.Length);

                                    string strBaseDir = file.path.Substring(0, file.path.LastIndexOf(System.IO.Path.DirectorySeparatorChar));
                                    appStorage.CreateDirectory(strBaseDir);

                                    // This will truncate/overwrite an existing file, or 
                                    using (IsolatedStorageFileStream outFile = appStorage.OpenFile(file.path, FileMode.Create))
                                    {
                                        Debug.WriteLine("Writing data for " + file.path + " and length = " + data.Length);
                                        using (var writer = new BinaryWriter(outFile))
                                        {
                                            writer.Write(data);
                                        }
                                    }

                                }
                            }
                            else
                            {
                                Debug.WriteLine("Failed to write file :: " + file.path + " did you forget to add it to the project?");
                            }
                        }
                    }
                }

3.为什么启动页面必须是www/index.html

通过

  Uri indexUri = new Uri("www/index.html", UriKind.Relative);
this.GapBrowser.Navigate(indexUri);


得知PhoneGap采用硬编码的方式将启动页面写死了,相信以后的版本会通过配置文件更改吧,现在大家还是按它写的来吧!

版权所有欢迎转载

 

 

 

 

 

 





原文地址:http://www.cnblogs.com/ootwooo/archive/2011/11/14/2246423.html

收起阅读 »

HTML5 Canvas学习---第一章 《Hello World及图片显示》

  在这个章节我们将在Html中使用Canvas标签,再使用Javascript操纵它,达到显示《Hello World》及图片的目的。

开始之前我们需要了解2个对象的概念:window和document。

  1. window对象:window对象在DOM最顶层。我们应该检测这个对象以确保所有的资源和代码在我们开始编写Canvas应用之前已经载入完成。
  2. document对象:该对象包含页面上所有的HTML标签。我们需要查看该对象,以寻找标签并且使用JavaScript来操纵他。

HTML代码为:

doctype html>
<html lang="en">
    <head>
        <meta charset="utf-8" />
        <script type="text/javascript" src="chp1.js">script>
        <script type="text/javascript" src="modernizr.custom.99886.js">script>
    head>
    <body>
    
<canvas id="canvas_helloworld" width="500" height="300"> 你的浏览器不支持HTML5 Canvas canvas> body> html>

其中chp1.js为我们以后需要编写的javascript脚本。modernizr.custom.99886.js为modernizr第三方javascript插件,使用它可以避免不同浏览器引起的各种问题。

具体内容请看这里:modernizr介绍

首先我们需要检测window对象的load事件,它是当所有的HTML标签载入完成后触发。

检测load时间有两种方式

  1. window.addEventListener("load", eventWindowCallBack, false);第一个参数:事件名称,第二个参数:回调函数。第三个参数:设为false就行
  2. window.onload=function() { ... };

在这个章节以及以后的文章中我们都是用第一种方式。

 

HTML代码中我们创建了Canvas标签,它主要有三个属性。

  •  id:唯一标识符
  • width:宽度
  • height: 高度

第一步检测浏览器是否支持canvas,有多种实现方法:theCanvas为我们在HTML中布置得canvas对象。

第一种为

if(!theCanvas || !theCanvas.getContext) {
        return;
    }

第二种为

!document.createElement('testcanvas').getContext;

第三种为使用modernizr插件

return Modernizr.canvas;

我们使用第三种方式,因为它在不同的浏览器中做了不同的处理,拿过来直接用。

第二步获取canvas对象,并获取context对象。

var theCanvas = document.getElementById("canvas_helloworld");
var context = theCanvas.getContext("2d"); //canvas中有很多不同的context,这里我们仅需要2D

第三部创建drawScreen()函数,把内容画到界面中。

在这里我们涉及的函数及属性为

  1. fillStyle属性:设置颜色
  2. fillRect(x, y, width, height):画矩形参数为左上角及宽度和高度。
  3. font属性:设置文字风格
  4. fillText(text, x, y):往canvas画出字符串,余下的参数为左上角的x坐标和y坐标。

具体代码为

        context.fillStyle="#ffffaa";
        context.fillRect(0,0,500,300);
        context.fillStyle="#000000";
        context.font="20px _sans";
        context.textBaseline="top";
        context.fillText("Hello World!", 195, 80);        

还有一步我们需要在canvas载入一张图片。在canvas中显示图片,我们需要实例化一个Image()对象并且指定它的src属性。

在显示之前,你需要等待Image载入完毕,当载入完成后可以创建一个回调函数把它显示到屏幕中。

        var img = new Image();
        img.src="rubi.jpg";
        img.onload=function() {
            context.drawImage(img, 180, 130);
        }

最后我们在canvas的边上画一个黑色的矩形,醒目的显示出来。

     context.strokeStyle="#000000";
        context.strokeRect(5, 5, 490, 290);

整理后的代码为

/**
 * @author Rafael
 */
window.addEventListener("load",eventWindowLoaded, false);

function eventWindowLoaded() {
    canvasApp();
}

function canvasSupport() {
    // return !document.createElement('testcanvas').getContext;
    return Modernizr.canvas;
}

function canvasApp() {

    if(!canvasSupport()) {
        return;
    }
    var theCanvas = document.getElementById("canvas_helloworld");
    var context = theCanvas.getContext("2d"); 
    //canvas中有很多不同的context,这里我们仅需要2D
        // if(!theCanvas || !theCanvas.getContext) {
        // return;
    // }
    
    function drawScreen() {
        context.fillStyle="#ffffaa";
        context.fillRect(0,0,500,300);
        context.fillStyle="#000000";
        context.font="20px _sans";
        context.textBaseline="top";
        context.fillText("Hello World!", 195, 80);
        
        var img = new Image();
        img.src="rubi.jpg";
        img.onload=function() {
            context.drawImage(img, 180, 130);
        }
        
        context.strokeStyle="#000000";
        context.strokeRect(5, 5, 490, 290);
    }
    drawScreen();
    
}

 

 至此,这一篇的内容讲完了,今天是学习HTML5的第一天,以后也还会陆续的把最新的学习成果发表出来供大家分享,具体时间为一周4篇左右。

写的不好的地方,望大家谅解,我也是第一次写博客。只要对一个人有帮助,我的目的就达到了。

 

 

 

原文地址:http://www.cnblogs.com/tcpcg/archive/2012/12/03/HTML5_Hello_World.html

继续阅读 »

  在这个章节我们将在Html中使用Canvas标签,再使用Javascript操纵它,达到显示《Hello World》及图片的目的。

开始之前我们需要了解2个对象的概念:window和document。

  1. window对象:window对象在DOM最顶层。我们应该检测这个对象以确保所有的资源和代码在我们开始编写Canvas应用之前已经载入完成。
  2. document对象:该对象包含页面上所有的HTML标签。我们需要查看该对象,以寻找标签并且使用JavaScript来操纵他。

HTML代码为:

doctype html>
<html lang="en">
    <head>
        <meta charset="utf-8" />
        <script type="text/javascript" src="chp1.js">script>
        <script type="text/javascript" src="modernizr.custom.99886.js">script>
    head>
    <body>
    
<canvas id="canvas_helloworld" width="500" height="300"> 你的浏览器不支持HTML5 Canvas canvas> body> html>

其中chp1.js为我们以后需要编写的javascript脚本。modernizr.custom.99886.js为modernizr第三方javascript插件,使用它可以避免不同浏览器引起的各种问题。

具体内容请看这里:modernizr介绍

首先我们需要检测window对象的load事件,它是当所有的HTML标签载入完成后触发。

检测load时间有两种方式

  1. window.addEventListener("load", eventWindowCallBack, false);第一个参数:事件名称,第二个参数:回调函数。第三个参数:设为false就行
  2. window.onload=function() { ... };

在这个章节以及以后的文章中我们都是用第一种方式。

 

HTML代码中我们创建了Canvas标签,它主要有三个属性。

  •  id:唯一标识符
  • width:宽度
  • height: 高度

第一步检测浏览器是否支持canvas,有多种实现方法:theCanvas为我们在HTML中布置得canvas对象。

第一种为

if(!theCanvas || !theCanvas.getContext) {
        return;
    }

第二种为

!document.createElement('testcanvas').getContext;

第三种为使用modernizr插件

return Modernizr.canvas;

我们使用第三种方式,因为它在不同的浏览器中做了不同的处理,拿过来直接用。

第二步获取canvas对象,并获取context对象。

var theCanvas = document.getElementById("canvas_helloworld");
var context = theCanvas.getContext("2d"); //canvas中有很多不同的context,这里我们仅需要2D

第三部创建drawScreen()函数,把内容画到界面中。

在这里我们涉及的函数及属性为

  1. fillStyle属性:设置颜色
  2. fillRect(x, y, width, height):画矩形参数为左上角及宽度和高度。
  3. font属性:设置文字风格
  4. fillText(text, x, y):往canvas画出字符串,余下的参数为左上角的x坐标和y坐标。

具体代码为

        context.fillStyle="#ffffaa";
        context.fillRect(0,0,500,300);
        context.fillStyle="#000000";
        context.font="20px _sans";
        context.textBaseline="top";
        context.fillText("Hello World!", 195, 80);        

还有一步我们需要在canvas载入一张图片。在canvas中显示图片,我们需要实例化一个Image()对象并且指定它的src属性。

在显示之前,你需要等待Image载入完毕,当载入完成后可以创建一个回调函数把它显示到屏幕中。

        var img = new Image();
        img.src="rubi.jpg";
        img.onload=function() {
            context.drawImage(img, 180, 130);
        }

最后我们在canvas的边上画一个黑色的矩形,醒目的显示出来。

     context.strokeStyle="#000000";
        context.strokeRect(5, 5, 490, 290);

整理后的代码为

/**
 * @author Rafael
 */
window.addEventListener("load",eventWindowLoaded, false);

function eventWindowLoaded() {
    canvasApp();
}

function canvasSupport() {
    // return !document.createElement('testcanvas').getContext;
    return Modernizr.canvas;
}

function canvasApp() {

    if(!canvasSupport()) {
        return;
    }
    var theCanvas = document.getElementById("canvas_helloworld");
    var context = theCanvas.getContext("2d"); 
    //canvas中有很多不同的context,这里我们仅需要2D
        // if(!theCanvas || !theCanvas.getContext) {
        // return;
    // }
    
    function drawScreen() {
        context.fillStyle="#ffffaa";
        context.fillRect(0,0,500,300);
        context.fillStyle="#000000";
        context.font="20px _sans";
        context.textBaseline="top";
        context.fillText("Hello World!", 195, 80);
        
        var img = new Image();
        img.src="rubi.jpg";
        img.onload=function() {
            context.drawImage(img, 180, 130);
        }
        
        context.strokeStyle="#000000";
        context.strokeRect(5, 5, 490, 290);
    }
    drawScreen();
    
}

 

 至此,这一篇的内容讲完了,今天是学习HTML5的第一天,以后也还会陆续的把最新的学习成果发表出来供大家分享,具体时间为一周4篇左右。

写的不好的地方,望大家谅解,我也是第一次写博客。只要对一个人有帮助,我的目的就达到了。

 

 

 

原文地址:http://www.cnblogs.com/tcpcg/archive/2012/12/03/HTML5_Hello_World.html

收起阅读 »

Android中Canvas和Paint简单例子

 

package com.canvas.paint;

import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;
import android.graphics.Shader;
import android.os.Bundle;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

public class mainActivity extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(new MyView(this));
    }
    class MyView extends SurfaceView implements SurfaceHolder.Callback{
     private SurfaceHolder mHolder;
     private Canvas canvas;
  public MyView(Context context) {
   super(context);
   mHolder = getHolder();
   mHolder.addCallback(this);//设置Surface生命周期回调
  }
  @Override
  public void surfaceChanged(SurfaceHolder holder, int format, int width,
    int height) {
  }
  @Override
  public void surfaceCreated(SurfaceHolder holder) {
   canvas = mHolder.lockCanvas();//获得画布
   canvas.drawColor(Color.WHITE);//设置画布背景为白色
   Paint mPaint = new Paint();
   //画矩形
   mPaint.setColor(Color.YELLOW);
   canvas.drawRect(100, 200, 200, 300, mPaint);
   canvas.save();//每画完一个图做备忘存储,以保证与其它图形互不影响
   //画旋转
   canvas.rotate(45);//旋转角度45
   mPaint.setColor(Color.GREEN);
   canvas.drawRect(150, 10, 200, 60, mPaint);//画矩形
   canvas.save();
   //画渐变色圆形
   Shader mShader=new LinearGradient(0,0,100,100,
     new int[]{Color.RED,Color.GREEN,Color.BLUE,Color.YELLOW},
     null,Shader.TileMode.REPEAT);//使用着色器
   mPaint.setShader(mShader);
   canvas.drawCircle(500, 150, 80, mPaint);
   /*
   canvas.save();
   //画三角形
   mPaint.setStyle(Paint.Style.STROKE);//设置空心
   mPaint.setStrokeWidth(3);//设置p外框宽度
   Path path=new Path();
   path.moveTo(10,330);
   path.lineTo(70,330);
   path.lineTo(40,270);
   path.close();
   canvas.drawPath(path,mPaint);
   canvas.save();
   // 画梯形
   mPaint.setAntiAlias(true);//去掉边缘锯齿
   mPaint.setColor(Color.BLUE);
   mPaint.setStyle(Paint.Style.FILL);//设置实心
   Path path1=new Path();
   path1.moveTo(10,410);
   path1.lineTo(70,410);
   path1.lineTo(55,350);
   path1.lineTo(25,350);
   path1.close();
   canvas.drawPath(path1,mPaint);
   canvas.save();
   //画椭圆形
   mPaint.setAntiAlias(true);//去掉边缘锯齿
   mPaint.setColor(Color.RED);
   RectF re=new RectF(10,220,70,250);
   canvas.drawOval(re,mPaint);
   */
   canvas.restore();
   mHolder.unlockCanvasAndPost(canvas);//完成绘图后解锁递交画布视图
  }
  @Override
  public void surfaceDestroyed(SurfaceHolder holder) {
   // TODO Auto-generated method stub
  }
    }
}

 

原文地址:http://www.cnblogs.com/-cyb/archive/2011/06/30/2229162.html

继续阅读 »

 

package com.canvas.paint;

import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;
import android.graphics.Shader;
import android.os.Bundle;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

public class mainActivity extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(new MyView(this));
    }
    class MyView extends SurfaceView implements SurfaceHolder.Callback{
     private SurfaceHolder mHolder;
     private Canvas canvas;
  public MyView(Context context) {
   super(context);
   mHolder = getHolder();
   mHolder.addCallback(this);//设置Surface生命周期回调
  }
  @Override
  public void surfaceChanged(SurfaceHolder holder, int format, int width,
    int height) {
  }
  @Override
  public void surfaceCreated(SurfaceHolder holder) {
   canvas = mHolder.lockCanvas();//获得画布
   canvas.drawColor(Color.WHITE);//设置画布背景为白色
   Paint mPaint = new Paint();
   //画矩形
   mPaint.setColor(Color.YELLOW);
   canvas.drawRect(100, 200, 200, 300, mPaint);
   canvas.save();//每画完一个图做备忘存储,以保证与其它图形互不影响
   //画旋转
   canvas.rotate(45);//旋转角度45
   mPaint.setColor(Color.GREEN);
   canvas.drawRect(150, 10, 200, 60, mPaint);//画矩形
   canvas.save();
   //画渐变色圆形
   Shader mShader=new LinearGradient(0,0,100,100,
     new int[]{Color.RED,Color.GREEN,Color.BLUE,Color.YELLOW},
     null,Shader.TileMode.REPEAT);//使用着色器
   mPaint.setShader(mShader);
   canvas.drawCircle(500, 150, 80, mPaint);
   /*
   canvas.save();
   //画三角形
   mPaint.setStyle(Paint.Style.STROKE);//设置空心
   mPaint.setStrokeWidth(3);//设置p外框宽度
   Path path=new Path();
   path.moveTo(10,330);
   path.lineTo(70,330);
   path.lineTo(40,270);
   path.close();
   canvas.drawPath(path,mPaint);
   canvas.save();
   // 画梯形
   mPaint.setAntiAlias(true);//去掉边缘锯齿
   mPaint.setColor(Color.BLUE);
   mPaint.setStyle(Paint.Style.FILL);//设置实心
   Path path1=new Path();
   path1.moveTo(10,410);
   path1.lineTo(70,410);
   path1.lineTo(55,350);
   path1.lineTo(25,350);
   path1.close();
   canvas.drawPath(path1,mPaint);
   canvas.save();
   //画椭圆形
   mPaint.setAntiAlias(true);//去掉边缘锯齿
   mPaint.setColor(Color.RED);
   RectF re=new RectF(10,220,70,250);
   canvas.drawOval(re,mPaint);
   */
   canvas.restore();
   mHolder.unlockCanvasAndPost(canvas);//完成绘图后解锁递交画布视图
  }
  @Override
  public void surfaceDestroyed(SurfaceHolder holder) {
   // TODO Auto-generated method stub
  }
    }
}

 

原文地址:http://www.cnblogs.com/-cyb/archive/2011/06/30/2229162.html

收起阅读 »

iOS视频开发经验

iOS视频开发经验

手机比PC的优势除了便携外,我认为最重要的就是可以快速方便的创作多媒体作品。照片分享,语音输入,视频录制,地理位置。一个成功的手机APP从产品形态上都有这其中的一项或多项,比如instagram,微信。如果把Web2.0的交互体验照搬到手机上就是死路一条。 当智能手机遇上视频就像潘金莲遇上西门庆,各取所需一拍即合,想不发生点事情都难。他们的结晶就是微视频。微视频可以说把手机的视频录制和碎片时间两个特点发挥到了极致,视频相关的APP现在无温不火的原因我认为跟坑爹的运营商有关。虽然现在移动网络流量小速度慢,但是不妨碍我们先把技术积累做起来。

这篇文章主要介绍本人在iOS视频开发中的一点经验。

视频实质:

纯粹的视频(不包括音频)实质上就是一组帧图片,经过视频编码成为视频(video)文件再把音频(audio)文件有些还有字幕文件组装在一起成为我们看到的视频(movie)文件。1秒内出现的图片数就是帧率,图片间隔越小画面就越流畅,所以帧率越高效果就越好,需要的存储空间也就越多。

视频编码:

因为不进行编码的视频数据量非常大,会造成存储和传输上的困难,所以视频文件都需要在录制完成后进行编码。视频编码主要从两个维度压缩数据。

  • 1、单张图像某一区域相邻像素相似,比如一片红色只记录红色色值和区域,不用记录这个区域的每一个像素点。
  • 2、相邻图像之间内容相似,因为相邻两帧要制造连续的效果,所以两帧之间的内容一般非常接近。目前主流的视频编码技术都是用图像编码方法对第一帧进行编码,然后用某种方式描述接下来的帧相对于附近的帧有什么区别。

视频格式:

MP4、MOV、AVI、RMVB这些播放格式其实都是封装格式,除了RMVB比较特殊外,其他格式内封装的视频编码格式都是H264,H264以高压缩率闻名于世,压缩效率比MEPG-2提升一倍多,但是世上没有两全其美的事,H264的解码难度提高了3倍多。

视频码率:

视频文件的大小除以是视频的时长定义为码率。

码率和分辨率跟视频质量的关系:

  • 码率可以理解为取样率,单位时间内取样率越大,精度就越高,同时体积也越大。
  • 当视频没有经过编码时,如果分辨率越高,那么视频图像的细节越清晰。
  • 但如果视频经过编码,被限制在一定码率内,编码器就必须舍弃掉一部分细节。
  • 所以分辨率和码率都同清晰度有关。

软解码和硬解码:

对H264的视频解码给CPU造成了很大负担,所以手机工程师把这部分工作交给了更善于进行处理简单工作但是数据量较大的GPU。

  • GPU解码就是所谓的硬解码
  • CPU解码就是软解码。
  • iOS提供的播放器类使用的是硬解码,所以视频播放对CPU不会有很大的压力,但是支持的播放格式比较单一,一般就是MP4、MOV、M4V这几个。

HTTP Live Streaming

HLS简介

HTTP Live Streaming(缩写是 HLS)是一个由苹果公司提出的基于HTTP的流媒体网络传输协议。它的工作原理是把整个流分成一个个小的基于HTTP的文件来下载,每次只下载一些。
当媒体流正在播放时,客户端可以选择从许多不同的备用源中以不同的速率下载同样的资源,允许流媒体会话适应不同的数据速率。支持的视频流编码为H.264。我们在视频网站上看到的M3U8后缀的播放链接就是使用HLS协议的视频。

HLS优点
  • 1、看完一段缓存一段,防止只看一段视频但是把整个视频文件都缓存下来的用户,减少服务器压力和节省流量。
  • 2、根据用户网速切换不同的码率,兼顾流程性和清晰度。
HLS支持情况
  • iOS 3.0及之后的版本
  • Android 3.0及之后的版本
  • HTML5。

终端播放格式的选取

  • Android由于3.0之后才支持HLS,所以Android2.3只能用MP4。
  • Android3.0及之后支持HLS。可以用m3u8、mp4格式
  • iOS支持HLS,但不支持flash。可以用m3u8、mp4格式
  • 支持HTML5的浏览器 可以用m3u8。
  • 不支持HTML5的浏览器只能用flash播放swf。

由于以上原因,目前无法实现一个播放地址在所有的平台都通用。

iOS视频播放:

iOS提供MPMoviePlayerController类进行播放,支持流媒体和文件播放。视频内容会渲染到他的View上,可以放在你想放的任何地方,用起来比较方便。这个类设计上不合理的是视频播放状态和视频加载状态都是通过Notification通知的,而不是通过block或者delegate。

iOS视频录制:

同拍照一样视频录制功能有两种实现方式

  • 1、UIImagePickerViewController
  • 2、AVFoundation。

这里只讨论AVFoundation框架,这个框架是苹果提供的底层多媒体框架,用于音视频采集、音视频解码、视频编辑等,多媒体基本上都依赖AVFoundation框架。

视频录制和拍照需要做的工作差不多,主要有以下5步:

  • 1、创建会话AVCaptureSession,用于控制input到output的流向。
  • 2、获取设备AVCaptureDevice,摄像头用于视频采集,话筒用于音频采集。
  • 3、创建输入设备AVCaptureDeviceInput,将设备绑定到input口中,并添加到session上
  • 4、创建输出AVCaptureOutput,可以输出到文件和屏幕上。 AVCaptureMovieFileOutput 输出一个电影文件 AVCaptureVideoDataOutput 输出处理视频帧,用于显示正在录制的视频 AVCaptureAudioDataOutput 输出音频数据
  • 5、音视频合成到一个文件中

iOS对视频实时处理:

如果需要对视频进行实时处理(当然需要否则看不到正在录制的内容),则需要直接对相机缓冲区(camera buffer)中的视频流进行处理。

    • 1、定义一个视频数据输出(AVCaptureVideoDataOutput), 并将其添加到session上。
    • 2、设置接受的controller作为视频数据输出缓冲区(sample buffer)的代理。
    • 3、实现代理方法
      -(void)captureOutput:(AVCaptureOutput )captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection )connection
      当数据缓冲区(data buffer)一有数据时,AVFoundation就调用该方法。在该代理方法中,我们可以获取视频帧、处理视频帧、显示视频帧。实时滤镜就是在这里进行处理的。在这个方法中将缓冲区中的视频数据(就是帧图片)输出到要显示的layer上。

原文地址:http://www.cnblogs.com/LiLihongqiang/p/5875750.html

继续阅读 »

iOS视频开发经验

手机比PC的优势除了便携外,我认为最重要的就是可以快速方便的创作多媒体作品。照片分享,语音输入,视频录制,地理位置。一个成功的手机APP从产品形态上都有这其中的一项或多项,比如instagram,微信。如果把Web2.0的交互体验照搬到手机上就是死路一条。 当智能手机遇上视频就像潘金莲遇上西门庆,各取所需一拍即合,想不发生点事情都难。他们的结晶就是微视频。微视频可以说把手机的视频录制和碎片时间两个特点发挥到了极致,视频相关的APP现在无温不火的原因我认为跟坑爹的运营商有关。虽然现在移动网络流量小速度慢,但是不妨碍我们先把技术积累做起来。

这篇文章主要介绍本人在iOS视频开发中的一点经验。

视频实质:

纯粹的视频(不包括音频)实质上就是一组帧图片,经过视频编码成为视频(video)文件再把音频(audio)文件有些还有字幕文件组装在一起成为我们看到的视频(movie)文件。1秒内出现的图片数就是帧率,图片间隔越小画面就越流畅,所以帧率越高效果就越好,需要的存储空间也就越多。

视频编码:

因为不进行编码的视频数据量非常大,会造成存储和传输上的困难,所以视频文件都需要在录制完成后进行编码。视频编码主要从两个维度压缩数据。

  • 1、单张图像某一区域相邻像素相似,比如一片红色只记录红色色值和区域,不用记录这个区域的每一个像素点。
  • 2、相邻图像之间内容相似,因为相邻两帧要制造连续的效果,所以两帧之间的内容一般非常接近。目前主流的视频编码技术都是用图像编码方法对第一帧进行编码,然后用某种方式描述接下来的帧相对于附近的帧有什么区别。

视频格式:

MP4、MOV、AVI、RMVB这些播放格式其实都是封装格式,除了RMVB比较特殊外,其他格式内封装的视频编码格式都是H264,H264以高压缩率闻名于世,压缩效率比MEPG-2提升一倍多,但是世上没有两全其美的事,H264的解码难度提高了3倍多。

视频码率:

视频文件的大小除以是视频的时长定义为码率。

码率和分辨率跟视频质量的关系:

  • 码率可以理解为取样率,单位时间内取样率越大,精度就越高,同时体积也越大。
  • 当视频没有经过编码时,如果分辨率越高,那么视频图像的细节越清晰。
  • 但如果视频经过编码,被限制在一定码率内,编码器就必须舍弃掉一部分细节。
  • 所以分辨率和码率都同清晰度有关。

软解码和硬解码:

对H264的视频解码给CPU造成了很大负担,所以手机工程师把这部分工作交给了更善于进行处理简单工作但是数据量较大的GPU。

  • GPU解码就是所谓的硬解码
  • CPU解码就是软解码。
  • iOS提供的播放器类使用的是硬解码,所以视频播放对CPU不会有很大的压力,但是支持的播放格式比较单一,一般就是MP4、MOV、M4V这几个。

HTTP Live Streaming

HLS简介

HTTP Live Streaming(缩写是 HLS)是一个由苹果公司提出的基于HTTP的流媒体网络传输协议。它的工作原理是把整个流分成一个个小的基于HTTP的文件来下载,每次只下载一些。
当媒体流正在播放时,客户端可以选择从许多不同的备用源中以不同的速率下载同样的资源,允许流媒体会话适应不同的数据速率。支持的视频流编码为H.264。我们在视频网站上看到的M3U8后缀的播放链接就是使用HLS协议的视频。

HLS优点
  • 1、看完一段缓存一段,防止只看一段视频但是把整个视频文件都缓存下来的用户,减少服务器压力和节省流量。
  • 2、根据用户网速切换不同的码率,兼顾流程性和清晰度。
HLS支持情况
  • iOS 3.0及之后的版本
  • Android 3.0及之后的版本
  • HTML5。

终端播放格式的选取

  • Android由于3.0之后才支持HLS,所以Android2.3只能用MP4。
  • Android3.0及之后支持HLS。可以用m3u8、mp4格式
  • iOS支持HLS,但不支持flash。可以用m3u8、mp4格式
  • 支持HTML5的浏览器 可以用m3u8。
  • 不支持HTML5的浏览器只能用flash播放swf。

由于以上原因,目前无法实现一个播放地址在所有的平台都通用。

iOS视频播放:

iOS提供MPMoviePlayerController类进行播放,支持流媒体和文件播放。视频内容会渲染到他的View上,可以放在你想放的任何地方,用起来比较方便。这个类设计上不合理的是视频播放状态和视频加载状态都是通过Notification通知的,而不是通过block或者delegate。

iOS视频录制:

同拍照一样视频录制功能有两种实现方式

  • 1、UIImagePickerViewController
  • 2、AVFoundation。

这里只讨论AVFoundation框架,这个框架是苹果提供的底层多媒体框架,用于音视频采集、音视频解码、视频编辑等,多媒体基本上都依赖AVFoundation框架。

视频录制和拍照需要做的工作差不多,主要有以下5步:

  • 1、创建会话AVCaptureSession,用于控制input到output的流向。
  • 2、获取设备AVCaptureDevice,摄像头用于视频采集,话筒用于音频采集。
  • 3、创建输入设备AVCaptureDeviceInput,将设备绑定到input口中,并添加到session上
  • 4、创建输出AVCaptureOutput,可以输出到文件和屏幕上。 AVCaptureMovieFileOutput 输出一个电影文件 AVCaptureVideoDataOutput 输出处理视频帧,用于显示正在录制的视频 AVCaptureAudioDataOutput 输出音频数据
  • 5、音视频合成到一个文件中

iOS对视频实时处理:

如果需要对视频进行实时处理(当然需要否则看不到正在录制的内容),则需要直接对相机缓冲区(camera buffer)中的视频流进行处理。

    • 1、定义一个视频数据输出(AVCaptureVideoDataOutput), 并将其添加到session上。
    • 2、设置接受的controller作为视频数据输出缓冲区(sample buffer)的代理。
    • 3、实现代理方法
      -(void)captureOutput:(AVCaptureOutput )captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection )connection
      当数据缓冲区(data buffer)一有数据时,AVFoundation就调用该方法。在该代理方法中,我们可以获取视频帧、处理视频帧、显示视频帧。实时滤镜就是在这里进行处理的。在这个方法中将缓冲区中的视频数据(就是帧图片)输出到要显示的layer上。

原文地址:http://www.cnblogs.com/LiLihongqiang/p/5875750.html

收起阅读 »

HTML5 canvas 模拟事件

我们知道在HTML5中的canvas只是一块画布,画布中的内容并没有相应的dom节点响应我们需要的事件来实现我们和用户的交互。那么我们必须要通过模拟来来触发相应的事件。首先我们必须知道鼠标在canvas上点击的是位置:

1 var offset = offset(canvasDom);
2 canvasDom.onclick = function(e){
3     var eventObj = {x:e.pageX-offset.left,y:e.pageY-offset.top,type:'click'};
4    fire(eventObj);
5 } 

这样我们就知道鼠标相对于画布的偏移了,方便我们触发事件。 当然我们要对我们在画布上画的每一个元素进行精确的定位,以及定义层级关系那样才能更加好的实现局部重绘达到我们的目的。

 

这样的事件模型在相对静止的画布游戏应用中可以起到作用。当然我们可以把他应用到子模块上面。我们在画布上画一个模块然后计算出相对子模块的偏移那么我们就可以相对触发子模块里面节点的事件了。

 

canvas 局部重绘游戏 连连看   http://www.laoshu133.com/soom/llk/index.html  就是使用这种事件机制实现的

原文地址:http://www.cnblogs.com/soom/archive/2012/06/14/2549702.html

继续阅读 »

我们知道在HTML5中的canvas只是一块画布,画布中的内容并没有相应的dom节点响应我们需要的事件来实现我们和用户的交互。那么我们必须要通过模拟来来触发相应的事件。首先我们必须知道鼠标在canvas上点击的是位置:

1 var offset = offset(canvasDom);
2 canvasDom.onclick = function(e){
3     var eventObj = {x:e.pageX-offset.left,y:e.pageY-offset.top,type:'click'};
4    fire(eventObj);
5 } 

这样我们就知道鼠标相对于画布的偏移了,方便我们触发事件。 当然我们要对我们在画布上画的每一个元素进行精确的定位,以及定义层级关系那样才能更加好的实现局部重绘达到我们的目的。

 

这样的事件模型在相对静止的画布游戏应用中可以起到作用。当然我们可以把他应用到子模块上面。我们在画布上画一个模块然后计算出相对子模块的偏移那么我们就可以相对触发子模块里面节点的事件了。

 

canvas 局部重绘游戏 连连看   http://www.laoshu133.com/soom/llk/index.html  就是使用这种事件机制实现的

原文地址:http://www.cnblogs.com/soom/archive/2012/06/14/2549702.html

收起阅读 »