当前位置:主页 > 查看内容

基于canvas的手风琴特效

发布时间:2021-05-20 00:00| 位朋友查看

简介:引言手风琴特效是比较常见的我之前没有见过用canvas写的就自己上手写了一个拿出来分享一下这其中处理图片的切换花了我不少时间。 效果如下 实现思路 1.排放好图片最前面的那张图片显示全部其他图片放到两侧只显示20像素的边剩余部分依次摆放放到画布外。 2.……

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

效果如下

实现思路

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

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

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

绘制图片

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

//绘制选项图片
	Accordion.prototype.drawImage=function(){
		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;
		var curr=this.currImgIndex,imageWidth = this.imageWidth;
		var n = curr-1;
		
		//分二次处理是为了让展示的图片处于数组的后面,不会被遮盖
		for(var i=curr;i>=1;i--){
			if(i==curr){
				dx = n*w;
			}else{
				dx = (i-1)*w-imageWidth+w;
			}
			
			image = this.imgObj[i];
			img = new _.ImageDraw({image:image,sx:sx,sy:sy,sWidth:sWidth,sHeight:sHeight, dx:dx, dy:dy ,dWidth:dWidth,dHeight:dHeight});
			img.id=i;
			this.renderArr.push(img);
			this.imgArr.unshift(img);//这里用unshift 保证顺序
		}
		
		for(var i=curr+1;i<=this.count;i++){
			dx = (i-1)*w+this.imageWidth-w;
			image = this.imgObj[i];
			img = new _.ImageDraw({image:image,sx:sx,sy:sy,sWidth:sWidth,sHeight:sHeight, dx:dx, dy:dy ,dWidth:dWidth,dHeight:dHeight});
			img.id=i;
			this.renderArr.push(img);
			this.imgArr.push(img);
		}
		
	
	}

此时效果

加入方形

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

//创建几个方形和图片一一对应,用来处理鼠标移入的动作
		for(var i=1;i<=this.count;i++){
			x=(i-1)*w;
			if(i>curr){
				x+= sWidth-w;
			}
			if(i==curr){
				width=sWidth;
			}else{
				width=20;
			}
			color=_.getRandomColor();
			rect = new _.Rect({
				x:x,
				y:0,
				width:width,
				height:sHeight,
				stroke:true,
				strokeStyle:color
			})
			if(i==curr){
				rect.curr=true;//当前展示图片
			}
			rect.index=i;//方形索引-对应图片下标
			
			this.renderArr.push(rect);
			this.rectArr.push(rect);
		}

效果如下:

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

//绘制选项图片
	Accordion.prototype.drawImage=function(){
		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;
		var curr=this.currImgIndex,imageWidth = this.imageWidth;
		var n = curr-1;
		//创建几个方形和图片一一对应,用来处理鼠标移入的动作
		for(var i=1;i<=this.count;i++){
			x=(i-1)*w;
			if(i>curr){
				x+= sWidth-w;
			}
			if(i==curr){
				width=sWidth;
			}else{
				width=20;
			}
			color=_.getRandomColor();
			rect = new _.Rect({
				x:x,
				y:0,
				width:width,
				height:sHeight,
				stroke:true,
				strokeStyle:color
			})
			if(i==curr){
				rect.curr=true;//当前展示图片
			}
			rect.index=i;//方形索引-对应图片下标
			
			this.renderArr.push(rect);
			this.rectArr.push(rect);
		}
		//分二次处理是为了让展示的图片处于数组的后面,不会被遮盖
		for(var i=curr;i>=1;i--){
			if(i==curr){
				dx = n*w;
			}else{
				dx = (i-1)*w-imageWidth+w;
			}
			
			image = this.imgObj[i];
			img = new _.ImageDraw({image:image,sx:sx,sy:sy,sWidth:sWidth,sHeight:sHeight, dx:dx, dy:dy ,dWidth:dWidth,dHeight:dHeight});
			img.id=i;
			this.renderArr.push(img);
			this.imgArr.unshift(img);//这里用unshift 保证顺序
		}
		
		for(var i=curr+1;i<=this.count;i++){
			dx = (i-1)*w+this.imageWidth-w;
			image = this.imgObj[i];
			img = new _.ImageDraw({image:image,sx:sx,sy:sy,sWidth:sWidth,sHeight:sHeight, dx:dx, dy:dy ,dWidth:dWidth,dHeight:dHeight});
			img.id=i;
			this.renderArr.push(img);
			this.imgArr.push(img);
		}
		
	}

加入鼠标移入事件

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

鼠标移入事件

//鼠标移动事件
	Accordion.prototype.mouseMove=function(e){
		var that=this,catchIndex=0,currFlag=false,item;
		if(that.catchFlag) return;//如果处理捕获状态,直接返回
		var pos = _.getOffset(e);//获取鼠标位置
		for(var i=0;i<that.rectArr.length;i++){
			item = that.rectArr[i];
			if(item.isPoint(pos)){
				if(that.currImgIndex==item.index){//当前显示的图片上移动,无效处理
					currFlag=true;
				}else{//需要执行图片手风琴效果
					catchIndex = item.index;
					that.catchFlag=true;
					currFlag=false;
				}
				break;
			}
		}
		if(!catchIndex || currFlag) return;
		
		that.move(catchIndex);
	}

图片移动的逻辑处理函数

//图片移动的逻辑处理函数	
	Accordion.prototype.move=function(index){
		var curr=this.currImgIndex,total=0;;
		var moveArr=[],dir=1;
		_.each(this.rectArr,function(item){
			if(index<curr){//判断好往左还是往右,设定dir
				if(item.index>=index && item.index<=curr){//往右移动
					moveArr.push(item);
				}
			}else{
				if(item.index>=curr && item.index<=index){//往左移动
					moveArr.push(item);
					dir=-1;
				}
			}
		})	
		//执行排序
		this.sort(index,dir);
		//开启定时任务
		var timmer = setInterval(doMove.bind(this),20);
		//执行移动的函数		
		function doMove(){
			var that=this,dis=10*dir;
			if(total>=580){//移动到位后
				clearInterval(timmer);//清除定时器
				timmer=null;
				that.catchFlag=false;//更改捕获状态
				that.currImgIndex=index;//设定当前显示图的下标
				_.each(moveArr,function(item){//设置flag为false
					item.flag=false;
				})
				return;
			}
		
			_.each(moveArr,function(item){
				if(dir>0){
					//对方形控制的处理
					if(item.index==index){
						item.width+=dis;
					}else {
						if(item.index==curr){
							item.width+=-dis;
						}
						item.x+=dis;
					}
					if(item.index<curr && item.index!=index){
						if(!item.flag){//表示图要先向右移动580,因为处于最左边
							that.imgArr[item.index-1].dx+=580;
							item.flag=true;
						}
					}
					//对图片移动处理
					that.imgArr[item.index-1].dx+=dis;
				}else{
					//对方形控制的处理
					if(item.index==curr){
						item.width+=dis;
					}else {
						if(item.index==index){
							item.width+=-dis;
						}
						item.x+=dis;
					}
					
					if(item.index>curr && item.index!=index){
						if(!item.flag){//表示图要先向做移动580,因为处于最右边,超过了画布的范围
							that.imgArr[item.index-1].dx+=-580;
							item.flag=true;
						}
					}
					//对图片移动处理
					that.imgArr[item.index-1].dx+=dis;
				}
			})
			total+=10;	//不管往左往右total都是递增
			that.render();
		}
	}

排序函数

//排好序,否则图片会相互遮盖
	Accordion.prototype.sort=function(index,dir){
		var arr=this.renderArr;
		var n=6;
		if(dir<0){//向左移动
			//左边的图放到数组前面
			for(var i=index-1;i>=1;i--){
				arr[n++] = this.imgArr[i-1];
			}
			//当前显示的图片放在中间
			arr[n++]=this.imgArr[index-1];
			//右边的图放到数组后面
			for(var i=index+1;i<=this.count;i++){
				arr[n++] = this.imgArr[i-1];
			}
		}else{//向右移动
			//右边的图放到数组前面
			for(var i=index+1;i<=this.count;i++){
				arr[n++] = this.imgArr[i-1];
			}
			//当前显示的图片放在中间
			arr[n++]=this.imgArr[index-1];
			//左边的图放到数组后面
			for(var i=index-1;i>=1;i--){
				arr[n++] = this.imgArr[i-1];
			}
		}
	
		
	}

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

?

源码下载

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

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

;原文链接:https://blog.csdn.net/dkm123456/article/details/115529446
本站部分内容转载于网络,版权归原作者所有,转载之目的在于传播更多优秀技术内容,如有侵权请联系QQ/微信:153890879删除,谢谢!

推荐图文


随机推荐