公司要求开发一个组件功能,希望将html元素变成图片;话不多说,直接上代码;
代码中的文件链接:
vue.js,html2canvas.js,element-ui.css,element-ui.js
(上面的文件链接是放在我自己的服务器上。如果打开慢,请去官网下载。请不要使用我的超链接放在代码中,因为带宽太差了。请下载下来使用)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<script src="./插件/vue.js"></script>
<script src="./插件/html2canvas.js"></script>
<link rel="stylesheet" href="./插件/element-ui.css">
<script src="./插件/element-ui.js"></script>
</head>
<body>
<!-- 创建一个根元素 -->
<div class="home" id="home" style="width: 620px;margin:auto;">
<el-form class="bg-control" label-position="right" label-width="110px" :rules="rules" :model="form">
<!-- <el-form-item label=" 媒体名称:" prop="mediaName">
<el-input size="small" placeholder="请输入媒体名称" v-model="form.mediaName" clearable></el-input>
</el-form-item> -->
<el-form-item label="适配分辨率:" prop="width_height">
<el-input size="small" placeholder="输入格式例如:1920*1080" v-model="form.width_height" clearable @change="changeWidth_height" @focus="savedOldData"></el-input>
</el-form-item>
<el-form-item label="背景版颜色:" prop="color">
<el-color-picker size="small" v-model="form.bgColor" show-alpha :predefine="predefineColors" @change="changeBgColor">
</el-color-picker>
</el-form-item>
<el-form-item label="媒体的内容:" class="media-content">
<div class="set">
<span>字体:</span>
<el-select size="small" v-model="form.fontFamily" @change="changeFont('fontFamily')">
<el-option value="SimSun" label="宋体"></el-option>
<el-option value="SimHei" label="黑体"></el-option>
<el-option value="Microsoft Yahei" label="微软雅黑"></el-option>
<el-option value="Microsoft JhengHei" label="微软正黑体"></el-option>
<el-option value="KaiTi" label="楷体"></el-option>
<el-option value="NSimSun" label="新宋体"></el-option>
<el-option value="FangSong" label="仿宋"></el-option>
<el-option value="cursive" label="手写草体"></el-option>
</el-select>
</div>
<div class="set">
<span>对齐方式:</span>
<el-select size="small" v-model="form.textAlign" @change="changeFont('textAlign')">
<el-option value="left" label="左对齐"></el-option>
<el-option value="right" label="右对齐"></el-option>
<el-option value="center" label="居中"></el-option>
</el-select>
</div>
<div class="set">
<span>颜色:</span>
<el-color-picker size="small" v-model="form.color" show-alpha :predefine="predefineColors" @change="changeFont('color')">
</el-color-picker>
</div>
<div class="set">
<span>字行高:</span>
<el-input-number size="small" v-model="form.lineHeight" :min="1" :step="0.5" @change="changeFont('lineHeight','em')"></el-nput-number>
</div>
<div class="set">
<span>字号:</span>
<el-input-number size="small" v-model="form.fontSize" :step="1" :min="10" @change="changeFont('fontSize','px')"></el-nput-number>
</div>
<div class="set">
<span>字间距:</span>
<el-input-number size="small" v-model="form.letterSpacing" :min="0" :step="0.5" @change="changeFont('letterSpacing','px')"></el-nput-number>
</div>
<div class="set">
<span>加粗:</span>
<el-input-number size="small" v-model="form.fontWeight" :step="100" :min="100" :max="900" @change="changeFont('fontWeight')"></el-nput-number>
</div>
</el-form-item>
<el-button type="primary" size="small" @click="addTxt" :disabled="!form.width_height">添加文字</el-button>
<el-button type="primary" size="small" @click="saved" :disabled="!form.width_height">生成canvas</el-button>
</el-form>
<div class="box-bg-container" :style="{'--pointColor':box.pointColor}">
<div class="bg-plate-bottom" v-if="box.show" :style="box.bgStyle"></div>
<div class="bg-plate" ref="bgPlate" v-if="box.show" :style="box.bgStyle" @mouseup="mouseleaveOrup" @mousemove="mousemove" @mouseleave="mouseleaveOrup" @wheel="changeSize" @click.stop="cancelDblclick">
<div class="mask" @click.stop="cancelDblclick" v-if="txtStatus.focus" name="遮罩层"></div>
<div class="suspension" :style="auxiliary.suspension.style" v-if="auxiliary.suspension.show">
<div>宽度:{{auxiliary.suspension.width}}px</div>
<div>高度:{{auxiliary.suspension.height}}px</div>
<div>旋转:{{auxiliary.suspension.rotate}}度</div>
</div>
<div class="horizontal" name="竖线" v-if="auxiliary.horizontal && txtStatus.move"></div>
<div class="vertical" name="横线" v-if="auxiliary.vertical && txtStatus.move"></div>
<div class="txtBox" v-for="(item, index) in box.txtBox" :style="item.boxStyle" @dblclick="selectText(index)" @mousedown="mousedown(index, $event)" @click.stop>
<div class="border" v-if="(txtStatus.move || txtStatus.focus) && index == txtStatus.index" @mousedown="changeWidth_down">
<div class="btn delete el-icon-delete" title="按下键盘delete" @click.stop="deleteTxt(index)"></div>
<div class="btn left-top"></div>
<div class="btn right-top"></div>
<div class="btn right"></div>
<div class="btn right-bottom"></div>
<div class="btn left-bottom"></div>
<div class="btn left"></div>
<div class="btn rotate el-icon-refresh"></div>
</div>
<div class="txt" :class="[`txt_${index}`]" ref="txtref" ondragstart="return false" :contenteditable="txtStatus.focus && index == txtStatus.index" :style="item.txtStyle">
{{ item.txt }}
</div>
</div>
</div>
</div>
</div>
</body>
<script>
// 将vue挂载到id为home的根元素上
new Vue({
el: "#home",
data() {
return {
predefineColors: [
'#ff4500',
'#ff8c00',
'#ffd700',
'#90ee90',
'#00ced1',
'#1e90ff',
'#c71585',
'rgba(255, 69, 0, 0.68)',
'rgb(255, 120, 0)',
'hsv(51, 100, 98)',
'hsva(120, 40, 94, 0.5)',
'hsl(181, 100%, 37%)',
'hsla(209, 100%, 56%, 0.73)',
'#c7158577'
],
templateTxt: {
txt: '双击编辑文字',
boxStyle: {
width: 'max-content',
border: `1px dashed transparent`,
left: '10px',
top: '10px',
transform: 'rotate(0deg)'
},
txtStyle: {
color: 'rgb(255, 255, 255)',
fontSize: '66px',
pointerEvents: 'auto',
fontFamily: 'SimSun',
textAlign: 'left',
lineHeight: 1,
letterSpacing: 0,
fontWeight: 500,
}
},
auxiliary: {
horizontal: false,
vertical: false,
suspension: {
width: '', //悬浮框内容中的宽度字段
height: '', //悬浮框内容中的高度字段
rotate: '', //悬浮框内容中的旋转字段
show: false, //悬浮框是否显示
move: false, //悬浮框是否移动
btnName: null, //被点击的元素className
startX: null, //被点击的元素的起点
startWidth: null, //元素被按下鼠标拖拽放大缩小时,文字框架的宽
fontSize: null, //元素被按下鼠标拖拽放大缩小时,文字的大小
startLeft: null, //元素被按下鼠标拖拽放大缩小时,文字框架的left位置
startTop: null, //元素被按下鼠标拖拽放大缩小时,文字框架的top位置
startRotate: null, //元素被按下鼠标拖拽旋转时,文字框架当时的旋转的角度
style: {
left: '0',
top: '0'
}
}
},
form: {
mediaName: '',
width_height: '',
bgColor: 'rgba(0,0,0,1)',
old_width_height: '',
fontFamily: null,
textAlign: '',
color: null,
lineHeight: undefined,
fontSize: undefined,
letterSpacing: undefined,
fontWeight: undefined,
},
box: {
pointColor: '#c1c1c1', //
show: false, //背景版的开关
bgStyle: {
width: '1000px',
height: '600px',
transform: 'scale(1)',
backgroundColor: '',
}, //背景版的style
txtBox: [], //文字数组
},
txtStatus: {
focus: false,
move: false,
index: null,
EleStartX: null, //元素的起始点
EleStartY: null, //元素的起始点
mouseStartX: null,
mouseStartY: null
},
rules: {
mediaName: [{
required: true,
message: '请输入媒体名称',
trigger: 'blur'
}, ],
width_height: [{
required: true,
message: '请输入适配分辨率',
trigger: 'blur'
}, ]
}
}
},
mounted() {
window.addEventListener('keydown', (e) => {
switch (e.key) {
case 'Escape':
if (this.txtStatus.focus) this.cancelDblclick();
break;
case 'Delete':
if (this.txtStatus.focus) this.deleteTxt(this.txtStatus.index);
break;
default:
break
}
})
},
beforeDestroy() {
},
methods: {
//保存一下旧的背景版宽高的数据
savedOldData() {
this.form.old_width_height = this.form.width_height;
},
//修改背景版的颜色
changeWidth_height() {
if (this.form.width_height.indexOf('*') == -1) return
this.createdBox();
let arrnew = this.form.width_height.split('*');
let arrold = this.form.old_width_height.split('*');
for (let i in this.box.txtBox) {
let left = parseFloat(this.box.txtBox[i].boxStyle.left);
let top = parseFloat(this.box.txtBox[i].boxStyle.top);
this.box.txtBox[i].boxStyle.left = (left + (arrnew[0] - arrold[0]) / 2) + 'px';
this.box.txtBox[i].boxStyle.top = (top + (arrnew[1] - arrold[1]) / 2) + 'px';
}
},
//新建背景版
createdBox() {
this.cancelDblclick();
if (!this.form.width_height) return
let arr = this.form.width_height.split('*');
this.box.bgStyle.width = arr[0] + 'px';
this.box.bgStyle.height = arr[1] + 'px';
let father = document.querySelector('.box-bg-container');
let fatherHeight = father.offsetHeight;
let fatherWidth = father.offsetWidth;
this.box.bgStyle.left = (fatherWidth - arr[0]) / 2 + 'px';
this.box.bgStyle.top = (fatherHeight - arr[1]) / 2 + 'px';
this.box.bgStyle.backgroundColor = this.form.bgColor;
this.box.show = true;
},
//提交保存
saved() {
this.cancelDblclick();
let ele = this.$refs.bgPlate;
if (!ele) return;
let ele_clone = ele.cloneNode(true);
let boxBig = document.querySelector('.box-bg-container')
boxBig.appendChild(ele_clone)
let scale = this.box.bgStyle.transform;
this.box.bgStyle.transform = 'scale(1)';
this.box.bgStyle.zIndex = '-1';
this.$nextTick(() => {
html2canvas(ele).then((canvas) => {
let newCanvas = document.body.appendChild(canvas)
let newImg = newCanvas.toDataURL('image/png');
console.log('base64', newImg);
console.log('数据类型', JSON.stringify(this.box));
// this.box.bgStyle.transform = scale; //还原
// delete this.box.bgStyle.zIndex; //还原
// boxBig.removeChild(ele_clone); //还原
// newCanvas.remove();
})
})
},
//删除文字
deleteTxt(index) {
this.box.txtBox.splice(index, 1);
this.txtStatus.index = null;
this.txtStatus.focus = false;
},
//控制中间线的出现和隐藏
horizontal_vertical(i) {
let boxEle = this.$refs.txtref[i].parentElement;
let centerX = parseFloat(this.box.bgStyle.width) / 2 - boxEle.offsetWidth / 2; //背景板中心的x坐标-当前元素的width
let centerY = parseFloat(this.box.bgStyle.height) / 2 - boxEle.offsetHeight / 2; //背景板中心的y坐标-当前元素的height
let left = parseFloat(this.box.txtBox[i].boxStyle.left); //获取当前的元素的left坐标
let top = parseFloat(this.box.txtBox[i].boxStyle.top); //获取当前的元素的top坐标
if (left < centerX + 2 && left > centerX - 2) this.auxiliary.horizontal = true; //当前的元素的 left 坐标与居中的位置相差± 3的时候,显示,否则不显示
else this.auxiliary.horizontal = false;
if (top < centerY + 2 && top > centerY - 2) this.auxiliary.vertical = true; //当前的元素的 top 坐标与居中的位置相差± 3的时候,显示,否则不显示
else this.auxiliary.vertical = false;
},
//按下鼠标:记录各个工作的起始点
mousedown(index, e) {
if (e.button != 0) return
if (this.txtStatus.focus) return
this.box.txtBox[index].txtStyle.cursor = 'move';
this.box.txtBox[index].boxStyle.border = `1px dashed ${this.box.pointColor}`;
this.txtStatus.move = true;
this.txtStatus.index = index;
let parentEle = e.target.parentNode;
this.txtStatus.EleStartX = parseFloat(parentEle.style.left);
this.txtStatus.EleStartY = parseFloat(parentEle.style.top);
this.txtStatus.mouseStartX = e.pageX; //记录鼠标点击的起始点
this.txtStatus.mouseStartY = e.pageY; //记录鼠标点击的起始点
this.box.txtBox.splice();
},
// 按下鼠标:记录各个工作的起始点
changeWidth_down(e) {
if (e.button != 0) return
if (!this.txtStatus.focus) return
let classList = e.target.classList;
if (classList[1] == 'delete') return
this.auxiliary.suspension.btnName = classList[1];
this.auxiliary.suspension.startX = e.pageX;
this.auxiliary.suspension.startY = e.pageY;
let i = this.txtStatus.index;
this.auxiliary.suspension.move = true;
let ele_txt = this.$refs.txtref[i].getBoundingClientRect();
if (classList[1] == 'left') {
this.auxiliary.suspension.startwidth = parseFloat(ele_txt.width)
this.auxiliary.suspension.startLeft = parseFloat(this.box.txtBox[i].boxStyle.left);
} else if (classList[1] == 'right') {
this.auxiliary.suspension.startwidth = parseFloat(ele_txt.width);
} else if (classList[1] == 'left-top' || classList[1] == 'right-top' || classList[1] == 'left-bottom') {
this.auxiliary.suspension.fontSize = parseFloat(this.box.txtBox[i].txtStyle.fontSize);
this.auxiliary.suspension.startLeft = parseFloat(this.box.txtBox[i].boxStyle.left);
this.auxiliary.suspension.startTop = parseFloat(this.box.txtBox[i].boxStyle.top);
} else if (classList[1] == 'right-bottom') {
this.auxiliary.suspension.fontSize = parseFloat(this.box.txtBox[i].txtStyle.fontSize);
this.auxiliary.suspension.startLeft = parseFloat(this.box.txtBox[i].boxStyle.left);
} else if (classList[1] == 'rotate') {
let ele_w = parseFloat(this.$refs.txtref[i].offsetWidth);
let ele_h = parseFloat(this.$refs.txtref[i].offsetHeight);
let ele_l = parseFloat(this.box.txtBox[i].boxStyle.left);
let ele_t = parseFloat(this.box.txtBox[i].boxStyle.top);
let orginX = ele_l + ele_w / 2;
let orginY = ele_t + ele_h / 2;
this.auxiliary.suspension.startRotate = [orginX, orginY]
}
this.showSuspension(e)
},
//拖拽鼠标:计算移动的距离
mousemove(e) {
let scale = parseFloat(this.box.bgStyle.transform.replace('scale(', '').replace(')', ''));
if (this.txtStatus.move && !this.txtStatus.focus) {
let moveX = this.txtStatus.mouseStartX - e.pageX; //鼠标移动的距离
let moveY = this.txtStatus.mouseStartY - e.pageY; //鼠标移动的距离
let i = this.txtStatus.index;
this.box.txtBox[i].boxStyle.left = this.txtStatus.EleStartX - moveX / scale + 'px'
this.box.txtBox[i].boxStyle.top = this.txtStatus.EleStartY - moveY / scale + 'px'
this.horizontal_vertical(i);
} //当处于移动的状态的时候,执行此功能会一直修改元素的位置
else if (this.auxiliary.suspension.move && this.txtStatus.focus) {
let moveX = this.auxiliary.suspension.startX - e.pageX; //鼠标移动的距离
let moveY = this.auxiliary.suspension.startY - e.pageY; //鼠标移动的距离
let i = this.txtStatus.index;
let btnName = this.auxiliary.suspension.btnName;
if (btnName == 'left') {
moveX = moveX / scale;
this.box.txtBox[i].boxStyle.width = (this.auxiliary.suspension.startwidth + moveX) / scale + 'px';
this.box.txtBox[i].boxStyle.left = (this.auxiliary.suspension.startLeft - moveX) + 'px'
} else if (btnName == 'right') {
moveX = moveX / scale;
this.box.txtBox[i].boxStyle.width = (this.auxiliary.suspension.startwidth - moveX * scale) / scale + 'px';
} else if (btnName == 'left-top') {
moveX = moveX / scale;
this.box.txtBox[i].txtStyle.fontSize = this.auxiliary.suspension.fontSize + moveX + 'px';
this.box.txtBox[i].boxStyle.left = this.auxiliary.suspension.startLeft - moveX + 'px';
this.box.txtBox[i].boxStyle.top = this.auxiliary.suspension.startTop - moveY + 'px';
this.form.fontSize = parseFloat(this.box.txtBox[i].txtStyle.fontSize);
} else if (btnName == 'left-bottom') {
this.box.txtBox[i].txtStyle.fontSize = this.auxiliary.suspension.fontSize + moveX + 'px';
this.box.txtBox[i].boxStyle.left = this.auxiliary.suspension.startLeft - moveX + 'px';
this.box.txtBox[i].boxStyle.top = this.auxiliary.suspension.startTop + moveY + 'px';
this.form.fontSize = parseFloat(this.box.txtBox[i].txtStyle.fontSize);
} else if (btnName == 'right-top') {
let txt = this.box.txtBox[i].txt.length;
this.box.txtBox[i].txtStyle.fontSize = this.auxiliary.suspension.fontSize - moveX + 'px';
this.box.txtBox[i].boxStyle.left = this.auxiliary.suspension.startLeft + moveX * (txt - 1) + 'px';
this.box.txtBox[i].boxStyle.top = this.auxiliary.suspension.startTop + moveY + 'px';
this.form.fontSize = parseFloat(this.box.txtBox[i].txtStyle.fontSize);
} else if (btnName == 'right-bottom') {
let txt = this.box.txtBox[i].txt.length;
this.box.txtBox[i].txtStyle.fontSize = this.auxiliary.suspension.fontSize - moveX + 'px';
this.box.txtBox[i].boxStyle.left = this.auxiliary.suspension.startLeft + moveX * (txt - 1) + 'px';
this.form.fontSize = parseFloat(this.box.txtBox[i].txtStyle.fontSize);
} else if (btnName == 'rotate') {
if (!this.auxiliary.suspension.startRotate) return
let orginX = this.auxiliary.suspension.startRotate[0]; //围绕选择的中心点
let orginY = this.auxiliary.suspension.startRotate[1]; //围绕选择的中心点
let boxH = parseFloat(this.box.bgStyle.height);
let ele = document.querySelector('.bg-plate').getBoundingClientRect();
let x = (e.pageX - ele.left) / scale;
let y = (e.pageY - ele.top) / scale;
let rotate = this.getAngle([orginX - orginX, boxH - orginY], [x - orginX, y - orginY])
this.box.txtBox[i].boxStyle.transform = `rotate(${rotate.toFixed(2)}deg)`
}
if (parseFloat(this.box.txtBox[i].txtStyle.fontSize) * scale < 10) this.auxiliary.suspension.move = false
this.showSuspension(e)
} //当处于修改宽高的状态的时候,执行此功能会一直修改元素的宽高
},
//销毁移动;清空各个变量的状态
mouseleaveOrup(e) {
if (e.button != 0) return
if (!this.txtStatus.focus && this.txtStatus.move) {
let i = this.txtStatus.index;
this.box.txtBox[i].txtStyle.cursor = 'default';
this.box.txtBox[i].boxStyle.border = "1px dashed transparent";
this.txtStatus.mouseStartX = null;
this.txtStatus.mouseStartY = null;
this.txtStatus.EleStartX = null;
this.txtStatus.EleStartY = null;
this.txtStatus.move = false;
this.txtStatus.index = 0;
this.box.txtBox.splice();
} //当处于移动的状态的时候,执行此功能会关闭移动的状态
else if (this.txtStatus.focus && this.auxiliary.suspension.move) {
this.auxiliary.suspension.show = false;
this.auxiliary.suspension.move = false;
this.auxiliary.suspension.btnName = null;
this.auxiliary.suspension.startX = null;
this.auxiliary.suspension.startWidth = null;
this.auxiliary.suspension.fontSize = null;
this.cancelDblclick()
} //当处于修改宽的状态的时候,执行此功能会关闭修改宽高的状态
},
//计算旋转角度
getAngle([x1, y1], [x2, y2]) {
const dot = x1 * x2 + y1 * y2
const det = x1 * y2 - y1 * x2
const angle = Math.atan2(det, dot) / Math.PI * 180
return (angle + 360) % 360
},
//双击文字
selectText(index) {
this.txtStatus.focus = true;
this.txtStatus.index = index;
this.box.txtBox[index].txtStyle.cursor = 'text';
this.box.txtBox[index].boxStyle.border = `1px dashed ${this.box.pointColor}`;
this.box.txtBox.splice();
this.$nextTick(() => {
let ele = this.$refs.txtref[index];
if (document.selection) {
let range = document.body.createTextRange()
range.moveToElementText(ele);
range.select();
} else if (window.getSelection) {
let range = document.createRange();
range.selectNodeContents(ele)
window.getSelection().removeAllRanges()
window.getSelection().addRange(range)
}
})
let txt = this.box.txtBox[index].txtStyle;
this.form.fontFamily = txt.fontFamily;
this.form.textAlign = txt.textAlign;
this.form.color = txt.color;
this.form.lineHeight = parseFloat(txt.lineHeight);
this.form.fontSize = parseInt(txt.fontSize);
this.form.letterSpacing = parseFloat(txt.letterSpacing);
this.form.fontWeight = parseInt(txt.fontWeight);
},
//取消双击效果
cancelDblclick() {
let i = this.txtStatus.index;
if (i === null) return
if (!this.txtStatus.focus) return
// this.box.txtBox[i].txtStyle.backgroundColor = '';
this.box.txtBox[i].txtStyle.cursor = 'default';
this.box.txtBox[i].boxStyle.border = "1px dashed transparent";
this.changeTxt(i)
this.txtStatus.index = null;
this.txtStatus.focus = false;
this.box.txtBox.splice();
this.form.fontFamily = null;
this.form.textAlign = null;
this.form.color = null;
this.form.lineHeight = undefined;
this.form.fontSize = undefined;
this.form.letterSpacing = undefined;
this.form.fontWeight = undefined;
this.auxiliary.suspension.show = false
},
//添加文字
addTxt() {
this.cancelDblclick()
if (!this.box.show) return
let txt = JSON.parse(JSON.stringify(this.templateTxt));
if (!this.box.show) return
//当一个字的大小为66,那么这个字框的宽度就是字数*66,高度就是66;这个地方
let fontS = parseInt(txt.txtStyle.fontSize);
let txtNum = txt.txt.length;
txt.boxStyle.left = parseFloat(this.box.bgStyle.width) / 2 - (fontS * txtNum / 2) + 'px';
txt.boxStyle.top = parseFloat(this.box.bgStyle.height) / 2 - (fontS / 2) + 'px';
// txt.boxStyle.backgroundColor = this.form.bgColor;
this.auxiliary.horizontal = true;
this.auxiliary.vertical = true;
this.box.txtBox.push(txt);
let i = this.box.txtBox.length - 1;
this.selectText(i);
},
//小视窗的位置和内部的信息
showSuspension(e) {
let i = this.txtStatus.index;
this.auxiliary.suspension.show = true;
this.auxiliary.suspension.style.left = e.pageX + 10 + 'px';
this.auxiliary.suspension.style.top = e.pageY + 10 + 'px';
let ele_txt = this.$refs.txtref[i];
this.auxiliary.suspension.width = parseInt(ele_txt.offsetWidth);
this.auxiliary.suspension.height = parseInt(ele_txt.offsetHeight);
let rotate = this.box.txtBox[i].boxStyle.transform;
this.auxiliary.suspension.rotate = rotate.replace('rotate(', '').replace('deg)', '');
},
//通过滚轮修改背景的大小
changeSize(e) {
e.preventDefault()
if (this.txtStatus.focus) return;
if (this.txtStatus.move) return;
let changeSize; //这可以看做百分比
if (e.deltaY > 0) changeSize = -0.02;
else if (e.deltaY < 0) changeSize = 0.02;
let scale = parseFloat(this.box.bgStyle.transform.replace('scale(', '').replace(')', '')) + changeSize;
if (scale < 0.05) return
this.box.bgStyle.transform = `scale(${scale})`
},
//修改选中字体的方法
changeFont(attribute, pixel = '') {
let i = this.txtStatus.index;
if (i == null) return
this.box.txtBox[i].txtStyle[attribute] = this.form[attribute] + pixel;
},
//改变背景版的颜色
changeBgColor() {
this.box.bgStyle.backgroundColor = this.form.bgColor;
this.box.txtBox.splice()
},
changeTxt(index) {
this.box.txtBox[index].txt = this.$refs.txtref[index].innerText;
this.box.txtBox.splice()
}
}
});
</script>
<style lang="scss">
.bg-control {
.media-content {
background-color: #f4f6fa;
.el-form-item__content {
display: flex;
flex-wrap: wrap;
box-sizing: border-box;
.set {
width: 50%;
box-sizing: border-box;
display: flex;
align-items: center;
margin-bottom: 5px;
>span {
width: 60px;
text-align: right;
padding-right: 10px;
}
.el-color-picker {
width: 150px;
border: 1px solid #e6e6e6;
.el-color-picker__trigger {
border: none;
}
}
.el-input-number {
width: 150px;
}
.el-select {
width: 150px;
}
}
}
}
}
.box-bg-container {
background-color: #f5f5f5;
margin-top: 10px;
border: 1px dashed #616161;
height: 510px;
box-sizing: border-box;
overflow: hidden;
position: relative;
.mask {
width: 100%;
height: 100%;
position: absolute;
background-color: rgba(0, 0, 0, 0);
left: 0;
top: 0;
box-sizing: border-box;
}
.bg-plate,
.bg-plate-bottom {
overflow: hidden;
box-shadow: 0 4px 20px var(--stroke--separater);
box-sizing: border-box;
transform-origin: center;
position: absolute;
.suspension {
position: fixed;
color: var(--pointColor);
font-size: 12px;
background-color: rgba(0, 0, 0, 0.9);
padding: 6px 10px;
z-index: 1;
border-radius: 10px;
border: 1px solid #919191;
user-select: none;
}
.horizontal {
width: 2px;
height: 100%;
opacity: 0.5;
background-color: var(--pointColor);
position: absolute;
left: calc(50% + 2px);
transform: translate(-50%, 0%);
}
.vertical {
width: 100%;
height: 2px;
opacity: 0.5;
background-color: var(--pointColor);
position: absolute;
top: calc(50% - 2px);
transform: translate(0%, -50%);
}
.txtBox {
position: absolute;
height: auto;
.border {
.btn {
user-select: none;
width: 8px;
height: 8px;
background-color: var(--pointColor);
border-radius: 100%;
position: absolute;
user-select: none;
transform: translate(-50%, -50%);
}
.left-top.btn {
cursor: se-resize;
}
.left.btn {
left: 0;
top: 50%;
height: 4px;
width: 16px;
border-radius: 4px;
transform: rotate(90deg) translate(-25%, 8px);
cursor: w-resize;
}
.right-top.btn {
left: 100%;
cursor: ne-resize;
}
.right.btn {
left: 100%;
top: 50%;
height: 4px;
width: 16px;
border-radius: 4px;
transform: rotate(90deg) translate(-25%, 8px);
cursor: w-resize;
}
.left-bottom.btn {
left: 0%;
top: 100%;
cursor: ne-resize;
}
.right-bottom.btn {
left: 100%;
top: 100%;
cursor: se-resize;
}
.delete.btn {
width: 18px;
height: 18px;
color: var(--pointColor);
font-size: 16px;
left: 50%;
top: -30px;
background-color: transparent;
cursor: pointer;
}
.delete.btn::before {
position: absolute;
left: 50%;
transform: translate(-50%, 0px);
}
.btn.rotate {
width: 18px;
height: 18px;
color: var(--pointColor);
font-size: 16px;
left: 50%;
bottom: -50px;
background-color: transparent;
//cursor: url(./_mouse-icon-rotate-0.svg) 12 12, auto;
}
.btn.rotate::before {
position: absolute;
left: 50%;
transform: translate(-50%, 0px);
}
}
.txt {
width: 100%;
height: 100%;
user-select: none;
cursor: default;
box-sizing: border-box;
outline: none;
word-break: break-all;
}
}
}
.bg-plate-bottom {
background-image: url(./_background-transparent.png);
}
}
</style>
</html>
使用html2canvas生成的dom元素,其元素以及子元素尽量不要使用transform:translate;否则会出现绘制canvas定位显示问题
文件图片(_background-transparent):