大家好,我是吃饱就睡,不知道想干嘛的蔬菜乌鸦。想熟悉一下blob和canvas这些工作开发中不是特别常用东西。
预览
⛱️一睹为快
思路
- 导入图片,通过blob和FileReader生成img
- 将img全都绘制到canvas中,通过toDataURL,将canvas转成图片
- 通过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>