400X400
class="pre-area"
ref="pre_area"
@click="gHandle($event)"
:style="{boxShadow:dituObj.shadow1+'px '+dituObj.shadow2+'px '+dituObj.shadow3+'px '+dituObj.shadowColor+' '+dituObj.shadowDirection,backgroundColor:dituObj.backgroundColor,backgroundImage:'url(' + dituObj.backgroundImage + ')',backgroundSize: '100% 100%',backgroundRepeat: 'no-repeat'}"
>
v-for="(item, i) in elemList" :w="item.w" :h="item.h" :x="item.x" :y="item.y" :z="item.zIndex" :isActive="item.isActive" :minw="1" :minh="1" :key="i+item.type" :parentLimitation="item.parentLimitation" @dragging="onDragging($event, item, i)" @deactivated="onDeactivated($event, item)" @resizing="changeSize($event, item, i)" @activated="onActivated($event, item, i)" @mousedown.native="mouthDown($event, item, i)" @mouseup.native="mouthUp($event, item, i)" > :style="{boxShadow:item.shadow1+'px '+item.shadow2+'px '+item.shadow3+'px '+item.shadowColor+' '+item.shadowDirection,transform:'rotate('+item.rotate+'deg)',backgroundColor:item.backgroundColor,backgroundImage:'url(' + item.backgroundImage + ')',backgroundSize: '100% 100%',backgroundRepeat: 'no-repeat'}" class="dian" v-if="item.type == '点/圆'" >
:style="{boxShadow:item.shadow1+'px '+item.shadow2+'px '+item.shadow3+'px '+item.shadowColor+' '+item.shadowDirection,transform:'rotate('+item.rotate+'deg)',backgroundColor:item.backgroundColor,backgroundImage:'url(' + item.backgroundImage + ')',backgroundSize: '100% 100%',backgroundRepeat: 'no-repeat'}"
class="zhixian"
v-if="item.type == '直线'"
>
class="inner-area"
v-if="item.type == '文字输入区'"
:style="{fontStyle:item.fontStyle,fontWeight:item.fontWeight,textShadow:item.shadow1+'px '+item.shadow2+'px '+item.shadow3+'px '+item.shadowColor,transform:'rotate('+item.rotate+'deg)',color:item.color,fontSize:item.fontSize+'px',backgroundColor:item.backgroundColor,backgroundImage:'url(' + item.backgroundImage + ')',backgroundSize: '100% 100%',backgroundRepeat: 'no-repeat'}"
>{{ item.text }}
:style="{boxShadow:item.shadow1+'px '+item.shadow2+'px '+item.shadow3+'px '+item.shadowColor+' '+item.shadowDirection,transform:'rotate('+item.rotate+'deg)',border: item.borderSize + 'px solid ' + item.borderColor,backgroundColor:item.backgroundColor,backgroundImage:'url(' + item.backgroundImage + ')',backgroundSize: '100% 100%',backgroundRepeat: 'no-repeat'}"
class="yuanquan"
v-if="item.type == '圆圈'"
>
:style="{boxShadow:item.shadow1+'px '+item.shadow2+'px '+item.shadow3+'px '+item.shadowColor+' '+item.shadowDirection,transform:'rotate('+item.rotate+'deg)',border: item.borderSize + 'px solid ' + item.borderColor,transform:'rotate('+item.rotate+'deg)',backgroundColor:item.backgroundColor,backgroundImage:'url(' + item.backgroundImage + ')',backgroundSize: '100% 100%',backgroundRepeat: 'no-repeat'}"
class="zhengfangxing"
v-if="item.type == '正方形'"
>
X:{{ activeElem.x }},Y:{{ activeElem.y }}
宽:{{ activeElem.w }},高:{{ activeElem.h }}
v-model="outerShape" @change="shapeChange($event, 'outerBorder')" placeholder="选择形状" size="mini" > v-for="item in shapeOpts" :key="item.value" :label="item.label" :value="item.value" >
show-alpha v-model="color" @active-change="colorChange($event, '全局背景颜色')" size="mini" />
外边框:
v-model="outerBorderWidth" @change="sizeChange($event, '外边框')" :min="1" :max="200" size="mini" >
show-alpha v-model="outerBorderColor" @active-change="colorChange($event, '全局边框')" size="mini" />
show-alpha v-model="gshadowColor" @active-change="colorChange($event,'全局阴影')" size="mini" />
import VueDragResize from 'vue-drag-resize'
import html2canvas from 'html2canvas'
import Tools from '../components/Tools'
import { userDevice } from '../utils/fun.js'
export default {
name: 'Home',
components: {
VueDragResize, Tools
},
data () {
return {
elemList: [
{ name: '文字输入区', isActive: true, type: '文字输入区', parentLimitation: true, text: '文字输入区', w: 80, h: 40, x: 150, y: 150, zIndex: 1, color: '#000', fontSize: 20, backgroundColor: '', backgroundImage: '', rotate: 0, shadow1: 0, shadow2: 0, shadow3: 0, shadowColor: '#000', fontWeight: 'normal', fontStyle: '' },
{ name: '文字输入区', isActive: false, type: '文字输入区', area: 'tool-area', text: '文字输入区', parentLimitation: true, w: 80, h: 40, x: -130, y: 39, zIndex: 1, color: '#000', fontSize: 20, backgroundColor: '', backgroundImage: '', rotate: 0, shadow1: 0, shadow2: 0, shadow3: 0, shadowColor: '#000', fontWeight: 'normal', fontStyle: '' },
{ name: '点/圆', isActive: false, type: '点/圆', area: 'tool-area', parentLimitation: false, w: 10, h: 10, x: -100, y: 98, zIndex: 1, backgroundColor: '#000', backgroundImage: '', rotate: 0, shadow1: 0, shadow2: 0, shadow3: 0, shadowColor: '#000', shadowDirection: '' },
{ name: '直线', isActive: false, type: '直线', area: 'tool-area', parentLimitation: false, w: 50, h: 2, x: -110, y: 141, zIndex: 1, rotate: 0, backgroundColor: '#000', backgroundImage: '', shadow1: 0, shadow2: 0, shadow3: 0, shadowColor: '#000', shadowDirection: '' },
{ name: '圆圈', isActive: false, type: '圆圈', area: 'tool-area', parentLimitation: false, w: 30, h: 30, x: -110, y: 168, zIndex: 1, borderColor: '#000', borderSize: 1, backgroundColor: '', backgroundImage: '', rotate: 0, shadow1: 0, shadow2: 0, shadow3: 0, shadowColor: '#000', shadowDirection: '' },
{ name: '正方形', isActive: false, type: '正方形', area: 'tool-area', parentLimitation: false, w: 30, h: 30, x: -110, y: 205, zIndex: 1, borderColor: '#000', borderSize: 1, rotate: 0, backgroundColor: '', backgroundImage: '', shadow1: 0, shadow2: 0, shadow3: 0, shadowColor: '#000', shadowDirection: '' }
],
fileList: [],
maxIndex: 1,
activeElem: {},
dituObj: {
name: '底图', type: '底图', borderColor: '#000', borderSize: 1, backgroundColor: '', backgroundImage: '', rotate: 0, shadow1: 0, shadow2: 0, shadow3: 0, shadowColor: '#000', shadowDirection: ''
},
outerShape: '正方形',
fontBorderShape: '',
shapeOpts: [
{
value: '正方形',
div: '正方形'
},
{
value: '圆形',
div: '圆形'
}
],
fontBorderShapeOpts: [
{
value: '圆形',
div: '圆形'
}, {
value: '方形',
div: '方形'
}
],
fontOpts: [
{
value: '常规',
div: '常规'
}, {
value: '微软雅黑',
div: '微软雅黑'
}, {
value: '宋体',
div: '宋体'
}, {
value: '楷体',
div: '楷体'
}, {
value: '隶书',
div: '隶书'
}
],
color: '#fff',
outerBorder: false,
outerBorderWidth: 5,
outerBorderColor: '#000',
gshadow1: 0, // 全局阴影
gshadow2: 0,
gshadow3: 0,
gshadowColor: '',
imgUrl: '',
shadowDirection: ''
}
},
methods: {
gHandle (e) {
if (e.target.className === 'pre-area') {
this.activeElem = this.dituObj
}
},
colorChange (val, type) {
console.log(12343, val, type)
if (type === '文字输入区') {
this.activeElem.color = val
} else if (type === '边框') {
this.activeElem.borderColor = val
} else if (type === '背景') {
this.activeElem.backgroundImage = ''
this.activeElem.backgroundColor = val
} else if (type === '阴影') {
this.activeElem.shadowColor = val
} else if (type === '全局背景颜色') {
this.color = val
const dom = document.getElementsByClassName('pre-area')[0]
dom.style.backgroundImage = ''
dom.style.backgroundColor = val
} else if (type === '全局边框') {
this.outerBorderColor = val
if (!this.outerBorder) return
const dom = document.getElementsByClassName('pre-area')[0]
dom.style.border = this.outerBorderWidth + 'px solid ' + this.outerBorderColor
} else if (type === '全局阴影') {
const dom = document.getElementsByClassName('pre-area')[0]
dom.style.boxShadow = this.gshadow1 + 'px ' + this.gshadow2 + 'px ' + this.gshadow3 + 'px ' + this.gshadowColor + ' inset'
}
},
rotateRadusChange (val) {
this.activeElem.rotate = val
},
sizeChange (val, type) {
console.log(123)
if (type === '文字') {
this.activeElem.fontSize = val
} else if (type === '线条宽度') {
this.activeElem.borderSize = val
} else if (type === '度数') {
this.activeElem.rotate = val
} else if (type === '外边框' && this.outerBorder) {
const dom = document.getElementsByClassName('pre-area')[0]
dom.style.border = this.outerBorderWidth + 'px solid ' + this.outerBorderColor
}
},
fontStyleHandle (type) {
if (type === 'fontWeight') {
this.activeElem.fontWeight === 'bold' ? this.activeElem.fontWeight = 'normal' : this.activeElem.fontWeight = 'bold'
} else {
this.activeElem.fontStyle === 'italic' ? this.activeElem.fontStyle = '' : this.activeElem.fontStyle = 'italic'
}
},
shapeChange (val, type) {
console.log(val)
if (type === 'outerBorder') {
const dom = document.getElementsByClassName('pre-area')[0]
if (val === '圆形') {
dom.style.width = '400px'
dom.style.height = '400px'
dom.style.borderRadius = '50%'
} else if (val === '正方形') {
dom.style.width = '400px'
dom.style.height = '400px'
dom.style.borderRadius = ''
}
} else if (type === 'fontBorder') {
const dom = document.getElementsByClassName('inner-area')[0]
if (val === '圆形') {
dom.style.borderRadius = '50%'
} else if (val === '方形') {
dom.style.borderRadius = ''
}
}
},
fontChange (val) {
const dom = document.getElementsByClassName('pre-area')[0]
if (val === '常规') {
dom.style.fontFamily = ''
} else if (val === '微软雅黑') {
dom.style.fontFamily = 'Microsoft YaHei'
} else if (val === '宋体') {
dom.style.fontFamily = 'SimSun'
} else if (val === '楷体') {
dom.style.fontFamily = 'KaiTi'
} else if (val === '隶书') {
dom.style.fontFamily = 'LiSu'
}
},
borderChange (bool, type) {
if (type === '外边框') {
const dom = document.getElementsByClassName('pre-area')[0]
if (bool) {
dom.style.border = this.outerBorderWidth + 'px solid ' + this.outerBorderColor
} else {
dom.style.border = ''
}
}
},
shadowChange (val, i) {
this.activeElem['shadow' + i] = val
},
gshadowChange () {
const dom = document.getElementsByClassName('pre-area')[0]
dom.style.boxShadow = this.gshadow1 + 'px ' + this.gshadow2 + 'px ' + this.gshadow3 + 'px ' + this.gshadowColor + ' inset'
},
shadowDirectionChange (val) {
console.log(val)
if (val === 'inset') {
this.activeElem.shadowDirection = val
} else {
this.activeElem.shadowDirection = ''
}
console.log(this.activeElem)
},
beforeUpload (file) {
console.log(file, 'file')
if (file.type !== 'image/jpg' && file.type !== 'image/png' && file.type !== 'image/jpeg') {
this.$message.error('上传图片只能是 JPG/PNG 格式!')
return false
}
if (file.size / 1024 / 1024 > 2) {
this.$message.error('上传图片大小不能超过 2MB!')
return false
}
const fr = new FileReader()
fr.readAsDataURL(file)
fr.onload = (e) => {
this.fileList.push(e.target.result)
}
console.log(this.fileList, 'fileList')
},
setBgImg (type, n) {
console.log(type, n)
if (type === '选中') {
this.activeElem.backgroundColor = ''
this.activeElem.backgroundImage = n
} else if (type === '全局') {
const dom = document.getElementsByClassName('pre-area')[0]
dom.style.backgroundImage = 'url(' + n + ')'
dom.style.backgroundSize = '100% 100%'
dom.style.backgroundRepeat = 'no-repeat'
}
},
handleExceed (files, fileList) {
this.$message.warning(`每次限制选择 3 个文件,本次选择了 ${files.length} 个文件`)
},
createImg () {
window.scrollTo(0, 0)
console.log(window.scrollX)
const canvas = document.createElement('canvas')
// const canva = document.getElementsByClassName('canvas_area')[0]
const dom = document.getElementsByClassName('pre-area')[0]
const width = dom.offsetWidth // 获取dom 宽度
const height = dom.offsetHeight // 获取dom 高度
const scale = 2 // 定义任意放大倍数 支持小数
canvas.getContext('2d').scale(scale, scale) // 获取context,设置scale
const rect = dom.getBoundingClientRect() // 获取元素相对于视口的
console.log(rect, 'rect')
// const scrollTop = document.documentElement.scrollTop || document.body.scrollTop // 获取滚动轴滚动的长度
const opts = {
// canvas: canva,
x: rect.left, // 绘制的dom元素相对于视口的位置
y: rect.top,
// scrollX: 0, // 滚动的长度
// scrollY: 0,
scale: scale, // 添加的scale 参数
width: width, // dom 原始宽度
height: height,
useCORS: true, // 开启跨域
dpi: window.devicePixelRatio * 2
}
// return
this.$nextTick(() => {
(window.html2canvas || html2canvas)(dom, opts).then(canvas => {
const context = canvas.getContext('2d')
// 关闭抗锯齿
context.mozImageSmoothingEnabled = false
context.msImageSmoothingEnabled = false
context.imageSmoothingEnabled = false
// 转成图片,生成图片地址
this.imgUrl = canvas.toDataURL('image/png')
if (userDevice() === 'mobile') {
} else {
const a = document.createElement('a') // 生成一个a元素
const event = new MouseEvent('click') // 创建一个单击事件
a.download = name || 'photo' // 设置图片名称
a.href = this.imgUrl // 将生成的URL设置为a.href属性
a.dispatchEvent(event)
}
}).catch(err => {
console.log(err, 'err')
})
})
},
addTool (type) {
let el
if (type === '文字输入区') {
el = { name: '文字输入区', isActive: true, type: '文字输入区', parentLimitation: true, text: '文字输入区', w: 80, h: 40, x: 150, y: 150, zIndex: 1, color: '#000', fontSize: 20, backgroundColor: '', backgroundImage: '', fontWeight: 'normal' }
} else if (type === '点/圆') {
el = { name: '点/圆', isActive: true, type: '点/圆', area: 'tool-area', parentLimitation: false, w: 10, h: 10, x: -100, y: 98, zIndex: 1, backgroundColor: '#000', backgroundImage: '' }
} else if (type === '直线') {
el = { name: '直线', isActive: true, type: '直线', area: 'tool-area', parentLimitation: false, w: 50, h: 2, x: -110, y: 141, zIndex: 1, rotate: '', backgroundColor: '#000', backgroundImage: '' }
} else if (type === '圆圈') {
el = { name: '圆圈', isActive: true, type: '圆圈', area: 'tool-area', parentLimitation: false, w: 30, h: 30, x: -110, y: 168, zIndex: 1, borderColor: '#000', borderSize: 1, backgroundImage: '' }
} else if (type === '正方形') {
el = { name: '正方形', isActive: true, type: '正方形', area: 'tool-area', parentLimitation: false, w: 30, h: 30, x: -110, y: 205, zIndex: 1, borderColor: '#000', borderSize: 1, rotate: '', backgroundImage: '' }
}
this.elemList.push(el)
},
deleteElem () {
console.log(this.elemList, 1)
this.elemList.splice(this.activeIndex, 1)
console.log(this.elemList, 2)
},
onActivated (e, item, i) {
},
mouthDown (e, item, i) {
console.log('mouthDown', item.name, this.elemList)
this.elemList.forEach(el => {
el.isActive = false
})
item.isActive = true
this.maxIndex += 1
item.zIndex = this.maxIndex
this.activeIndex = i
console.log('onActivated')
this.activeElem = item
// if (item.area === 'tool-area' && e.left >= 0 && e.left <= 400 && e.top >= 0 && e.top <= 400) {
// item.parentLimitation = true
// }
},
mouthUp (e, item, i) {
},
onDragging (e, item) {
console.log('onDragging', item.name, e, this.elemList)
item.x = e.left
item.y = e.top
item.w = e.width
item.h = e.height
},
onDeactivated (e, item) {
// console.log(e, item, 'onDeactivated')
item.isActive = false
// if (item.area === 'tool-area' && e.left >= 0 && e.left <= 400 && e.top >= 0 && e.top <= 400) {
// item.parentLimitation = true
// this.elemList.push(Object.assign(item))
// }
},
changeSize (e, item) {
// 当内容超出轮廓线时会无法缩放,此时出发一次点击即可缩放,原因不知
console.log('changeSize', item.name, e, this.elemList)
item.x = e.left
item.y = e.top
item.w = e.width
item.h = e.height
}
},
mounted () {
console.log(this.activeElem, '1')
}
}
.home {
background-color: #f6f6f6;
width: 960px;
margin: 0 auto;
}
.img-mask {
position: fixed;
margin: 0;
left: 0;
right: 0;
top: 0;
bottom: 0;
z-index: 9999;
.img-wrap {
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
.el-icon-circle-close {
width: 30px;
height: 30px;
display: block;
position: absolute;
bottom: -30px;
left: 50%;
transform: translateX(-50%);
}
}
}
.main {
display: flex;
flex-direction: column;
align-items: center;
// justify-content: center;
width: 680px;
}
.tool-bar {
display: flex;
justify-content: space-between;
width: 100%;
background: #fff;
border-bottom: 1px solid rgba(57, 76, 96, 0.15);
height: 48px;
box-sizing: border-box;
position: relative;
.el-tooltip {
margin-left: 10px;
cursor: pointer;
}
.i-font {
font-size: 23px;
// cursor: pointer;
line-height: 28px;
}
.i-letter {
// cursor: pointer;
font-size: 23px;
min-width: 28px;
height: 28px;
line-height: 28px;
box-sizing: border-box;
border-radius: 4px;
}
.i-text {
font-size: 14px;
}
.isActive {
border: 1px solid #e6e6e6;
}
.shadow-wrap {
font-size: 12px;
}
.activeElem {
display: flex;
align-items: center;
}
}
.flex1-item {
margin: 5px 0;
// justify-content: space-between;
align-items: center;
}
.flex1-item-name {
min-width: 60px;
text-align: right;
}
.tool-bar-left {
display: flex;
align-items: center;
}
.edit-area {
margin-top: 30px;
}
.canvas_area {
width: 400px;
height: 400px;
}
.pre-area {
width: 400px;
height: 400px;
background-color: #fff;
word-break: break-all;
// margin: 0 auto;
display: flex;
align-items: center;
justify-content: center;
font-size: 50px;
line-height: 1;
position: relative;
box-sizing: border-box;
}
.vdr {
div {
width: 100%;
height: 100%;
}
}
.createImg {
margin-top: 20px;
}
.nowelem {
text-align: left;
}
.edit-wrap-left {
margin: 23px 10px 0 0;
}
.edit-wrap-right {
margin: 23px 0 0 10px;
}
.block {
background-color: #fff;
border: 1px solid #ebebeb;
border-radius: 3px;
transition: 0.2s;
box-sizing: border-box;
&:hover {
box-shadow: 0 0 8px 0 rgba(232, 237, 250, 0.6),
0 2px 4px 0 rgba(232, 237, 250, 0.5);
}
}
.edit-wrap {
width: 270px;
min-height: 400px;
}
.edit-title {
font-size: 16px;
padding: 5px;
border-bottom: 1px solid #ebebeb;
.bar {
justify-content: space-around;
}
}
.edit-content {
padding: 10px;
}
.item {
min-height: 30px;
display: flex;
align-items: center;
margin: 5px 0;
.el-slider {
width: 200px;
}
}
.item-name {
font-size: 14px;
// width: 80px;
text-align: right;
margin-left: 10px;
}
.txt-input {
width: 100px !important;
}
.inner-area {
display: flex;
align-items: center;
justify-content: center;
}
.dian {
width: 10px;
height: 10px;
border-radius: 50%;
background-color: #000;
}
.zhixian {
width: 1px;
height: 50px;
background-color: #000;
}
.yuanquan {
width: 50px;
height: 50px;
border: 1px solid #000;
border-radius: 50%;
}
.zhengfangxing {
width: 50px;
height: 50px;
border: 1px solid #000;
}
.upload-area {
width: 270px;
margin-top: 23px;
min-height: 170px;
img {
max-width: 250px;
height: 50px;
margin: 5px;
}
.fileList {
display: flex;
flex-wrap: wrap;
}
}
.el-form-item {
margin-bottom: 0 !important;
}
.el-form-item__content {
text-align: left;
line-height: 30px !important;
}
.el-upload-list {
display: none;
}