小言_互联网的博客

基于canvas的手风琴特效

402人阅读  评论(0)

引言:手风琴特效是比较常见的,我之前没有见过用canvas写的,就自己上手写了一个,拿出来分享一下,这其中处理图片的切换花了我不少时间。

效果如下

实现思路

1.排放好图片,最前面的那张图片显示全部,其他图片放到两侧只显示20像素的边,剩余部分依次摆放放到画布外。

2.绘制几个相对应的方形,每个方形大小跟对应的图片显示在画布中的大小一样,这些方形用来控制鼠标的移入事件。

3.鼠标移入以后,切换图片,执行手风琴特效。

绘制图片

分二次处理是为了让展示的图片处于数组的后面,不会被遮盖。


  
  1. //绘制选项图片
  2. Accordion.prototype.drawImage=function(){
  3. var image,img,rect,x= 0,sx= 0,sy= 0,sWidth= 600,sHeight= 360,dx= 0,dy= 0,dWidth= 600,dHeight= 360,w= this.dis,width= 0,color;
  4. var curr= this.currImgIndex,imageWidth = this.imageWidth;
  5. var n = curr -1;
  6. //分二次处理是为了让展示的图片处于数组的后面,不会被遮盖
  7. for(var i=curr;i>= 1;i--){
  8. if(i==curr){
  9. dx = n*w;
  10. } else{
  11. dx = (i -1)*w-imageWidth+w;
  12. }
  13. image = this.imgObj[i];
  14. img = new _.ImageDraw({ image:image, sx:sx, sy:sy, sWidth:sWidth, sHeight:sHeight, dx:dx, dy:dy , dWidth:dWidth, dHeight:dHeight});
  15. img.id=i;
  16. this.renderArr.push(img);
  17. this.imgArr.unshift(img); //这里用unshift 保证顺序
  18. }
  19. for(var i=curr+ 1;i<= this.count;i++){
  20. dx = (i -1)*w+ this.imageWidth-w;
  21. image = this.imgObj[i];
  22. img = new _.ImageDraw({ image:image, sx:sx, sy:sy, sWidth:sWidth, sHeight:sHeight, dx:dx, dy:dy , dWidth:dWidth, dHeight:dHeight});
  23. img.id=i;
  24. this.renderArr.push(img);
  25. this.imgArr.push(img);
  26. }
  27. }

此时效果

加入方形

依次摆放好就行,显示的那张图片宽度取到图片的宽度一样为600.


  
  1. //创建几个方形和图片一一对应,用来处理鼠标移入的动作
  2. for( var i= 1;i<= this.count;i++){
  3. x=(i- 1)*w;
  4. if(i>curr){
  5. x+= sWidth-w;
  6. }
  7. if(i==curr){
  8. width=sWidth;
  9. } else{
  10. width= 20;
  11. }
  12. color=_.getRandomColor();
  13. rect = new _.Rect({
  14. x:x,
  15. y: 0,
  16. width:width,
  17. height:sHeight,
  18. stroke: true,
  19. strokeStyle:color
  20. })
  21. if(i==curr){
  22. rect.curr= true; //当前展示图片
  23. }
  24. rect.index=i; //方形索引-对应图片下标
  25. this.renderArr.push(rect);
  26. this.rectArr.push(rect);
  27. }

效果如下:

此时绘制的几个方形显示在图片上面了,需要修改绘制顺序,让方形先生成即可。


  
  1. //绘制选项图片
  2. Accordion.prototype.drawImage=function(){
  3. var image,img,rect,x= 0,sx= 0,sy= 0,sWidth= 600,sHeight= 360,dx= 0,dy= 0,dWidth= 600,dHeight= 360,w= this.dis,width= 0,color;
  4. var curr= this.currImgIndex,imageWidth = this.imageWidth;
  5. var n = curr -1;
  6. //创建几个方形和图片一一对应,用来处理鼠标移入的动作
  7. for(var i= 1;i<= this.count;i++){
  8. x=(i -1)*w;
  9. if(i>curr){
  10. x+= sWidth-w;
  11. }
  12. if(i==curr){
  13. width=sWidth;
  14. } else{
  15. width= 20;
  16. }
  17. color=_.getRandomColor();
  18. rect = new _.Rect({
  19. x:x,
  20. y: 0,
  21. width:width,
  22. height:sHeight,
  23. stroke: true,
  24. strokeStyle:color
  25. })
  26. if(i==curr){
  27. rect.curr= true; //当前展示图片
  28. }
  29. rect.index=i; //方形索引-对应图片下标
  30. this.renderArr.push(rect);
  31. this.rectArr.push(rect);
  32. }
  33. //分二次处理是为了让展示的图片处于数组的后面,不会被遮盖
  34. for(var i=curr;i>= 1;i--){
  35. if(i==curr){
  36. dx = n*w;
  37. } else{
  38. dx = (i -1)*w-imageWidth+w;
  39. }
  40. image = this.imgObj[i];
  41. img = new _.ImageDraw({ image:image, sx:sx, sy:sy, sWidth:sWidth, sHeight:sHeight, dx:dx, dy:dy , dWidth:dWidth, dHeight:dHeight});
  42. img.id=i;
  43. this.renderArr.push(img);
  44. this.imgArr.unshift(img); //这里用unshift 保证顺序
  45. }
  46. for(var i=curr+ 1;i<= this.count;i++){
  47. dx = (i -1)*w+ this.imageWidth-w;
  48. image = this.imgObj[i];
  49. img = new _.ImageDraw({ image:image, sx:sx, sy:sy, sWidth:sWidth, sHeight:sHeight, dx:dx, dy:dy , dWidth:dWidth, dHeight:dHeight});
  50. img.id=i;
  51. this.renderArr.push(img);
  52. this.imgArr.push(img);
  53. }
  54. }

加入鼠标移入事件

  1. 鼠标移入后,鼠标的坐标处于哪个方形范围内,那对应的图片就要显示出来;
  2. 根据当前选择的方形与之前显示的图片位置比较,可以确定图片的运动方形(向左边 or 向右),以及需要运动图片对象。
  3. 开启定时任务,来执行这些图片的运动,运动的时候要重新排序,处理好图片与图片的遮蔽关系,不然会出现被其他图片遮罩的效果,我在这里也费了不少时间去处理。
  4. 在已经显示的图片上移动鼠标和图片正在做运动的时候,是不会再次触发定时任务的。
  5. 运动完成后,清除定时任务,重新设定相关参数即可!

鼠标移入事件


  
  1. //鼠标移动事件
  2. Accordion.prototype.mouseMove=function(e){
  3. var that= this,catchIndex= 0,currFlag= false,item;
  4. if(that.catchFlag) return; //如果处理捕获状态,直接返回
  5. var pos = _.getOffset(e); //获取鼠标位置
  6. for( var i= 0;i<that.rectArr.length;i++){
  7. item = that.rectArr[i];
  8. if(item.isPoint(pos)){
  9. if(that.currImgIndex==item.index){ //当前显示的图片上移动,无效处理
  10. currFlag= true;
  11. } else{ //需要执行图片手风琴效果
  12. catchIndex = item.index;
  13. that.catchFlag= true;
  14. currFlag= false;
  15. }
  16. break;
  17. }
  18. }
  19. if(!catchIndex || currFlag) return;
  20. that.move(catchIndex);
  21. }

图片移动的逻辑处理函数


  
  1. //图片移动的逻辑处理函数
  2. Accordion.prototype.move= function(index){
  3. var curr= this.currImgIndex,total= 0;;
  4. var moveArr=[],dir= 1;
  5. _.each( this.rectArr, function(item){
  6. if(index<curr){ //判断好往左还是往右,设定dir
  7. if(item.index>=index && item.index<=curr){ //往右移动
  8. moveArr.push(item);
  9. }
  10. } else{
  11. if(item.index>=curr && item.index<=index){ //往左移动
  12. moveArr.push(item);
  13. dir= -1;
  14. }
  15. }
  16. })
  17. //执行排序
  18. this.sort(index,dir);
  19. //开启定时任务
  20. var timmer = setInterval(doMove.bind( this), 20);
  21. //执行移动的函数
  22. function doMove(){
  23. var that= this,dis= 10*dir;
  24. if(total>= 580){ //移动到位后
  25. clearInterval(timmer); //清除定时器
  26. timmer= null;
  27. that.catchFlag= false; //更改捕获状态
  28. that.currImgIndex=index; //设定当前显示图的下标
  29. _.each(moveArr, function(item){ //设置flag为false
  30. item.flag= false;
  31. })
  32. return;
  33. }
  34. _.each(moveArr, function(item){
  35. if(dir> 0){
  36. //对方形控制的处理
  37. if(item.index==index){
  38. item.width+=dis;
  39. } else {
  40. if(item.index==curr){
  41. item.width+=-dis;
  42. }
  43. item.x+=dis;
  44. }
  45. if(item.index<curr && item.index!=index){
  46. if(!item.flag){ //表示图要先向右移动580,因为处于最左边
  47. that.imgArr[item.index -1].dx+= 580;
  48. item.flag= true;
  49. }
  50. }
  51. //对图片移动处理
  52. that.imgArr[item.index -1].dx+=dis;
  53. } else{
  54. //对方形控制的处理
  55. if(item.index==curr){
  56. item.width+=dis;
  57. } else {
  58. if(item.index==index){
  59. item.width+=-dis;
  60. }
  61. item.x+=dis;
  62. }
  63. if(item.index>curr && item.index!=index){
  64. if(!item.flag){ //表示图要先向做移动580,因为处于最右边,超过了画布的范围
  65. that.imgArr[item.index -1].dx+= -580;
  66. item.flag= true;
  67. }
  68. }
  69. //对图片移动处理
  70. that.imgArr[item.index -1].dx+=dis;
  71. }
  72. })
  73. total+= 10; //不管往左往右total都是递增
  74. that.render();
  75. }
  76. }

排序函数


  
  1. //排好序,否则图片会相互遮盖
  2. Accordion.prototype.sort=function(index,dir){
  3. var arr= this.renderArr;
  4. var n= 6;
  5. if(dir< 0){ //向左移动
  6. //左边的图放到数组前面
  7. for( var i=index- 1;i>= 1;i--){
  8. arr[n++] = this.imgArr[i- 1];
  9. }
  10. //当前显示的图片放在中间
  11. arr[n++]= this.imgArr[index- 1];
  12. //右边的图放到数组后面
  13. for( var i=index+ 1;i<= this.count;i++){
  14. arr[n++] = this.imgArr[i- 1];
  15. }
  16. } else{ //向右移动
  17. //右边的图放到数组前面
  18. for( var i=index+ 1;i<= this.count;i++){
  19. arr[n++] = this.imgArr[i- 1];
  20. }
  21. //当前显示的图片放在中间
  22. arr[n++]= this.imgArr[index- 1];
  23. //左边的图放到数组后面
  24. for( var i=index- 1;i>= 1;i--){
  25. arr[n++] = this.imgArr[i- 1];
  26. }
  27. }
  28. }

最终效果就跟文章开头的一样。

 

源码下载

方式1:少量积分,下载代码

方式2:关注下方公众号,回复 126 下载代码

更多源码

♥ 抖音很火的华为太空人表盘(附源码)

♥ 基于JavaScript页面动态验证码(附源码)

♥ 基于JavaScript的拖动滑块拼图验证(附源码)

♥ 基于JavaScript的幸运大转盘(附源码)

♥ 抖音很火的罗盘时钟(附源码)

♥ 基于JavaScript的俄罗斯方块小游戏(附源码)

♥ 基于JavaScript的贪吃蛇游戏(附源码)

♥ 基于JavaScript的拼图游戏(附源码)

♥ 用JavaScript给女儿做的烟花特效(附源码)

♥ 老父亲给女儿做的下雪特效,满足女儿看雪的愿望(附源码)

♥ 雷达扫描特效(附源码)

♥ 香港黄金配角吴孟达去世,80后程序员以轮播图来悼念达叔,达叔一路走好!(附源码)

♥ 仿抖音刷新进度条(附源码)

♥ 仿头条方形刷新进度条(附源码)

♥ 仿360加速球、水波评分特效(附源码)

♥ 基于canvas的刮刮卡(附源码)

♥ 原生js写的左侧飞入拼图特效,你是喜欢美女单飞还是双飞(附源码)

♥ 用js写的旋转木马,在新年献给各位刚登基的皇帝,让你的后宫转起来!程序员就是可以为所欲为!(附源码)

♥ 用js写的轮播图,八位女明星,你翻谁的牌,程序员就是可以为所欲为!(附源码)

♥ 原生js实现美女拼图,把美女老婆抱回家,5个美女够不够!程序员就是可以为所欲为!(附源码)

♥ 用js仿探探拖拽卡片的效果、飞卡片的效果,感觉挺酷,最后有美女看哦!(附源码)

♥ 老婆说程序员不懂浪漫,程序员默默拿起了键盘,这就亲手带你去看流星雨,女人真的会影响男人拔刀的速度!(附源码)

♥ 学生成绩管理系统(jsp+jquery+java+mysql+tomcat)有源码,你的毕设我的心(附源码)


转载:https://blog.csdn.net/dkm123456/article/details/115529446
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场