前言:
最近看到一个有趣的视频,一张狗的图片,横着切割后,交叉排列,就变成两只狗了。再竖着切割,就变成了4只狗。这个东西很有趣,所以我就准备来自己实现编程一下这个东西。
演示
照片无限分裂1?
设计
这里我使用canvas来实现这个功能,通过初始化的时候加载一张图片。然后对图片进行横向切割(x轴切割),例如间隔20像素进行切割。切割下来的左边10像素和右边10像素就是两个图片。每次进行这样的切割操作,左边的按照顺序放在一起,右边的也同样。这样进行一次x轴的切割后就会看到图像被切分成了两份,当时整体上变得窄了。然后再上面的方式,从y轴方向进行切割,就会看到图像变成了4份(图像整体的大小是不变的)。这里就这样简单介绍一下了,因为本身也很简单,不过我实现的时候对这个canvas的用法不太熟悉,走了一些弯路。建议先看一下视频,我在B站上传了2个视频,看完视频再看代码,或者自己直接运行一下代码试一试。
注意:这个代码是不能直接打开在浏览器预览的,因为canvas的drawImage不允许跨域操作图片。所以建议使用vscode的 live server 或者其它IDE开启一个静态服务器,通过ip+port的形式访问。如果你想更加简洁一些,那么推荐你:python3 -m http.server
。
实现
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>dog2dogs</title>
</head>
<body>
<div style="border: 1px solid red">
<canvas id="cs" height="600" width="1000"></canvas>
</div>
<button id="load" onclick="load()">加载</button>
<button id="x_split" onclick="x_split()">横切</button>
<button id="y_split" onclick="y_split()">纵切</button>
<script>
let flag = false; // 初始是未加载
let cs = document.getElementById("cs");
let ctx = cs.getContext("2d");
let img = new Image();
let size = 2; // 分隔的像素间隔,最小是2.
let r = {}; // 图片缩放后的宽高属性对象
img.setAttribute("src", "002.jpg");
img.onload = () => {
flag = true; // 设置状态为已经加载
r = resize(img.width, img.height, cs.height)
}
// 绘制原始图像
function load() {
if (!flag) {
alert("图片未加载!")
}
ctx.drawImage(img, 0, 0, r.w, r.h);
}
function x_split() {
img_x_split(cs, ctx, r, size);
// 获取右边横向分割的图片
let t_img_data = ctx.getImageData(cs.width/2, 0, r.w, r.h);
// 清除canvas
ctx.clearRect(0, 0, cs.width, cs.height);
// 重新绘制横向分割的图片
ctx.putImageData(t_img_data, 0, 0)
}
function y_split() {
// 对横向切割图片进行纵向分割
img_y_split(cs, ctx, r, size);
}
function img_x_split(cs, ctx, r, size) {
for (let i = 0; i < r.w; i=i+size) {
let left_img_data = ctx.getImageData(i, 0, size/2, r.h);
let right_img_data = ctx.getImageData(i+size/2, 0, size/2, r.h)
ctx.putImageData(left_img_data, cs.width/2+i/2, 0);
ctx.putImageData(right_img_data, cs.width/2+r.w/2+i/2, 0)
}
}
function img_y_split(cs, ctx, r, size) {
for (let i = 0; i < r.h; i=i+size) {
let up_img_data = ctx.getImageData(0, i, r.w, size/2);
let down_img_data = ctx.getImageData(0, i+size/2, r.w, size/2)
ctx.putImageData(up_img_data, cs.width/2, i/2);
ctx.putImageData(down_img_data, cs.width/2, r.h/2+i/2)
}
}
/*
图片的resize函数,用来计算缩放图片,
返回缩放后的宽高
param: w 图片的宽
h 图片的高
ch 画板的高
*/
function resize(w, h, ch) {
w = w/h * ch;
h = ch;
return {
w: w,
h: h
}
}
</script>
</body>
</html>