js和canvas实现多张图片拼接成一张图片

选择多张图片从上到下排列合成一张图片

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>拼长图</title>
</head>

<body>
<input id="uploadInput" type="file" accept="image/*" multiple="multiple" style="display: none;">
<label for="uploadInput" style="border: 1px solid #333; cursor: pointer; padding: 5px 20px;">
点击选择图片
</label>

<div id="imageBox"></div>

<script src="https://cdn.bootcss.com/jquery/1.11.3/jquery.min.js"></script>
<script>
// 拼出来的图片的宽度
const width = 300;
// 拼出来的图片的质量,0-1之间,越大质量越好
const encoderOptions = 0.5;
// 图片选择输入框
const uploadInput = document.getElementById('uploadInput');
// 图片展示框
const imageBox = document.getElementById('imageBox');

// 给图片选择输入框添加change监听事件
uploadInput.addEventListener('change', event => {
const files = Array.from(event.target.files); // 将图片文件对象转换为数组

filesToInstances(files, instances => {
drawImages(instances, finalImageUrl => {
imageBox.innerHTML = `<img src=${finalImageUrl}><a download href=${finalImageUrl}>点击下载</a>`;
});
});
});

/**
* 根据图片文件拿到图片实例
* @param files 图片文件对象数组
* @param callback
*/
const filesToInstances = (files, callback) => {
const length = files.length; // 文件个数
let instances = []; // 文件实例数组
let finished = 0; // 转换成功个数

// 遍历图片文件数组
files.forEach((file, index) => {
const reader = new FileReader();
// 把文件读为 dataUrl
reader.readAsDataURL(file);
reader.onload = e => {
const image = new Image();
image.src = e.target.result; // 获取图片文件的base64数据
// 解决跨域
// image.setAttribute('crossOrigin', 'anonymous');
// image.src = e.target.result + '?time=' + new Date().valueOf();
image.onload = () => {
// 图片实例化成功后存起来
instances[index] = image;
finished++;
if (finished === length) { // 如果全部完成转换,调用回调函数
callback(instances);
}
}
}
});
}

/**
* 拼图
* @param images 图片实例数组
* @param callback
*/
const drawImages = (images, callback) => {
const heights = images.map(item => width / item.width * item.height); // 计算获取每个图片文件根据指定width后的高度
const canvas = document.createElement('canvas'); // 创建canvas元素
canvas.width = width; // canvas宽度
canvas.height = heights.reduce((total, current) => total + current); // 计算heights数组元素相加后的总和为canvas的高度
const context = canvas.getContext('2d'); // 创建渲染
let y = 0; // canvas Y轴坐标

// 遍历图片实例数组
images.forEach((item, index) => {
const height = heights[index];
context.drawImage(item, 0, y, width, height);
y += height; // Y轴坐标加上上一张图片高度
});

// canvas数据放到回调函数
callback(canvas.toDataURL('image/jpeg', encoderOptions));
}
</script>
</body>

</html>

注意:如果是在线上运行,可能要处理图片跨域的问题

解决方法:

image.src = e.target.result;改为以下代码即可。
image.setAttribute('crossOrigin', 'anonymous');
image.src = e.target.result + '?time=' + new Date().valueOf();

提供图片数组路径将图片从上往下排列合成一张图片

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>拼长图</title>
</head>

<body>
<label id="uploadInput" style="border: 1px solid #333; cursor: pointer; padding: 5px 20px;">
点击选择图片
</label>

<div id="imageBox"></div>

<script src="https://cdn.bootcss.com/jquery/1.11.3/jquery.min.js"></script>
<script>
const files = ['img/icon1.jpg', 'img/icon2.jpg', 'img/icon3.jpg']; // 提供图片数组路径
// 拼出来的图片的宽度
const width = 300;
// 拼出来的图片的质量,0-1之间,越大质量越好
const encoderOptions = 0.5;
// 图片选择输入框
const uploadInput = document.getElementById('uploadInput');
// 图片展示框
const imageBox = document.getElementById('imageBox');

// 给图片选择输入框添加click监听事件
uploadInput.addEventListener('click', event => {
filesToInstances(files, instances => {
drawImages(instances, finalImageUrl => {
imageBox.innerHTML = `<img src=${finalImageUrl}><a download href=${finalImageUrl}>点击下载</a>`;
});
});
});

/**
* 根据图片路径拿到图片实例
* @param files 图片路径数组
* @param callback
*/
const filesToInstances = (files, callback) => {
const length = files.length; // 图片路径个数
let instances = []; // 文件实例数组
let finished = 0; // 转换成功个数

// 遍历图片路径数组
files.forEach((file, index) => {
const image = new Image();
image.src = file; // 赋值图片路径
image.onload = () => {
// 图片实例化成功后存起来
instances[index] = image;
finished++;
if (finished === length) { // 如果全部完成转换,调用回调函数
callback(instances);
}
}
});
}

/**
* 拼图
* @param images 图片实例数组
* @param callback
*/
const drawImages = (images, callback) => {
const heights = images.map(item => width / item.width * item.height); // 计算获取每个图片文件根据指定width后的高度
const canvas = document.createElement('canvas'); // 创建canvas元素
canvas.width = width; // canvas宽度
canvas.height = heights.reduce((total, current) => total + current); // 计算heights数组元素相加后的总和为canvas的高度
const context = canvas.getContext('2d'); // 创建渲染
let y = 0; // canvas Y轴坐标

// 遍历图片实例数组
images.forEach((item, index) => {
const height = heights[index];
context.drawImage(item, 0, y, width, height);
y += height; // Y轴坐标加上上一张图片高度
});

// canvas数据放到回调函数
callback(canvas.toDataURL('image/jpeg', encoderOptions));
}
</script>
</body>

</html>

注意:和上面一样,在线上时也需要解决图片跨域问题

坚持原创技术分享,您的支持将鼓励我继续创作!
0%