jquery+canvas实现html5幻灯片

发布时间:2013-11-29    发布:cenbel_luoshushi    分类:前端开发

 


 

html5最重要的更新之一:增加了canvas,开始支持矢量绘画,目前浏览器支持比较好的是canvas的2d接口,3d有点遥远,通过canvas,我们可以在web设计中实现很炫的效果,从理论上来讲,大部分的flash动画特效都有办法使用canvas实现,当然实现的成本还是过高了。今天明河向各位讲解个canvas相关的实战教程:jquery+canvas实现html5幻灯片。 关于html5的canvas有个非常经典的教程,你不得不看:来自opera中国的《HTML 5 canvas —— 基本语法》。 canvas内容太丰富了,想要通过一篇文章都讲解到,难免流于浅谈则止,所以这篇教程只让大家了解canvas的drawImage接口。 也许你会疑惑,html早就有插入图片的标签了,在canvas中插入图像有意义吗?明河的回答是:有!canvas的图像是可以实现像素级的操作!

1.原理简述

这篇教程的难点在于切换图片时先提高图片的对比度,然后再予以渐隐(由于使用canvas,请勿在IE下查看demo)。提高图片的对比度用的是photoshop的对比度算法,当然这个算法的细节大家无需纠结,明河只是希望通过这篇教程大家能够大致了解canvas的图像处理方面的技巧。 排除这个对比度处理,其他的jquery代码其实难度不高,明河特意加了翔实的中文注释,只要你有耐心,我相信你一定看的懂。

2.开始构建个用于幻灯片的图片列表

  1. 				<!-- 幻灯片 START -->
  2.     <div id="slideshow">
  3.         <ul class="slides">
  4.             <li><img src="img/photos/1.jpg" width="620" height="320" alt="照片1" /></li>
  5.             <li><img src="img/photos/2.jpg" width="620" height="320" alt="照片2" /></li>
  6.             <li><img src="img/photos/3.jpg" width="620" height="320" alt="照片3" /></li>
  7.             <li><img src="img/photos/4.jpg" width="620" height="320" alt="照片4" /></li>
  8.         </ul>
  9.         <span class="arrow previous"></span>
  10.         <span class="arrow next"></span>
  11.     </div>
  12.     <!-- 幻灯片 END -->

非常简单的结构,除了图片列表外,当然还免不了上一张、下一张的箭头。样式不是本文的重点,这里略过。

3.在页面加载结束后加载初始化幻灯片

  1. $(window).load(function(){})

这里可能朋友们有疑惑:为啥不用$(function(){}),不是更简单? 之所以使用$(window).load()而不使用更简洁的$(),是因为我们需要确保图片全部加载完成,而不是DOM加载完成,还有个原因canvas还是很耗资源的。

4.判断浏览器是否支持canvas

  1. //测试浏览器是否支持canvas
  2.     var supportCanvas = 'getContext' in document.createElement('canvas');

这一步很重要哦,当用户的浏览器不支持canvas,我们需要另外一种降级处理。

5.遍历每张图片

  1. //遍历每张图片
  2.             $('#slideshow img').each(function(){
  3.                 //第一张图片时先设置下幻灯片的宽高(将图片的宽高缓存起来,供其他代码调用)
  4.                 if(!slideshow.width){
  5.                     slideshow.width = this.width;
  6.                     slideshow.height = this.height;
  7.                 }
  8.                 //在图片之前产生canvas
  9.                 createCanvasOverlay(this);
  10.             });

这里有二步操作:

  • 将图片尺寸写入缓存变量slideshow,供日后调用
  • 执行createCanvasOverlay()函数,插入canvas

6.创造canvas对像

  1. /**
  2.      * 创造canvas对像
  3.       * @param {Object} image 图片
  4.      */
  5.     function createCanvasOverlay(image){
  6.         //创建canvas元素
  7.         var canvas            = document.createElement('canvas'),
  8.             //获取2d canvas上下文(如果不支持canvas,这个对象是不存在的)
  9.             canvasContext    = canvas.getContext("2d");
  10.        
  11.         // 设置canvas的宽度和高度
  12.         canvas.width = slideshow.width;
  13.         canvas.height = slideshow.height;
  14.         //在canvas内绘制一张图片
  15.         canvasContext.drawImage(image,0,0);
  16.         //获取canvas图片像素数据,这非常重要
  17.         var imageData    = canvasContext.getImageData(0,0,canvas.width,canvas.height),
  18.             data        = imageData.data;
  19.        
  20.         // Loop through all the pixels in the imageData array, and modify
  21.         // the red, green, and blue color values.
  22.         //遍历所有的像素并修改红色、绿色、蓝色通道的值,这是整个教程中最难的部分,如果没理解没关系,但希望通过这一个操作,让各位直观的感受canvas像素级操作的强大
  23.         for(var i = 0,z=data.length;i<z;i++){
  24.             data[i] = ((data[i] < 128) ? (2*data[i]*data[i] / 255) : (255 - 2 * (255 - data[i]) * (255 - data[i]) / 255));
  25.             data[++i] = ((data[i] < 128) ? (2*data[i]*data[i] / 255) : (255 - 2 * (255 - data[i]) * (255 - data[i]) /255));
  26.             data[++i] = ((data[i] < 128) ? (2*data[i]*data[i] / 255) : (255 - 2 * (255 - data[i]) * (255 - data[i]) /255));
  27.             //为了更好的说明,这里明河加入颜色反转效果,可以把上面的代码去掉,换成下面的试下
  28.             /*data[i] = 255 - data[i];
  29.             data[++i] = 255 - data[++i];
  30.             data[++i] = 255 - data[++i];*/
  31.             ++i;
  32.         }
  33.        
  34.         //重新应用下像素数据,后面二个参数是x\y坐标值
  35.         canvasContext.putImageData(imageData,0,0);
  36.         //将canvas插入到图片前面
  37.         image.parentNode.insertBefore(canvas,image);
  38.     }

这是教程代码的关键部分。我们一步一步来看。

1)创建个canvas元素
  1. //创建canvas元素
  2.                 var canvas            = document.createElement('canvas'),
  3.                 //获取2d canvas上下文(如果不支持canvas,这个对象是不存在的)
  4.             canvasContext    = canvas.getContext("2d");
  5.        
  6.         // 设置canvas的宽度和高度
  7.         canvas.width = slideshow.width;
  8.         canvas.height = slideshow.height;

设置canvas的尺寸等于图片尺寸,正好遮住图片,当切换图片时,先出现canvas(canvas的图片是修改过的高对比度的图片)。最后我们输出的节点如下: 想要使用canvas的API,请先获取2d canvas上下文,这非常重要,所有基于canvas的操作都基于getContext(“2d”)

2)向canvas内插入图片
  1. //在canvas内绘制一张图片
  2.         canvasContext.drawImage(image,0,0);

严重推荐阅读:http://kb.operachina.com/node/190#insertingimages。 drawImage方法允许在 canvas 中插入图像,共有九个参数(恐怖吧…常用的是前面三个):

  1. 图片对象
  2. x轴坐标
  3. y轴坐标
  4. 图像宽度
  5. 图像高度

之前说过,在canvas中插入图像的优势,在于可以实现像素级的操作,比如这里我们要加强图像的对比度。

3)获取canvas图片像素数据
  1. //获取canvas图片像素数据,这非常重要
  2.         var imageData    = canvasContext.getImageData(0,0,canvas.width,canvas.height),
  3.             data        = imageData.data;

getImageData方法,将获取canvas图片像素数据,此对象有个data数组,用于存放像素数据。getImageData共有四个参数:x坐标、y坐标、宽度、高度。

4)强化图像对比度

这段代码有点复杂,特别是对比度强化处理

  1. //遍历所有的像素并修改红色、绿色、蓝色通道的值,这是整个教程中最难的部分,如果没理解没关系,但希望通过这一个操作,让各位直观的感受canvas像素级操作的强大
  2.         for(var i = 0,z=data.length;i<z;i++){
  3.             data[i] = ((data[i] < 128) ? (2*data[i]*data[i] / 255) : (255 - 2 * (255 - data[i]) * (255 - data[i]) / 255));
  4.             data[++i] = ((data[i] < 128) ? (2*data[i]*data[i] / 255) : (255 - 2 * (255 - data[i]) * (255 - data[i]) /255));
  5.             data[++i] = ((data[i] < 128) ? (2*data[i]*data[i] / 255) : (255 - 2 * (255 - data[i]) * (255 - data[i]) /255));
  6.             ++i;
  7.         }

来着photoshop强化对比度的算法,如果这个算法没弄明白,没关系,只要记得有这样的用法即可。简单说明下原理:强化对比度,实际是处理红(data[i])、绿(data[i+1])、蓝(data[i+2])三个通道数据,大部分对图像像素数据,更准确的将应该是矩阵的处理,实际上都是对三个通道的处理。 说真的,这个算法内部细节的含义,明河也不清楚,欢迎讨论。

5)重新输出图像像素
  1. //重新应用下像素数据,后面二个参数是x\y坐标值
  2.        canvasContext.putImageData(imageData,0,0);
6)将canvas插入到DOM中
  1. //将canvas插入到图片前面
  2.         image.parentNode.insertBefore(canvas,image);

7.监听箭头切换幻灯片事件

  1. $('#slideshow .arrow').click(function(){
  2.             var li            = slides.eq(current),
  3.             canvas        = li.find('canvas'),
  4.             nextIndex    = 0;
  5.  
  6.             //下一张
  7.             if($(this).hasClass('next')){
  8.                 nextIndex = current >= slides.length-1 ? 0 : current+1;
  9.             }
  10.             //上一张
  11.             else {
  12.                 nextIndex = current <= 0 ? slides.length-1 : current-1;
  13.             }
  14.  
  15.             var next = slides.eq(nextIndex);
  16.             //支持canvas的情况
  17.             if(supportCanvas){
  18.                                 //渐现canvas
  19.                 canvas.fadeIn(function(){
  20.                     //显示下个容器
  21.                     next.show();
  22.                     current = nextIndex;
  23.                     //隐藏当前图片容器,并移除激活样式,给新出现的图片容器加上激活样式
  24.                     li.fadeOut(function(){
  25.                         li.removeClass('slideActive');
  26.                         canvas.hide();
  27.                         next.addClass('slideActive');
  28.                     });
  29.                 });
  30.             }
  31.             else {
  32.                 //如果浏览器不支持canvas只做简单的显隐处理
  33.                 current=nextIndex;
  34.                 next.addClass('slideActive').show();
  35.                 li.removeClass('slideActive').hide();
  36.             }
  37.         });

这代码相当简单多了。这里有个推荐学习的技巧,将next和prev方法合并,其实不管是next还是prev方法执行的动作都是类似的,我们根据按钮是否带有“next”样式来判断是上一张还是下一张。

  1. //下一张
  2.             if($(this).hasClass('next')){
  3.                 nextIndex = current >= slides.length-1 ? 0 : current+1;
  4.             }
  5.                         //上一张
  6.             else {
  7.                 nextIndex = current <= 0 ? slides.length-1 : current-1;
  8.             }

8.轮播幻灯片

轮播幻灯片,实际上是定时触发next(下一张箭头)的click事件。

  1. var timeOut = null;
  2.  
  3.     $('#slideshow .arrow').click(function(e,simulated){
  4.         //点击箭头,清除定时器
  5.         if(!simulated){
  6.             clearTimeout(timeOut);
  7.         }
  8.     });
  9.  
  10.     (function autoAdvance(){
  11.                 //触发箭头点击事件,当第二个参数为false时,清理定时器
  12.         $('#slideshow .next').trigger('click',[true]);
  13.         //5秒定时轮放
  14.         timeOut = setTimeout(autoAdvance,5000);
  15.     })();

代码请看autoadvance.js。这里有个很有意思的jquery技巧,触发事件,并给事件传递自定义参数。

  1. $('#slideshow .arrow').click(function(e,simulated){
  2.  
  3.     });
  4. $('#slideshow .next').trigger('click',[true]);

trigger接受第二个参数,并且是数组类型,分别对应事件方法的第二至N个参数,比如这里的true对应simulated,事件内部根据simulated值做相应的处理。html5最重要的更新之一:增加了canvas,开始支持矢量绘画,目前浏览器支持比较好的是canvas的2d接口,3d有点遥远,通过canvas,我们可以在web设计中实现很炫的效果,从理论上来讲,大部分的flash动画特效都有办法使用canvas实现,当然实现的成本还是过高了。今天明河向各位讲解个canvas相关的实战教程:jquery+canvas实现html5幻灯片。

关于html5的canvas有个非常经典的教程,你不得不看:来自opera中国的《HTML 5 canvas —— 基本语法》。 canvas内容太丰富了,想要通过一篇文章都讲解到,难免流于浅谈则止,所以这篇教程只让大家了解canvas的drawImage接口。 也许你会疑惑,html早就有插入图片的标签了,在canvas中插入图像有意义吗?明河的回答是:有!canvas的图像是可以实现像素级的操作!

1.原理简述

这篇教程的难点在于切换图片时先提高图片的对比度,然后再予以渐隐(由于使用canvas,请勿在IE下查看demo)。提高图片的对比度用的是photoshop的对比度算法,当然这个算法的细节大家无需纠结,明河只是希望通过这篇教程大家能够大致了解canvas的图像处理方面的技巧。 排除这个对比度处理,其他的jquery代码其实难度不高,明河特意加了翔实的中文注释,只要你有耐心,我相信你一定看的懂。

2.开始构建个用于幻灯片的图片列表

  1. <!-- 幻灯片 START -->
  2.     <div id="slideshow">
  3.         <ul class="slides">
  4.             <li><img src="img/photos/1.jpg" width="620" height="320" alt="照片1" /></li>
  5.             <li><img src="img/photos/2.jpg" width="620" height="320" alt="照片2" /></li>
  6.             <li><img src="img/photos/3.jpg" width="620" height="320" alt="照片3" /></li>
  7.             <li><img src="img/photos/4.jpg" width="620" height="320" alt="照片4" /></li>
  8.         </ul>
  9.         <span class="arrow previous"></span>
  10.         <span class="arrow next"></span>
  11.     </div>
  12.     <!-- 幻灯片 END -->

非常简单的结构,除了图片列表外,当然还免不了上一张、下一张的箭头。样式不是本文的重点,这里略过。

3.在页面加载结束后加载初始化幻灯片

  1. $(window).load(function(){})

这里可能朋友们有疑惑:为啥不用$(function(){}),不是更简单? 之所以使用$(window).load()而不使用更简洁的$(),是因为我们需要确保图片全部加载完成,而不是DOM加载完成,还有个原因canvas还是很耗资源的。

4.判断浏览器是否支持canvas

  1. //测试浏览器是否支持canvas
  2.     var supportCanvas = 'getContext' in document.createElement('canvas');

这一步很重要哦,当用户的浏览器不支持canvas,我们需要另外一种降级处理。

5.遍历每张图片

  1. //遍历每张图片
  2.             $('#slideshow img').each(function(){
  3.                 //第一张图片时先设置下幻灯片的宽高(将图片的宽高缓存起来,供其他代码调用)
  4.                 if(!slideshow.width){
  5.                     slideshow.width = this.width;
  6.                     slideshow.height = this.height;
  7.                 }
  8.                 //在图片之前产生canvas
  9.                 createCanvasOverlay(this);
  10.             });

这里有二步操作:

  • 将图片尺寸写入缓存变量slideshow,供日后调用
  • 执行createCanvasOverlay()函数,插入canvas

6.创造canvas对像

  1. /**
  2.      * 创造canvas对像
  3.       * @param {Object} image 图片
  4.      */
  5.     function createCanvasOverlay(image){
  6.         //创建canvas元素
  7.         var canvas            = document.createElement('canvas'),
  8.             //获取2d canvas上下文(如果不支持canvas,这个对象是不存在的)
  9.             canvasContext    = canvas.getContext("2d");
  10.        
  11.         // 设置canvas的宽度和高度
  12.         canvas.width = slideshow.width;
  13.         canvas.height = slideshow.height;
  14.         //在canvas内绘制一张图片
  15.         canvasContext.drawImage(image,0,0);
  16.         //获取canvas图片像素数据,这非常重要
  17.         var imageData    = canvasContext.getImageData(0,0,canvas.width,canvas.height),
  18.             data        = imageData.data;
  19.        
  20.         // Loop through all the pixels in the imageData array, and modify
  21.         // the red, green, and blue color values.
  22.         //遍历所有的像素并修改红色、绿色、蓝色通道的值,这是整个教程中最难的部分,如果没理解没关系,但希望通过这一个操作,让各位直观的感受canvas像素级操作的强大
  23.         for(var i = 0,z=data.length;i<z;i++){
  24.             data[i] = ((data[i] < 128) ? (2*data[i]*data[i] / 255) : (255 - 2 * (255 - data[i]) * (255 - data[i]) / 255));
  25.             data[++i] = ((data[i] < 128) ? (2*data[i]*data[i] / 255) : (255 - 2 * (255 - data[i]) * (255 - data[i]) /255));
  26.             data[++i] = ((data[i] < 128) ? (2*data[i]*data[i] / 255) : (255 - 2 * (255 - data[i]) * (255 - data[i]) /255));
  27.             //为了更好的说明,这里明河加入颜色反转效果,可以把上面的代码去掉,换成下面的试下
  28.             /*data[i] = 255 - data[i];
  29.             data[++i] = 255 - data[++i];
  30.             data[++i] = 255 - data[++i];*/
  31.             ++i;
  32.         }
  33.        
  34.         //重新应用下像素数据,后面二个参数是x\y坐标值
  35.         canvasContext.putImageData(imageData,0,0);
  36.         //将canvas插入到图片前面
  37.         image.parentNode.insertBefore(canvas,image);
  38.     }

这是教程代码的关键部分。我们一步一步来看。

1)创建个canvas元素
  1. //创建canvas元素
  2.                 var canvas            = document.createElement('canvas'),
  3.                 //获取2d canvas上下文(如果不支持canvas,这个对象是不存在的)
  4.             canvasContext    = canvas.getContext("2d");
  5.        
  6.         // 设置canvas的宽度和高度
  7.         canvas.width = slideshow.width;
  8.         canvas.height = slideshow.height;

设置canvas的尺寸等于图片尺寸,正好遮住图片,当切换图片时,先出现canvas(canvas的图片是修改过的高对比度的图片)。最后我们输出的节点如下: 想要使用canvas的API,请先获取2d canvas上下文,这非常重要,所有基于canvas的操作都基于getContext(“2d”)

2)向canvas内插入图片
  1. //在canvas内绘制一张图片
  2.         canvasContext.drawImage(image,0,0);

严重推荐阅读:http://kb.operachina.com/node/190#insertingimages。 drawImage方法允许在 canvas 中插入图像,共有九个参数(恐怖吧…常用的是前面三个):

  1. 图片对象
  2. x轴坐标
  3. y轴坐标
  4. 图像宽度
  5. 图像高度

之前说过,在canvas中插入图像的优势,在于可以实现像素级的操作,比如这里我们要加强图像的对比度。

3)获取canvas图片像素数据
  1. //获取canvas图片像素数据,这非常重要
  2.         var imageData    = canvasContext.getImageData(0,0,canvas.width,canvas.height),
  3.             data        = imageData.data;

getImageData方法,将获取canvas图片像素数据,此对象有个data数组,用于存放像素数据。getImageData共有四个参数:x坐标、y坐标、宽度、高度。

4)强化图像对比度

这段代码有点复杂,特别是对比度强化处理

  1. //遍历所有的像素并修改红色、绿色、蓝色通道的值,这是整个教程中最难的部分,如果没理解没关系,但希望通过这一个操作,让各位直观的感受canvas像素级操作的强大
  2.         for(var i = 0,z=data.length;i<z;i++){
  3.             data[i] = ((data[i] < 128) ? (2*data[i]*data[i] / 255) : (255 - 2 * (255 - data[i]) * (255 - data[i]) / 255));
  4.             data[++i] = ((data[i] < 128) ? (2*data[i]*data[i] / 255) : (255 - 2 * (255 - data[i]) * (255 - data[i]) /255));
  5.             data[++i] = ((data[i] < 128) ? (2*data[i]*data[i] / 255) : (255 - 2 * (255 - data[i]) * (255 - data[i]) /255));
  6.             ++i;
  7.         }

来着photoshop强化对比度的算法,如果这个算法没弄明白,没关系,只要记得有这样的用法即可。简单说明下原理:强化对比度,实际是处理红(data[i])、绿(data[i+1])、蓝(data[i+2])三个通道数据,大部分对图像像素数据,更准确的将应该是矩阵的处理,实际上都是对三个通道的处理。 说真的,这个算法内部细节的含义,明河也不清楚,欢迎讨论。

5)重新输出图像像素
  1. //重新应用下像素数据,后面二个参数是x\y坐标值
  2.        canvasContext.putImageData(imageData,0,0);
6)将canvas插入到DOM中
  1. //将canvas插入到图片前面
  2.         image.parentNode.insertBefore(canvas,image);

7.监听箭头切换幻灯片事件

  1. $('#slideshow .arrow').click(function(){
  2.             var li            = slides.eq(current),
  3.             canvas        = li.find('canvas'),
  4.             nextIndex    = 0;
  5.  
  6.             //下一张
  7.             if($(this).hasClass('next')){
  8.                 nextIndex = current >= slides.length-1 ? 0 : current+1;
  9.             }
  10.             //上一张
  11.             else {
  12.                 nextIndex = current <= 0 ? slides.length-1 : current-1;
  13.             }
  14.  
  15.             var next = slides.eq(nextIndex);
  16.             //支持canvas的情况
  17.             if(supportCanvas){
  18.                                 //渐现canvas
  19.                 canvas.fadeIn(function(){
  20.                     //显示下个容器
  21.                     next.show();
  22.                     current = nextIndex;
  23.                     //隐藏当前图片容器,并移除激活样式,给新出现的图片容器加上激活样式
  24.                     li.fadeOut(function(){
  25.                         li.removeClass('slideActive');
  26.                         canvas.hide();
  27.                         next.addClass('slideActive');
  28.                     });
  29.                 });
  30.             }
  31.             else {
  32.                 //如果浏览器不支持canvas只做简单的显隐处理
  33.                 current=nextIndex;
  34.                 next.addClass('slideActive').show();
  35.                 li.removeClass('slideActive').hide();
  36.             }
  37.         });

这代码相当简单多了。这里有个推荐学习的技巧,将next和prev方法合并,其实不管是next还是prev方法执行的动作都是类似的,我们根据按钮是否带有“next”样式来判断是上一张还是下一张。

  1. //下一张
  2.             if($(this).hasClass('next')){
  3.                 nextIndex = current >= slides.length-1 ? 0 : current+1;
  4.             }
  5.                         //上一张
  6.             else {
  7.                 nextIndex = current <= 0 ? slides.length-1 : current-1;
  8.             }

8.轮播幻灯片

轮播幻灯片,实际上是定时触发next(下一张箭头)的click事件。

  1. var timeOut = null;
  2.  
  3.     $('#slideshow .arrow').click(function(e,simulated){
  4.         //点击箭头,清除定时器
  5.         if(!simulated){
  6.             clearTimeout(timeOut);
  7.         }
  8.     });
  9.  
  10.     (function autoAdvance(){
  11.                 //触发箭头点击事件,当第二个参数为false时,清理定时器
  12.         $('#slideshow .next').trigger('click',[true]);
  13.         //5秒定时轮放
  14.         timeOut = setTimeout(autoAdvance,5000);
  15.     })();

代码请看autoadvance.js。这里有个很有意思的jquery技巧,触发事件,并给事件传递自定义参数。

  1. $('#slideshow .arrow').click(function(e,simulated){
  2.  
  3.     });
  4. $('#slideshow .next').trigger('click',[true]);

trigger接受第二个参数,并且是数组类型,分别对应事件方法的第二至N个参数,比如这里的true对应simulated,事件内部根据simulated值做相应的处理。

查看 [2633]   评论 [0] 
相关标签: 网页设计 
文章评论
暂无数据!
我来说两句
昵 称:
评 论:
   
咨询电话:020-61136292 87569708 61004412 61004413
讯博官网 | 走进讯博 | 整合营销 | 案例解读 | 资讯中心 | 案例欣赏 | 产品体验区 | 客户如是说 | 联系我们
版权所有 © 2003-2014 广州讯博网络科技有限公司 粤ICP备08107356号 开心一刻
Website Design & Power by:Cenbel.com