liuhongdi@lhdpc:/data/vue/touch$ npm list html2canvas
touch@0.1.0 /data/vue/touch
└── html2canvas@1.4.1
说明:刘宏缔的架构森林是一个专注架构的博客,
网站:
https://blog.imgtouch.com
原文:
https://blog.imgtouch.com/index.php/2023/06/03/vue-js3-yong-html2canvas-ba-html-zhuan-canvas-tu-pian/
对应的源码可以访问这里获取:
https://github.com/liuhongdi/
或:
https://gitee.com/liuhongdi
说明:作者:刘宏缔 邮箱: 371125307@qq.com
二,js代码:
<template>
<div style="width:800px;margin: auto;display: flex;flex-direction: column;">
<div>请选择上传图片:
<input type="file" id="back" ref="backfile" accept="image/*" @change="handleFile" /></div>
<div id="imgContainer" style="position: relative;margin-left:150px;margin-top:10px;width:500px;height:500px;overflow: hidden;background: lightgray;" >
<div id="imgDiv">
<img id="img" :src="imgSrc" style="" />
<div id="text"
:style="{
width:'600px',
height:'200px',
position: 'absolute',
left:'50px',
top:'50px',
width: '300px',
height: 'auto',
fontSize:fontSizeValue+'px',
color:colorValue,
fontStyle:styleValue,
fontWeight:weightValue,
opacity:opacityValue,
textAlign:alignValue }">这是一个可编辑的信息,测试思源的字体文件</div>
</div>
</div>
字号: <el-input-number
v-model="fontSizeValue"
class="mx-4"
:min="10"
:max="100"
controls-position="right"
@change="fontSizeChange"
/><br/>
颜色:<el-color-picker v-model="colorValue" @active-change="setColor" /><br/>
<span>透明度:</span><el-slider v-model="opacityDispValue" :min="0" :max="100" @input="setOpacity" style="width:300px;" /><br/>
<button @click="weight">加粗</button>
<button @click="style">斜体</button>
</div>
<div id="dpiBtn" style="display: none;">
<input type="button" value="保存图片" @click="makeCanvas" />
</div>
</div>
</div>
</template>
<script>
import {ref} from "vue";
import html2canvas from "html2canvas"
export default {
name: "ImageText",
setup() {
//图片的原宽高
const imgWidth = ref(0);
const imgHeight = ref(0);
//图片内容
const imgSrc = ref("");
//选中的图片文件
const imgFile = ref();
//选中图片后的处理
const handleFile = () => {
let filePaths = window.event.target.files;
//清空原有缩略图
if (filePaths.length === 0) {
//未选择,则返回
return
//把新选中的图片加入数组
imgFile.value = filePaths[0];
imgSrc.value = URL.createObjectURL(imgFile.value);
let reader = new FileReader();
reader.readAsDataURL(imgFile.value);
reader.onload = () =>{
//显示图片
imgSrc.value = reader.result;
//得到宽高
let img = new Image();
img.src= reader.result;
img.onload = () => {
//保存宽高
imgWidth.value = img.width;
imgHeight.value = img.height;
if (img.width >= img.height) {
let rate = 500 / img.width;
let left = (500-img.width) / 2;
let top = (500 -img.height) / 2;
let styleStr = 'display:block;width:100%;height:100%;';
document.getElementById('img').style = styleStr;
let styleDivStr = 'width:'+img.width+'px;height:'+img.height+'px;transform:scale('+rate+');left:'+left+'px;display: block;top:'+top+'px;';
document.getElementById('imgDiv').style = styleDivStr;
} else {
let rate = 500 / img.height;
let left = (500-img.width) / 2;
let top = (500 -img.height) / 2;
let styleStr = 'display: inline-block;width:100%;height:100%;';
document.getElementById('img').style = styleStr;
let styleDivStr = 'width:'+img.width+'px;height:'+img.height+'px;transform:scale('+rate+');left:'+left+'px;display: block;top:'+top+'px;';
document.getElementById('imgDiv').style = styleDivStr;
document.getElementById('dpiBtn').style.display="";
//对齐
const alignValue = ref("left");
//倾斜
const styleValue = ref("normal");
const style = () => {
if (styleValue.value == 'normal') {
styleValue.value ='italic'
} else {
styleValue.value ='normal'
//加粗
const weightValue = ref("normal");
const weight = () => {
if (weightValue.value == 'normal') {
weightValue.value ='bold'
} else {
weightValue.value ='normal'
//透明度
const opacityValue = ref(1);
const opacityDispValue = ref(100);
const setOpacity = (value) => {
opacityValue.value = value / 100;
//颜色
const colorValue = ref("#2c3e50");
const setColor = (value) => {
colorValue.value = value;
//字号
const fontSizeValue = ref(38);
const fontSizeChange = (value) =>{
fontSizeValue.value = value;
//把编辑的文字部分保存成图片
const makeCanvas = () => {
html2canvas(document.getElementById('text'),{
onclone: function(documentClone){
documentClone.getElementById('imgDiv').style.transform = 'scale(1)';
}).then(function(canvas){
downPngByCanvas(canvas);
//下载图片
const downPngByCanvas = (canvas) => {
var oA = document.createElement("a");
let time = timeFormat();
oA.download = "img_"+time+'.png';// 设置下载的文件名,默认是'下载'
oA.href = canvas.toDataURL("image/png").replace('image/png', 'image/octet-stream');
document.body.appendChild(oA);
oA.click();
oA.remove(); // 下载之后把创建的元素删除
//补0
const add0 = (m) => {
return m<10?'0'+m:m
//格式化时间
const timeFormat = ()=>{
var time = new Date();
var y = time.getFullYear();
var m = time.getMonth()+1;
var d = time.getDate();
var h = time.getHours();
var mm = time.getMinutes();
var s = time.getSeconds();
let res = y+add0(m)+add0(d)+add0(h)+add0(mm)+add0(s);
return res;
return {
imgSrc,
handleFile,
alignValue,
style,
styleValue,
weight,
weightValue,
opacityValue,
opacityDispValue,
setOpacity,
colorValue,
setColor,
fontSizeValue,
fontSizeChange,
makeCanvas,
</script>
<style scoped>
</style>
三,测试效果:
转canvas后:
四,查看vue框架的版本:
root@lhdpc:/data/vue/imgtouch# npm list vue
imgtouch@0.1.0 /data/vue/imgtouch
├─┬ @vue/cli-plugin-babel@5.0.6
│ └─┬ @vue/babel-preset-app@5.0.6
│ └── vue@3.2.37 deduped
└─┬ vue@3.2.37
└─┬ @vue/server-renderer@3.2.37
└── vue@3.2.37 deduped