canvas把多张图片拼成长图

最近看到一个用canvas实现给图片加水印的文章,学习了之后做了个把多张图片拼成长图的功能。


需要了解的知识点:

  1. Data URLs
  2. FileReader
  3. HTMLCanvasElement.toDataURL()

步骤是:

  1. <input type="file">来选择本地文件
  2. FileReaderreadAsDataURL来拿到作为图片srcdataURL
  3. 把图片实例化,然后画在canvas
  4. 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处理图片的应用场景,感兴趣的可以自行搜索。

完。

相关推荐