前言

老规矩,首先源代码。图片可点击,和动画开始从点击。

这个效果最初是在3年前完成的,但是当它用无数div标签完成时,性能是一个问题,它不能移动。最近,我想学习一个伟大的神,他在CSS中非常有效。我想从纯粹的CSS学习,但我不能放弃足够的技能,最后选择用帆布完成它。

死的工作

前1。对于某些图片的大小相同,本例大小的图片为1920×1080(注意:这是原始图像大小的大小,而不是页面大小上显示的CSS B)。为了方便使用,请将这些图片添加到HTML中的隐藏元素中。












{。隐藏
显示:无;
}



2。画布是用HTML插入的,其大小是自决定的,但必须与图片资源的宽度和高度之比保持一致。在这种情况下,画布的大小是800×450。


您的浏览器不支持画布。


三.基本代码如下,首先获得画布上下文对象;其次要了解对象;最后,图片由DrawImage方法绘制。


VaR CTX = document.queryselector(' # myCanvas)。GetContext(二维的),
img = document.queryselector('。IMG);

Ctx.beginPath();
Ctx.drawImage(IMG,0, 0);
Ctx.closePath();
Ctx.stroke();



实现

我相信很多人很快就会明白这是几个小单位的结合。每个单位只负责画一小部分的图片。最后,它将成为一幅完整的图画。

所以在解释源代码,让我们在画布上审查的DrawImage函数的用法,因为我们需要使用的函数的9个参数,有更多的参数,我们需要记住这些参数的意义和参考对象。


context.drawimage(IMG,SX,SY,swidth,sheight,X,Y,宽度,高度);


图片:一个图像,画布,或要使用的视频

。SX:开始削减的x坐标

。SY:开始切割的y坐标

。swidth:图像的剪切宽度

sheight:图像的剪切高度

x:将图像的x坐标定位在画布上。

y:将图像的y坐标定位在画布上。

。宽度:要使用的图像的宽度。

高度:要使用的图像的高度

我相信,即使上面列出了这些参数,当开发它们时仍然很容易感到头晕。除了第一IMG参数,参数有8个。前4个参数的大小是原始对象,即1920×1080。4个参数的大小是画布,800×450。

记住这个公式,当实际写不容易晕的时候。

格

网格是建立在一个单元大小的画布上,最重要的是单元的大小可以通过两侧的图片被整除,即单元尺寸应宽屏幕高公约数。公约数不一定是最大公约数和最小公约数太大,因为效果不是太小的Hyun,会有压力的表现。

作为这个例子的800×450大小的例子,我选择25×25作为单位大小,也就是说,整个画布由576个32×18的单元组成,在划分网格之后,我们需要先计算一些基本参数。


bvar imgW = 1920, / / original picture width / height
imgh = 1080;

无功conw = 800, / /画布的宽度/高度
一= 450;

var = 25,单元格宽度高度/画布
DH=25;

var i = CONH / / / DH,单位行/列数
J = conw /数据仓库;

VaR DW = imgw / J /原始细胞宽度/高度
DH = imgh /我;



前三组参数是我们以前设置的。我们需要注意它。当我们计算的行/列在第四组的数量,我们应该清楚:行数=画布的高度/细胞高度;列数=屏幕宽度/单元格的宽度。如果这是错的,后面会被迫的。数据仓库/ DH最后一集是放大转换为原始图的单元格的大小,用于后期的切割图片。

画

一步一步地,我们首先画左上角的单元格,因为原始地图的切割位置和画布的布局都是(0, 0),所以它是最简单的。


Ctx.drawImage(IMG,0, 0,0, 0,DH,DW,DW,DH);



成功u3002so现在画第二行,第三列如何写图片。


var I=2,
j=3;
Ctx.drawImage(IMG,DW *,*我的DH,DW,DW * j,DH,DH *我,DW,DH);


这里很容易混淆:剪裁或放置的横向坐标是单元格的单元格数,纵坐标是单元格的高度*行号。


为了方便起见,封装了一个负责绘制的纯函数,并且它不参与逻辑。它只能根据传入的图片对象和坐标来绘制。


功能handledraw(IMG,i,j){
Ctx.drawImage(IMG,DW *,*我的DH,DW,DW * j,DH,DH *我,DW,DH);
}


封装了渲染方法后,整个图片由行数和列数的双循环绘制。


Ctx.beginPath();

对于(var i = 0;i < i;i + +){
对于(var j=0;j j;j;j + +){
HandleDraw(IMG,I,J);
}
}

Ctx.closePath();
Ctx.stroke();




完美的。事实上,这一步的核心部分已经完成。为什么因为这张照片是由数百个细胞组成的,所以可以想象出来。

在分享自己的动画算法,让你的拼写错误是一样的。


有一些酷。

动画算法

下面让我们分享我的动画算法。演示中的效果是怎样实现的

由于画布网格,每个单元格都有一个i(j),我希望能够给出一个i,j,以获得从近到远的坐标周围所有菱形上的点。


例如,坐标是(3, 3)。

距离1的点分别为(2, 3)、(3, 4)、(4, 3)、4(3, 2)。

距离的点是2(1, 3)、(2, 4)、(3, 5)、(4, 4)、(5, 3)、(4, 2)、(4, 2);

…

这一系列的算法也很容易找到,因为菱形线的点数与坐标的差值和列数与列数之间的距离的绝对值是距离。


功能countaround(i,j,DST){
无功resarr = { };
对于(var = M(i-dst);m(我+DST);M + +){
对于(var = N(j-dst);N(J+DST);N + +){
如果((Math.abs(M-I)+ math.abs(N-J)= = DST){)
ResArr.push({ x:M、Y:n });
}
}
}
返回resarr;
}




该函数用于给定坐标和距离(DST),查找坐标周围的所有点,并以数组的形式返回,但上述算法的边界约束较少,其完成如下:


countaround(i,j,DST){
无功resarr = { };
对于(var = M(i-dst);m(我+DST);M + +){
对于(var = N(j-dst);N(J+DST);N + +){
如果((Math.abs(M-I)+ math.abs(N-J)= DST(M)> = 0 N(M = > = 0)(i-1)n(J-1))){
ResArr.push({ x:M、Y:n });
}
}
}
返回resarr;
}




所以我们有一个纯函数来计算我们周围固定距离上的所有点,然后我们开始完成动画。

首先,我们写一个清除功能,以清除细胞的内容。我们只需要导入坐标来清除坐标单元的内容,然后在等待后绘制新的图案。


handleclear(i,j){
ctx.clearrect(DW *,*我的DH,DW,DH);
}


AnotherImg是下一个画面,最后得出一种新的图像通过setInterval完成破碎作用。


var=0,
intervalobj = setInterval(){()函数(
无功resarr = countaround(I,J,DST);

resarr.foreach(功能(项目、指标){
handleclear(项目。X,Y项目。);
HandleDraw(anotherimg,项目。X,Y项目。);
});

如果(!resarr。长度){
ClearInterval(intervalobj);
}
DST + +;
},20);




当数组的长度countaround返回的是0,即所有点的距离的坐标点以外的边界,和定时器周期停止。在这一点上,所有的核心代码进行了介绍,对源代码的具体实现。

现在,给定画布上的任何坐标,您可以开始从该点展开图片的碎片图片。

在自动旋转木马中,每个从8点预置(四点角和四边)开始动画,坐标为8点如下:


无功randompoint = { {
X:0,
Y:0
{ }。
X:I - 1,
Y:0
{ }。
X:0,
Y - J - 1
{ }。
X:I - 1,
Y - J - 1
{ }。
X:0,
Y:Math.ceil(J / 2)
{ }。
X:I - 1,
Y:Math.ceil(J / 2)
{ }。
X:Math.ceil(我2),
Y:0
{ }。
X:Math.ceil(我2),
Y - J - 1
} }




单击时,计算单击所在位置的单元格坐标,并在该点启动动画。


功能handleclick(e){
无功offsetx = e.offsetx,
offsety = e.offsety,
J = math.floor(offsetx / DW),
我= math.floor(offsety / DH),

与我,j,开始动画…
},




目前,效果只是演示阶段。如果您是免费的,效果将添加到效果中,方便感兴趣的朋友使用。

以上是本文的全部内容,希望能对您有所帮助,希望大家多多支持。