文章目录
- 环境
- 实现
- 效果
- 代码
环境
安装html2canvas,用于将指定标签下的全部子节点转换为图片
npm install html2canvas
实现
<template>
<div class="handwrite">
<div id="left" class="left">
<div id="backImg" class="backImg" :style="{ backgroundImage: `url(${defaultImgUrl})` }">
<div id="textContent" class="textContent">
</div>
</div>
</div>
<div class="right">
<el-input type="textarea" :autosize="{minRows: 20, maxRows: 20 }" resize="none" v-model="text"></el-input>
<div class="setting">
<el-row>
<el-col :span="12"> <label>颜色: </label> <input type="number" v-model="R" min="0" max="255"> <input type="number" v-model="G" min="0" max="255"> <input type="number" v-model="B" min="0" max="255"> </el-col>
<el-col :span="12"> <label>默认背景: </label>
<el-radio-group v-model="defaultImgUrl">
<el-radio :label="item.value" v-for="(item,index) in defaultImgOptions" :key="index">{{item.label}}</el-radio>
</el-radio-group>
</el-col>
</el-row>
<br>
<el-row>
<el-col :span="12"> <label>字体: </label>
<!-- <input id="fontFile" type="file" name="fontFile" accept=".ttf,.tff" @change="" />-->
<el-radio-group v-model="fontType">
<el-radio :label="item.value" v-for="(item,index) in fontOptions" :key="index">{{item.label}}</el-radio>
</el-radio-group>
</el-col>
<el-col :span="12"> <label>背景图: </label> <input id="imgFile" type="file" name="imgFile" accept="image/png, image/jpeg, image/jpg" @change="selectImg" /> </el-col>
</el-row>
<br>
<el-row>
<el-col :span="8"> <label>字体水平间距: </label> <input type="number" v-model="level" min="-10" max="50"></el-col>
<el-col :span="8"> <label>字体竖直间距: </label> <input type="number" v-model="vertical" min="10" max="50"> </el-col>
<el-col :span="8"> <label>字体大小: </label> <input type="number" v-model="size" min="-10" max="50"> </el-col>
</el-row>
<br>
<el-row>
<el-col :span="6"> <label>左间距: </label> <input type="number" v-model="leftPitch" min="0" max="30"></el-col>
<el-col :span="6"> <label>右间距: </label> <input type="number" v-model="rightPitch" min="0" max="30"> </el-col>
<el-col :span="6"> <label>上间距: </label> <input type="number" v-model="topPitch" min="0" max="30"> </el-col>
<el-col :span="6"> <label>下间距: </label> <input type="number" v-model="bottomPitch" min="0" max="30"> </el-col>
</el-row>
<br>
<el-row>
<el-col :span="6"> <label>文字旋转角度: </label> <input type="number" v-model="rotaAngle" min="-90" max="90"></el-col>
<el-col :span="6"> <label>背景旋转角度: </label> <input type="number" v-model="backRotaAngle" min="-90" max="90"></el-col>
</el-row>
<br>
<el-row>
<el-button @click="exportImg" style="margin-left: 80%">导出图片</el-button>
</el-row>
</div>
</div>
</div>
</template>
<script >
import html2canvas from "html2canvas";
export default {
name: "handwrite",
data() {
return {
text: "",
R: 0,
G: 0,
B: 0,
defaultImgUrl: require('@/assets/handwrite/a4.jpg'),
backImgUrl: "",
level: 0,
vertical: 10,
size: 15,
leftPitch: 0,
rightPitch: 0,
topPitch: 0,
bottomPitch: 0,
rotaAngle: 0,
backRotaAngle: 0,
defaultImgOptions: [
{
label: "A4",
value: require('@/assets/handwrite/a4.jpg'),
},
{
label: "A4-横线(红)",
value: require('@/assets/handwrite/a4-line.jpg'),
},
{
label: "A4-横线(黑)",
value: require('@/assets/handwrite/a4-line-black.jpg'),
},
{
label: "牛皮纸",
value: require('@/assets/handwrite/niupi.jpeg'),
},
{
label: "信签纸",
value: require('@/assets/handwrite/xz.jpeg'),
},
],
fontType: "caoshu",
fontOptions: [
{
label: "字体1",
value: "XingKai",
},
{
label: "字体2",
value: "caoshu",
},
{
label: "字体3",
value: "XingShu",
},
]
}
},
computed: {},
mounted() {
},
watch: {
//文本
text(){
var textArry = this.text.split("") || [];
if(this.isEmpty(textArry) || textArry.length <= 0){
return ;
}
let textContent = document.getElementById("textContent");
while(textContent.hasChildNodes()) //当div下还存在子节点时 循环继续
{
textContent.removeChild(textContent.firstChild);
}
let number = 0;
textArry.forEach((item) => {
var span = document.createElement("span");
if(" " == item || ' ' == item ){
item = " ";
}
if("\n" == item ){
item = "<br>";
}
span.innerHTML = item;
if(this.size >=15 ){
span.style.fontSize = Math.floor(Math.random() * (this.size - (this.size-3) + 1)) + (this.size-3)+"px";
}
span.style.transform = "rotate("+(Math.floor(Math.random() * (5 - (-5) + 1)) + (-5))+"deg)";
if(number%5 == 0){
span.style.marginLeft = (Math.floor(Math.random() * (3 - (0) + 1)) + (0)) + "px";
}
if(number%3 == 0){
span.style.marginLeft = (Math.floor(Math.random() * (3 - (0) + 1)) + (0)) + "px";
}
if(number%9 == 0){
span.style.marginLeft = (Math.floor(Math.random() * (3 - (0) + 1)) + (0)) + "px";
}
span.style.fontFamily = this.fontType;
number = number +1;
textContent.appendChild(span);
});
},
//RGB颜色
R(){
let textContent = document.getElementById("textContent");
let rgb = "rgb("+this.R+","+this.G+","+this.B+")";
textContent.style.color = this.colorHex(rgb);
},
//RGB颜色
G(){
let textContent = document.getElementById("textContent");
let rgb = "rgb("+this.R+","+this.G+","+this.B+")";
textContent.style.color = this.colorHex(rgb);
},
//RGB颜色
B(){
let textContent = document.getElementById("textContent");
let rgb = "rgb("+this.R+","+this.G+","+this.B+")";
textContent.style.color = this.colorHex(rgb);
},
//文字水平间距
level(){
let textContent = document.getElementById("textContent");
textContent.style.letterSpacing = this.level+"px";
},
//文字竖直间距
vertical(){
let textContent = document.getElementById("textContent");
textContent.style.lineHeight = this.vertical+"px";
},
//文字大小
size(){
let textContent = document.getElementById("textContent");
textContent.style.fontSize = this.size+"px";
var textArry = this.text.split("") || [];
if(this.isEmpty(textArry) || textArry.length <= 0){
return ;
}
while(textContent.hasChildNodes()) //当div下还存在子节点时 循环继续
{
textContent.removeChild(textContent.firstChild);
}
let number = 0;
textArry.forEach((item) => {
var span = document.createElement("span");
if(" " == item || ' ' == item ){
item = " ";
}
if("\n" == item ){
item = "<br>";
}
span.innerHTML = item;
if(this.size >=15 ){
span.style.fontSize = Math.floor(Math.random() * (this.size - (this.size-3) + 1)) + (this.size-3)+"px";
}
span.style.transform = "rotate("+(Math.floor(Math.random() * (5 - (-5) + 1)) + (-5))+"deg)";
if(number%5 == 0){
span.style.marginLeft = (Math.floor(Math.random() * (3 - (0) + 1)) + (0)) + "px";
}
if(number%3 == 0){
span.style.marginLeft = (Math.floor(Math.random() * (3 - (0) + 1)) + (0)) + "px";
}
if(number%9 == 0){
span.style.marginLeft = (Math.floor(Math.random() * (3 - (0) + 1)) + (0)) + "px";
}
span.style.fontFamily = this.fontType;
number = number +1;
textContent.appendChild(span);
});
},
//字体
fontType(){
var textArry = this.text.split("") || [];
if(this.isEmpty(textArry) || textArry.length <= 0){
return ;
}
let textContent = document.getElementById("textContent");
while(textContent.hasChildNodes()) //当div下还存在子节点时 循环继续
{
textContent.removeChild(textContent.firstChild);
}
let number = 0;
textArry.forEach((item) => {
var span = document.createElement("span");
if(" " == item || ' ' == item ){
item = " ";
}
if("\n" == item ){
item = "<br>";
}
span.innerHTML = item;
if(this.size >=15 ){
span.style.fontSize = Math.floor(Math.random() * (this.size - (this.size-3) + 1)) + (this.size-3)+"px";
}
span.style.transform = "rotate("+(Math.floor(Math.random() * (5 - (-5) + 1)) + (-5))+"deg)";
if(number%5 == 0){
span.style.marginLeft = (Math.floor(Math.random() * (3 - (0) + 1)) + (0)) + "px";
}
if(number%3 == 0){
span.style.marginLeft = (Math.floor(Math.random() * (3 - (0) + 1)) + (0)) + "px";
}
if(number%9 == 0){
span.style.marginLeft = (Math.floor(Math.random() * (3 - (0) + 1)) + (0)) + "px";
}
span.style.fontFamily = this.fontType;
number = number +1;
textContent.appendChild(span);
});
},
//左边距
leftPitch(){
let textContent = document.getElementById("textContent");
textContent.style.paddingLeft = this.leftPitch+"px";
},
//右边距
rightPitch(){
let textContent = document.getElementById("textContent");
textContent.style.paddingRight = this.rightPitch+"px";
},
//上边距
topPitch(){
let textContent = document.getElementById("textContent");
textContent.style.paddingTop = this.topPitch+"px";
},
//下边距
bottomPitch(){
let textContent = document.getElementById("textContent");
textContent.style.paddingBottom = this.bottomPitch+"px";
},
//字体旋转角
rotaAngle(){
let textContent = document.getElementById("textContent");
textContent.style.transform = "rotate("+this.rotaAngle+"deg)";
},
//背景旋转角
backRotaAngle(){
let backImg = document.getElementById("backImg");
backImg.style.transform = "rotate("+this.backRotaAngle+"deg)";
}
},
methods: {
//选择背景图
selectImg(){
//生成的临时url
debugger
const url = URL.createObjectURL(document.querySelector('#imgFile').files[0]);
this.defaultImgUrl = url;
},
//导出图片
exportImg(){
html2canvas(document.querySelector("#backImg")
,{
//高度和宽度 背景色
// width: 75,
// height: 75,
// backgroundColor: "#00ff00",
//使用 scale 属性可以修改渲染时的放大倍数(默认为 1),将其调大可以解决低分辨率设备下生成的图片模糊问题。
scale: 2,
//指定渲染的 Canvas 如果页面上原先就有个 canvas 元素,我们希望可以将图片绘制在它上面,可以使用 canvas 属性设置。
// canvas: document.querySelector("#myCanvas")
}
).then(canvas => {
// 将canvas转换成img的src流
// var imgUrl = canvas.toDataURL("image/png");
// console.log("base64编码数据:", imgUrl);
// 此方法可以设置截图质量(0-1)
// var imgUrl = canvas.toDataURL("image/png", 1);
// console.log("base64编码数据:", imgUrl);
//将canvas内容保存为文件并下载
canvas.toBlob(function(blob) {
saveAs(blob, "手写稿.png");
});
});
},
/**
*
* @param 校验是否为空
*/
isEmpty(obj) {
if (obj == undefined || obj == null || obj == '' || obj == "" ) {
return true
}
return false
},
/**
* RGB转换为16进制
* @returns {string}
*/
colorHex(color) {
// RGB颜色值的正则
var reg = /^(rgb|RGB)/;
if (reg.test(color)) {
var strHex = "#";
// 把RGB的3个数值变成数组
var colorArr = color.replace(/(?:\(|\)|rgb|RGB)*/g, "").split(",");
// 转成16进制
for (var i = 0; i < colorArr.length; i++) {
var hex = Number(colorArr[i]).toString(16);
if (hex === "0") {
hex += hex;
}
strHex += hex;
}
return strHex;
} else {
return String(color);
}
},
/**
* 16进制转换为RGB
* @returns {string}
*/
colorRgb(color) {
// 16进制颜色值的正则
var reg = /^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$/;
// 把颜色值变成小写
var color = color.toLowerCase();
if (reg.test(color)) {
// 如果只有三位的值,需变成六位,如:#fff => #ffffff
if (color.length === 4) {
var colorNew = "#";
for (var i = 1; i < 4; i += 1) {
colorNew += color.slice(i, i + 1).concat(color.slice(i, i + 1));
}
color = colorNew;
}
// 处理六位的颜色值,转为RGB
var colorChange = [];
for (var i = 1; i < 7; i += 2) {
colorChange.push(parseInt("0x" + color.slice(i, i + 2)));
}
return "RGB(" + colorChange.join(",") + ")";
} else {
return color;
}
}
}
}
</script>
<style scoped lang="scss">
.handwrite{
width: 100%;
height: 100%;
.left{
background-color: #c01111;
float: left;
margin-left: 3%;
width: 45%;
height: 98vh;
padding: 5px;
margin-bottom: 10px;
.backImg{
width: 100%;
height: 100%;
-moz-background-size:100% 100%;
background-size:100% 100%;
}
.textContent {
margin-top: 0%;
}
}
.right{
background-color: #1ab394;
float: left;
margin-left: 3%;
width: 45%;
height: 98vh;
padding: 5px;
margin-bottom: 10px;
.setting{
margin-top: 5px;
}
}
}
</style>