export default class Printctrl {
|
/**
|
* @description 绘制模板至缓存
|
* @param {Object} configs 配置信息
|
* @param {Boolean} selectId 编辑元素
|
*/
|
static sketch (configs, selectId, debug = false) {
|
if (!configs.height || !configs.width) return
|
|
if (configs.height / configs.width > 10 || configs.width / configs.height > 10) return
|
|
let ratio = parseInt(document.getElementById('darea').style.width) / configs.width * (window.devicePixelRatio || 1) * 1.5
|
let sizeradio = 210 / configs.width * (window.devicePixelRatio || 1) * 1.5
|
let canvas = document.createElement('canvas')
|
|
canvas.height = configs.height * ratio
|
canvas.width = configs.width * ratio
|
let context = canvas.getContext('2d')
|
|
if (configs.elements.length > 0) {
|
let elements = JSON.parse(JSON.stringify(configs.elements))
|
elements.forEach(element => {
|
element.left = element.left * ratio
|
element.top = element.top * ratio
|
element.oriwidth = element.width
|
element.oriheight = element.height
|
element.width = element.width * ratio
|
element.height = element.height * ratio
|
|
if (element.type === 'text') {
|
element.padding = element.padding * ratio
|
element.fontSize = element.fontSize * sizeradio
|
} else if (element.type === 'barcode') {
|
element.barcodeWidth = element.barcodeWidth * ratio
|
element.barcodeHeight = element.barcodeHeight * ratio
|
element.fontSize = element.fontSize * sizeradio
|
} else if (element.type === 'qrcode') {
|
element.qrcodeWidth = element.qrcodeWidth * ratio
|
|
if (element.qrcodeWidth > element.height) {
|
element.qrcodeWidth = element.height
|
}
|
if (element.qrcodeWidth > element.width) {
|
element.qrcodeWidth = element.width
|
}
|
} else if (element.type === 'image') {
|
element.imgWidth = element.imgWidth * ratio
|
element.imgHeight = element.imgHeight * ratio
|
}
|
})
|
|
return new Promise(resolve => {
|
this.sketchothers(context, elements, selectId, debug, ratio, resolve)
|
})
|
} else {
|
return new Promise(resolve => {
|
this.cachesketch(context, resolve)
|
})
|
}
|
}
|
|
/**
|
* @description 绘制图片及文字
|
* @param {Object} context 画布对象
|
* @param {Object} elements 图片文字信息
|
*/
|
static sketchothers (context, elements, selectId, debug, ratio, resolve) {
|
let element = elements.splice(0, 1)[0] // 逐个绘制图片文字
|
let textLineSpace = 5 // 绘制时行间距,防止文字重叠
|
context.save()
|
|
// if (element.rotate) { // 元素旋转时,设置画布旋转角度
|
// let _cx = element.left + element.width / 2
|
// let _cy = element.top + element.height / 2
|
// context.translate(_cx, _cy) // 移动原点
|
// context.rotate(element.rotate * Math.PI / 180)
|
// context.translate(-_cx, -_cy) // 恢复原点
|
// }
|
|
if (selectId === element.uuid) { // 选中元素,设置外部阴影
|
context.shadowBlur = 5
|
context.shadowColor = '#1890ff'
|
context.fillStyle = 'white'
|
context.fillRect(element.left, element.top, element.width || 1, element.height || 1)
|
context.shadowBlur = 0
|
} else if (debug) {
|
context.shadowBlur = 3
|
context.shadowColor = 'orange'
|
context.fillStyle = 'white'
|
context.fillRect(element.left, element.top, element.width || 1, element.height || 1)
|
context.shadowBlur = 0
|
}
|
|
// 绘制边框
|
// context.rect(element.left + element.borderSize / 2, element.top + element.borderSize / 2, element.width - element.borderSize, element.height - element.borderSize)
|
if (element.borderSize >= 1) {
|
context.beginPath()
|
context.strokeStyle = element.borderColor
|
context.lineWidth = element.borderSize
|
context.rect(element.left, element.top, element.width, element.height)
|
context.stroke()
|
}
|
|
// 设置背景色
|
if (!element.borderSize && (element.oriwidth === 1 || element.oriheight === 1)) { // 线
|
context.strokeStyle = element.background
|
context.beginPath()
|
if (element.oriwidth === 1) {
|
context.moveTo(element.left, element.top)
|
context.lineTo(element.left, element.top + element.height)
|
} else {
|
context.moveTo(element.left, element.top + element.height)
|
context.lineTo(element.left + element.width, element.top + element.height)
|
}
|
context.stroke()
|
} else if (element.background && element.background !== 'white') {
|
context.fillStyle = element.background
|
context.fillRect(element.left, element.top, element.width, element.height)
|
}
|
|
if (selectId === element.uuid && element.width > 3 * ratio && element.height > 3 * ratio) { // 选中元素,设置外部阴影
|
context.strokeStyle = '#1890ff'
|
context.beginPath()
|
context.moveTo(element.left + element.width - 7, element.top + element.height - 2)
|
context.lineTo(element.left + element.width - 2, element.top + element.height - 7)
|
context.moveTo(element.left + element.width - 14, element.top + element.height - 2)
|
context.lineTo(element.left + element.width - 2, element.top + element.height - 14)
|
context.stroke()
|
}
|
|
if (!element.width || !element.height) {
|
context.restore() // 重置画布
|
if (elements.length > 0) {
|
this.sketchothers(context, elements, selectId, debug, ratio, resolve)
|
} else {
|
this.cachesketch(context, resolve)
|
}
|
} else if (element.type === 'text') {
|
// 绘制文字信息
|
if (element.fontSize < 12) { // 浏览器最小字体
|
textLineSpace += 12 - element.fontSize
|
}
|
// italic 斜体 small-caps(英文小写字母变成小的大写)
|
context.font = 'normal normal ' + element.fontWeight + ' ' + element.fontSize + 'px ' + element.fontFamily
|
context.fillStyle = element.fontColor
|
|
let lines = element.value.split('\n')
|
|
if (!element.value && element.field) {
|
if (element.field === 'other_field') {
|
lines = [element.cusfield || '']
|
} else {
|
lines = [element.field]
|
}
|
}
|
let _y = element.top + element.padding + element.fontSize + element.borderSize
|
let _left = element.left + element.borderSize + element.padding
|
let _right = element.left + element.width - element.padding - element.borderSize
|
let _width = _right - _left
|
if (element.vertialAlign === 'top') {
|
lines.forEach(text => {
|
if (!text) {
|
_y += element.fontSize + textLineSpace
|
}
|
let _textArr = []
|
let _text = ''
|
text.split('').forEach(word => {
|
if (context.measureText(_text + word).width <= _width) {
|
_text = _text + word
|
} else {
|
_textArr.push(_text)
|
_text = word
|
}
|
})
|
_textArr.forEach(word => {
|
let _l = _left
|
if (element.align === 'center') {
|
_l = _left + (_width - context.measureText(word).width) / 2
|
} else if (element.align === 'right') {
|
_l = _right - context.measureText(word).width
|
} else if (element.align === 'justify') {
|
_l = _left + (_width - context.measureText(word).width) / 2
|
}
|
context.fillText(word, _l, _y)
|
_y += element.fontSize + textLineSpace
|
})
|
|
if (!_text) {
|
return
|
}
|
|
if (element.align === 'left') {
|
context.fillText(_text, _left, _y)
|
} else if (element.align === 'center') {
|
context.fillText(_text, _left + (_width - context.measureText(_text).width) / 2, _y)
|
} else if (element.align === 'right') {
|
context.fillText(_text, _right - context.measureText(_text).width, _y)
|
} else if (element.align === 'justify') {
|
if (_text.length === 1) {
|
context.fillText(_text, _left + (_width - context.measureText(_text).width) / 2, _y)
|
} else {
|
let _dleft = _left
|
_text.split('').forEach(_word => {
|
context.fillText(_word, _dleft, _y)
|
_dleft += (_width - context.measureText(_text).width) / (_text.length - 1) + context.measureText(_word).width
|
})
|
}
|
}
|
|
_y += element.fontSize + textLineSpace
|
})
|
} else if (element.vertialAlign === 'middle' || element.vertialAlign === 'bottom') {
|
let lineheight = 0
|
lines.forEach(text => {
|
if (!text) {
|
lineheight += element.fontSize + textLineSpace
|
return
|
}
|
lineheight += Math.ceil(context.measureText(text).width / _width) * (element.fontSize + textLineSpace)
|
})
|
|
if (element.vertialAlign === 'middle') {
|
_y += (element.height - element.padding * 2 - element.borderSize * 2 - lineheight) / 2
|
} else {
|
_y += element.height - element.padding * 2 - element.borderSize * 2 - lineheight
|
}
|
|
lines.forEach(text => {
|
if (!text) {
|
_y += element.fontSize + textLineSpace
|
}
|
let _textArr = []
|
let _text = ''
|
text.split('').forEach(word => {
|
if (context.measureText(_text + word).width <= _width) {
|
_text = _text + word
|
} else {
|
_textArr.push(_text)
|
_text = word
|
}
|
})
|
_textArr.forEach(word => {
|
let _l = _left
|
if (element.align === 'center') {
|
_l = _left + (_width - context.measureText(word).width) / 2
|
} else if (element.align === 'right') {
|
_l = _right - context.measureText(word).width
|
} else if (element.align === 'justify') {
|
_l = _left + (_width - context.measureText(word).width) / 2
|
}
|
context.fillText(word, _l, _y)
|
_y += element.fontSize + textLineSpace
|
})
|
|
if (!_text) {
|
return
|
}
|
|
if (element.align === 'left') {
|
context.fillText(_text, _left, _y)
|
} else if (element.align === 'center') {
|
context.fillText(_text, _left + (_width - context.measureText(_text).width) / 2, _y)
|
} else if (element.align === 'right') {
|
context.fillText(_text, _right - context.measureText(_text).width, _y)
|
} else if (element.align === 'justify') {
|
if (_text.length === 1) {
|
context.fillText(_text, _left + (_width - context.measureText(_text).width) / 2, _y)
|
} else {
|
let _dleft = _left
|
_text.split('').forEach(_word => {
|
context.fillText(_word, _dleft, _y)
|
_dleft += (_width - context.measureText(_text).width) / (_text.length - 1) + context.measureText(_word).width
|
})
|
}
|
}
|
|
_y += element.fontSize + textLineSpace
|
})
|
}
|
|
context.restore() // 重置画布
|
if (elements.length > 0) {
|
this.sketchothers(context, elements, selectId, debug, ratio, resolve)
|
} else {
|
this.cachesketch(context, resolve)
|
}
|
} else if (element.type === 'barcode') {
|
let _space = 5
|
let _left = element.left
|
let _top = element.top
|
if (element.vertialAlign === 'middle') {
|
if (element.barcodeLabel === 'true') {
|
_top = element.top + (element.height - element.barcodeHeight - element.fontSize - _space) / 2
|
} else {
|
_top = element.top + (element.height - element.barcodeHeight) / 2
|
}
|
} else if (element.vertialAlign === 'bottom') {
|
if (element.barcodeLabel === 'true') {
|
_top = element.top + (element.height - element.barcodeHeight - element.fontSize - _space)
|
} else {
|
_top = element.top + element.height - element.barcodeHeight
|
}
|
}
|
|
if (element.align === 'center') {
|
_left = element.left + (element.width - element.barcodeWidth) / 2
|
} else if (element.align === 'right') {
|
_left = element.left + element.width - element.barcodeWidth
|
}
|
context.font = 'normal normal normal ' + element.fontSize + 'px Microsoft YaHei'
|
context.fillStyle = 'black'
|
let text = '1234567890123'
|
let _tleft = _left + (element.barcodeWidth - context.measureText(text).width) / 2
|
let _ttop = _top + element.barcodeHeight + _space + element.fontSize
|
|
let image = new Image()
|
image.src = element.url
|
if (image.complete) {
|
context.drawImage(image, _left, _top, element.barcodeWidth, element.barcodeHeight)
|
if (element.barcodeLabel === 'true') {
|
context.fillText(text, _tleft, _ttop)
|
}
|
|
context.restore() // 重置画布
|
if (elements.length > 0) {
|
this.sketchothers(context, elements, selectId, debug, ratio, resolve)
|
} else {
|
this.cachesketch(context, resolve)
|
}
|
} else {
|
image.onload = () => {
|
context.drawImage(image, _left, _top, element.barcodeWidth, element.barcodeHeight)
|
if (element.barcodeLabel === 'true') {
|
context.fillText(text, _tleft, _ttop)
|
}
|
|
context.restore() // 重置画布
|
if (elements.length > 0) {
|
this.sketchothers(context, elements, selectId, debug, ratio, resolve)
|
} else {
|
this.cachesketch(context, resolve)
|
}
|
}
|
}
|
} else if (element.type === 'qrcode') {
|
let _left = element.left
|
let _top = element.top
|
if (element.vertialAlign === 'middle') {
|
_top = element.top + (element.height - element.qrcodeWidth) / 2
|
} else if (element.vertialAlign === 'bottom') {
|
_top = element.top + element.height - element.qrcodeWidth
|
}
|
|
if (element.align === 'center') {
|
_left = element.left + (element.width - element.qrcodeWidth) / 2
|
} else if (element.align === 'right') {
|
_left = element.left + element.width - element.qrcodeWidth
|
}
|
|
let image = new Image()
|
image.src = element.url
|
|
if (image.complete) {
|
context.drawImage(image, _left, _top, element.qrcodeWidth, element.qrcodeWidth)
|
|
context.restore() // 重置画布
|
if (elements.length > 0) {
|
this.sketchothers(context, elements, selectId, debug, ratio, resolve)
|
} else {
|
this.cachesketch(context, resolve)
|
}
|
} else {
|
image.onload = () => {
|
context.drawImage(image, _left, _top, element.qrcodeWidth, element.qrcodeWidth)
|
|
context.restore() // 重置画布
|
if (elements.length > 0) {
|
this.sketchothers(context, elements, selectId, debug, ratio, resolve)
|
} else {
|
this.cachesketch(context, resolve)
|
}
|
}
|
}
|
} else if (element.type === 'image') {
|
let _left = element.left
|
let _top = element.top
|
if (element.vertialAlign === 'middle') {
|
_top = element.top + (element.height - element.imgHeight) / 2
|
} else if (element.vertialAlign === 'bottom') {
|
_top = element.top + element.height - element.imgHeight
|
}
|
|
if (element.align === 'center') {
|
_left = element.left + (element.width - element.imgWidth) / 2
|
} else if (element.align === 'right') {
|
_left = element.left + element.width - element.imgWidth
|
}
|
|
let image = new Image()
|
image.src = element.url
|
if (element.value && element.value.indexOf(window.location.hostname) > -1) {
|
image.src = element.value
|
}
|
|
if (image.complete) {
|
context.drawImage(image, _left, _top, element.imgWidth, element.imgHeight)
|
|
context.restore() // 重置画布
|
if (elements.length > 0) {
|
this.sketchothers(context, elements, selectId, debug, ratio, resolve)
|
} else {
|
this.cachesketch(context, resolve)
|
}
|
} else {
|
image.onload = () => {
|
context.drawImage(image, _left, _top, element.imgWidth, element.imgHeight)
|
|
context.restore() // 重置画布
|
if (elements.length > 0) {
|
this.sketchothers(context, elements, selectId, debug, ratio, resolve)
|
} else {
|
this.cachesketch(context, resolve)
|
}
|
}
|
}
|
image.onerror = () => {
|
context.restore() // 重置画布
|
if (elements.length > 0) {
|
this.sketchothers(context, elements, selectId, debug, ratio, resolve)
|
} else {
|
this.cachesketch(context, resolve)
|
}
|
}
|
}
|
}
|
|
/**
|
* @description 绘制模板值页面
|
* @param {Object} configs 配置信息
|
*/
|
static cachesketch (context, resolve) {
|
let cacheCanvas = context.canvas
|
let canvas = document.getElementById('darea')
|
|
canvas.width = cacheCanvas.width
|
canvas.height = cacheCanvas.height
|
let ctx = canvas.getContext('2d')
|
ctx.clearRect(0, 0, canvas.width + 1, canvas.height + 1)
|
ctx.beginPath()
|
ctx.fillStyle = 'white'
|
ctx.fillRect(0, 0, canvas.width + 1, canvas.height + 1)
|
ctx.drawImage(cacheCanvas, 0, 0, canvas.width, canvas.height)
|
resolve(canvas.toDataURL('image/png'))
|
}
|
}
|