引言:手风琴特效是比较常见的,我之前没有见过用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);
-
}
-
-
}
加入鼠标移入事件
- 鼠标移入后,鼠标的坐标处于哪个方形范围内,那对应的图片就要显示出来;
- 根据当前选择的方形与之前显示的图片位置比较,可以确定图片的运动方形(向左边 or 向右),以及需要运动图片对象。
- 开启定时任务,来执行这些图片的运动,运动的时候要重新排序,处理好图片与图片的遮蔽关系,不然会出现被其他图片遮罩的效果,我在这里也费了不少时间去处理。
- 在已经显示的图片上移动鼠标和图片正在做运动的时候,是不会再次触发定时任务的。
- 运动完成后,清除定时任务,重新设定相关参数即可!
鼠标移入事件
-
//鼠标移动事件
-
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 下载代码
★ 更多源码
♥ 老父亲给女儿做的下雪特效,满足女儿看雪的愿望(附源码)♥
♥ 雷达扫描特效(附源码)♥
♥ 香港黄金配角吴孟达去世,80后程序员以轮播图来悼念达叔,达叔一路走好!(附源码)♥
♥ 原生js写的左侧飞入拼图特效,你是喜欢美女单飞还是双飞(附源码)♥
♥ 用js写的旋转木马,在新年献给各位刚登基的皇帝,让你的后宫转起来!程序员就是可以为所欲为!(附源码)♥
♥ 用js写的轮播图,八位女明星,你翻谁的牌,程序员就是可以为所欲为!(附源码)♥
♥ 原生js实现美女拼图,把美女老婆抱回家,5个美女够不够!程序员就是可以为所欲为!(附源码)♥
♥ 用js仿探探拖拽卡片的效果、飞卡片的效果,感觉挺酷,最后有美女看哦!(附源码)♥
♥ 老婆说程序员不懂浪漫,程序员默默拿起了键盘,这就亲手带你去看流星雨,女人真的会影响男人拔刀的速度!(附源码)♥
♥ 学生成绩管理系统(jsp+jquery+java+mysql+tomcat)有源码,你的毕设我的心(附源码)♥
转载:https://blog.csdn.net/dkm123456/article/details/115529446