最近看到一个用canvas实现给图片加水印的文章,学习了之后做了个把多张图片拼成长图的功能。
需要了解的知识点:
步骤是:
- 用
<input type="file">
来选择本地文件 - 用
FileReader
的readAsDataURL
来拿到作为图片src
的dataURL
- 把图片实例化,然后画在
canvas
中 - 用
HTMLCanvasElement.toDataURL()
拿到拼好的图的dataURL
完整代码如下。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>拼长图</title>
</head>
<body>
<input id="upload-input" type="file" accept="image/*" multiple="multiple" style="display: none;">
<label for="upload-input">点击选择图片</label>
<div id="image-container"></div>
<script>
// 拼出来的图片的宽度
const width = 300
// 拼出来的图片的质量,0-1之间,越大质量越好
const encoderOptions = 0.5
const uploadInput = document.getElementById('upload-input')
const imageDiv = document.getElementById('image-container')
uploadInput.addEventListener('change', event => {
const files = Array.from(event.target.files)
filesToInstances(files, instances => {
drawImages(instances, finalImageUrl => {
imageDiv.innerHTML = `<div><a download href=${finalImageUrl}>点击下载</a><br><img src=${finalImageUrl}></div>`
})
})
})
// 根据图片文件拿到图片实例
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
image.onload = () => {
// 图片实例化成功后存起来
instances[index] = image
finished ++
if (finished === length) {
callback(instances)
}
}
}
})
}
// 拼图
const drawImages = (images, callback) => {
const heights = images.map(item => width / item.width * item.height)
const canvas = document.createElement('canvas')
canvas.width = width
canvas.height = heights.reduce((total, current) => total + current)
const context = canvas.getContext('2d')
let y = 0
images.forEach((item, index) => {
const height = heights[index]
context.drawImage(item, 0, y, width, height)
y += height
})
callback(canvas.toDataURL('image/jpeg', encoderOptions))
}
</script>
</body>
</html>
还有许多别的canvas
处理图片的应用场景,感兴趣的可以自行搜索。
完。