纯原生实现多张图片合成

本文介绍了如何使用纯JavaScript和Canvas API将多张图片合成为一张图片。作者通过Blob和FileReader将图片转换为img元素,然后将所有img绘制到canvas上,再利用toDataURL方法将canvas转换为图片,并通过a标签进行导出。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

大家好,我是吃饱就睡,不知道想干嘛的蔬菜乌鸦。想熟悉一下blob和canvas这些工作开发中不是特别常用东西。

纯原生实现多张图片合成

预览

图片合成及导出

⛱️一睹为快

思路

  1. 导入图片,通过blob和FileReader生成img
  2. 将img全都绘制到canvas中,通过toDataURL,将canvas转成图片
  3. 通过a标签导出

源码

<!DOCTYPE html>
<html lang="en">

<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>blob</title>
    <style>
        body {
            background-color: #ededed;
            margin: 0;
            padding: 0;
        }
        .app {
            margin: 0 auto;
            width: 60%;
            height: 100vh;
            background-color: #fff;
        }
        .container {
            padding: 10px 0 0;
            display: flex;
            flex-direction: column;
            justify-content: center;
            align-items: center;
        }

        .tool-line {
            width: 100%;
            display: flex;
            justify-content: space-around;
            align-items: center;
            margin-bottom: 8px;
            flex-grow: 1;
        }

        .tool-btn {
            width: 95px;
            height: 30px;
            line-height: 30px;
            outline: none;
            border: none;
            background-color: #cfc2e7;
            text-align: center;
            border-radius: 5px;
        }

        .hidden {
            display: none;
        }
        .show {
            display: block;
        }

        .combinePic {
            font-size: 14px;
        }
        .combinePi:focus {
            background-color: linear-gradient(#cfc2e7, #a28fc5);
        }

        label[for='inputId'] {
            cursor: pointer;
        }

        input {
            margin: 10px auto;
        }

        input[type='file'] {
            display: none;
        }

        input[type='textarea'],
        .renderHtml {
            width: 100%;
            overflow-y: auto;
            display: flex;
            flex-direction: column;
            justify-content: center;
            align-items: center;
        }
        img {
            width: 145px;
            object-fit: cover;
        }

        .canvasContainer {
            width: 100%;
            display: flex;
            justify-content: center;
        }
    </style>
</head>

<body>
    <div class="app">
        <div class="container">
            <div class="tool-line">
                <label class="tool-btn" for="inputId">上传</label>
                <button class="combinePic tool-btn"> 图片合成</button>
                <button class="exportBtn tool-btn hidden">合成导出</button>
            </div>
            <input type="file" name="" id="inputId" />
            <!-- <input type="textarea" id="inputText" /> -->
            <div class="renderHtml"></div>
        </div>
        <div class="canvasContainer"></div>
    </div>
</body>
<script>
    const container = document.querySelector('.container')
    const inputBtn = document.querySelector('#inputId')
    const renderHtml = document.querySelector('.renderHtml')
    const combinePicBtn = document.querySelector('.combinePic')
    const canvasContainer = document.querySelector('.canvasContainer')
    const exportBtn = document.querySelector('.exportBtn')

    var canvas 

    function dealFile(content, fileType) {
        if (fileType === 'image') {
            const img = document.createElement('img')
            img.src = content
            const docFrag = document.createDocumentFragment()
            docFrag.appendChild(img)
            renderHtml.appendChild(docFrag)
        } else if (fileType === 'text') {
            renderHtml.innerText = content
        }
    }

    inputBtn.addEventListener('change', function (e) {
        const files = e.target.files
        const fileReader = new FileReader()
        const fileType = files[0].type.split('/')[0]
        if (fileType === 'image') {
            fileReader.readAsDataURL(files[0])
        } else if (fileType === 'text') {
            fileReader.readAsText(files[0], 'utf-8')
        }
        fileReader.onload = function () {
            var result = fileReader.result
            dealFile(result, fileType)
        }
    })
    

    combinePicBtn.addEventListener('click', function(e) {
        e.preventDefault()
        const imgList = getImageList()
        if (imgList.length === 0) {
            alert(`请先上传图片`)
        }else {
            generateImg()
        }
    })

    exportBtn.addEventListener('click', function(e) {
        e.preventDefault()
        const base64Img = canvas.toDataURL('image/jpeg')
        // console.log(base64Img)
        const dom = document.createElement('a')
        dom.href = base64Img
        dom.setAttribute('download', new Date().getTime() + '.jpeg')
        document.body.appendChild(dom)
        dom.click()
        URL.revokeObjectURL(base64Img)
        document.body.removeChild(dom)
    })

    function getImageList() {
        const imgList = renderHtml.querySelectorAll('img')
        return imgList
    }

    function generateImg (width = 420, height=1000) {
        const imgList = getImageList()
       canvas = document.createElement('canvas')
       let cheight = 250
       canvas.width = container.getBoundingClientRect().width - 30
       canvas.height = imgList.length * cheight + 10
       const ctx = canvas.getContext('2d')
       imgList.forEach((img, index) => {
           ctx.drawImage(img, 0, cheight * index, canvas.width, cheight)
        })
        
        canvasContainer.appendChild(canvas)
        exportBtn.classList.add('show')
    }

</script>

</html>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值