mirror of
https://github.com/pipipi-pikachu/PPTist.git
synced 2025-04-15 02:20:00 +08:00
refactor: 导出PPTX代码优化
This commit is contained in:
parent
6380098036
commit
f42b78b15a
@ -15,6 +15,9 @@ import { svg2Base64 } from '@/utils/svg2Base64'
|
|||||||
import { message } from 'ant-design-vue'
|
import { message } from 'ant-design-vue'
|
||||||
import useAddSlidesOrElements from '@/hooks/useAddSlidesOrElements'
|
import useAddSlidesOrElements from '@/hooks/useAddSlidesOrElements'
|
||||||
|
|
||||||
|
const INCH_PX_RATIO = 100
|
||||||
|
const PT_PX_RATIO = 0.75
|
||||||
|
|
||||||
interface ExportImageConfig {
|
interface ExportImageConfig {
|
||||||
quality: number
|
quality: number
|
||||||
width: number
|
width: number
|
||||||
@ -170,7 +173,7 @@ export default () => {
|
|||||||
const options: pptxgen.TextPropsOptions = {}
|
const options: pptxgen.TextPropsOptions = {}
|
||||||
|
|
||||||
if (styleObj['font-size']) {
|
if (styleObj['font-size']) {
|
||||||
options.fontSize = parseInt(styleObj['font-size']) * 0.75
|
options.fontSize = parseInt(styleObj['font-size']) * PT_PX_RATIO
|
||||||
}
|
}
|
||||||
if (styleObj['color']) {
|
if (styleObj['color']) {
|
||||||
options.color = formatColor(styleObj['color']).color
|
options.color = formatColor(styleObj['color']).color
|
||||||
@ -211,12 +214,12 @@ export default () => {
|
|||||||
if (styleObj['href']) options.hyperlink = { url: styleObj['href'] }
|
if (styleObj['href']) options.hyperlink = { url: styleObj['href'] }
|
||||||
|
|
||||||
if (bulletFlag && styleObj['list-type'] === 'ol') {
|
if (bulletFlag && styleObj['list-type'] === 'ol') {
|
||||||
options.bullet = { type: 'number', indent: 20 * 0.75 }
|
options.bullet = { type: 'number', indent: 20 * PT_PX_RATIO }
|
||||||
options.paraSpaceBefore = 0.1
|
options.paraSpaceBefore = 0.1
|
||||||
bulletFlag = false
|
bulletFlag = false
|
||||||
}
|
}
|
||||||
if (bulletFlag && styleObj['list-type'] === 'ul') {
|
if (bulletFlag && styleObj['list-type'] === 'ul') {
|
||||||
options.bullet = { indent: 20 * 0.75 }
|
options.bullet = { indent: 20 * PT_PX_RATIO }
|
||||||
options.paraSpaceBefore = 0.1
|
options.paraSpaceBefore = 0.1
|
||||||
bulletFlag = false
|
bulletFlag = false
|
||||||
}
|
}
|
||||||
@ -250,40 +253,40 @@ export default () => {
|
|||||||
}
|
}
|
||||||
else if (point.type === 'M') {
|
else if (point.type === 'M') {
|
||||||
return {
|
return {
|
||||||
x: point.x / 100 * scale.x,
|
x: point.x / INCH_PX_RATIO * scale.x,
|
||||||
y: point.y / 100 * scale.y,
|
y: point.y / INCH_PX_RATIO * scale.y,
|
||||||
moveTo: true,
|
moveTo: true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (point.curve) {
|
else if (point.curve) {
|
||||||
if (point.curve.type === 'cubic') {
|
if (point.curve.type === 'cubic') {
|
||||||
return {
|
return {
|
||||||
x: point.x / 100 * scale.x,
|
x: point.x / INCH_PX_RATIO * scale.x,
|
||||||
y: point.y / 100 * scale.y,
|
y: point.y / INCH_PX_RATIO * scale.y,
|
||||||
curve: {
|
curve: {
|
||||||
type: 'cubic',
|
type: 'cubic',
|
||||||
x1: (point.curve.x1 as number) / 100 * scale.x,
|
x1: (point.curve.x1 as number) / INCH_PX_RATIO * scale.x,
|
||||||
y1: (point.curve.y1 as number) / 100 * scale.y,
|
y1: (point.curve.y1 as number) / INCH_PX_RATIO * scale.y,
|
||||||
x2: (point.curve.x2 as number) / 100 * scale.x,
|
x2: (point.curve.x2 as number) / INCH_PX_RATIO * scale.x,
|
||||||
y2: (point.curve.y2 as number) / 100 * scale.y,
|
y2: (point.curve.y2 as number) / INCH_PX_RATIO * scale.y,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (point.curve.type === 'quadratic') {
|
else if (point.curve.type === 'quadratic') {
|
||||||
return {
|
return {
|
||||||
x: point.x / 100 * scale.x,
|
x: point.x / INCH_PX_RATIO * scale.x,
|
||||||
y: point.y / 100 * scale.y,
|
y: point.y / INCH_PX_RATIO * scale.y,
|
||||||
curve: {
|
curve: {
|
||||||
type: 'quadratic',
|
type: 'quadratic',
|
||||||
x1: (point.curve.x1 as number) / 100 * scale.x,
|
x1: (point.curve.x1 as number) / INCH_PX_RATIO * scale.x,
|
||||||
y1: (point.curve.y1 as number) / 100 * scale.y,
|
y1: (point.curve.y1 as number) / INCH_PX_RATIO * scale.y,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
x: point.x / 100 * scale.x,
|
x: point.x / INCH_PX_RATIO * scale.x,
|
||||||
y: point.y / 100 * scale.y,
|
y: point.y / INCH_PX_RATIO * scale.y,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -341,7 +344,7 @@ export default () => {
|
|||||||
type: 'outer',
|
type: 'outer',
|
||||||
color: c.color.replace('#', ''),
|
color: c.color.replace('#', ''),
|
||||||
opacity: c.alpha,
|
opacity: c.alpha,
|
||||||
blur: shadow.blur * 0.75,
|
blur: shadow.blur * PT_PX_RATIO,
|
||||||
offset,
|
offset,
|
||||||
angle,
|
angle,
|
||||||
}
|
}
|
||||||
@ -353,7 +356,7 @@ export default () => {
|
|||||||
return {
|
return {
|
||||||
color: c.color,
|
color: c.color,
|
||||||
transparency: (1 - c.alpha) * 100,
|
transparency: (1 - c.alpha) * 100,
|
||||||
width: (outline.width || 1) * 0.75,
|
width: (outline.width || 1) * PT_PX_RATIO,
|
||||||
dashType: outline.style === 'solid' ? 'solid' : 'dash',
|
dashType: outline.style === 'solid' ? 'solid' : 'dash',
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -415,21 +418,21 @@ export default () => {
|
|||||||
const textProps = formatHTML(el.content)
|
const textProps = formatHTML(el.content)
|
||||||
|
|
||||||
const options: pptxgen.TextPropsOptions = {
|
const options: pptxgen.TextPropsOptions = {
|
||||||
x: el.left / 100,
|
x: el.left / INCH_PX_RATIO,
|
||||||
y: el.top / 100,
|
y: el.top / INCH_PX_RATIO,
|
||||||
w: el.width / 100,
|
w: el.width / INCH_PX_RATIO,
|
||||||
h: el.height / 100,
|
h: el.height / INCH_PX_RATIO,
|
||||||
fontSize: 20 * 0.75,
|
fontSize: 20 * PT_PX_RATIO,
|
||||||
fontFace: '微软雅黑',
|
fontFace: '微软雅黑',
|
||||||
color: '#000000',
|
color: '#000000',
|
||||||
valign: 'top',
|
valign: 'top',
|
||||||
margin: 10 * 0.75,
|
margin: 10 * PT_PX_RATIO,
|
||||||
paraSpaceBefore: 5 * 0.75,
|
paraSpaceBefore: 5 * PT_PX_RATIO,
|
||||||
lineSpacingMultiple: 1.5 / 1.25,
|
lineSpacingMultiple: 1.5 / 1.25,
|
||||||
autoFit: true,
|
autoFit: true,
|
||||||
}
|
}
|
||||||
if (el.rotate) options.rotate = el.rotate
|
if (el.rotate) options.rotate = el.rotate
|
||||||
if (el.wordSpace) options.charSpacing = el.wordSpace * 0.75
|
if (el.wordSpace) options.charSpacing = el.wordSpace * PT_PX_RATIO
|
||||||
if (el.lineHeight) options.lineSpacingMultiple = el.lineHeight / 1.25
|
if (el.lineHeight) options.lineSpacingMultiple = el.lineHeight / 1.25
|
||||||
if (el.fill) {
|
if (el.fill) {
|
||||||
const c = formatColor(el.fill)
|
const c = formatColor(el.fill)
|
||||||
@ -441,7 +444,7 @@ export default () => {
|
|||||||
if (el.shadow) options.shadow = getShadowOption(el.shadow)
|
if (el.shadow) options.shadow = getShadowOption(el.shadow)
|
||||||
if (el.outline?.width) options.line = getOutlineOption(el.outline)
|
if (el.outline?.width) options.line = getOutlineOption(el.outline)
|
||||||
if (el.opacity !== undefined) options.transparency = (1 - el.opacity) * 100
|
if (el.opacity !== undefined) options.transparency = (1 - el.opacity) * 100
|
||||||
if (el.paragraphSpace !== undefined) options.paraSpaceBefore = el.paragraphSpace * 0.75
|
if (el.paragraphSpace !== undefined) options.paraSpaceBefore = el.paragraphSpace * PT_PX_RATIO
|
||||||
if (el.vertical) options.vert = 'eaVert'
|
if (el.vertical) options.vert = 'eaVert'
|
||||||
|
|
||||||
pptxSlide.addText(textProps, options)
|
pptxSlide.addText(textProps, options)
|
||||||
@ -450,10 +453,10 @@ export default () => {
|
|||||||
else if (el.type === 'image') {
|
else if (el.type === 'image') {
|
||||||
const options: pptxgen.ImageProps = {
|
const options: pptxgen.ImageProps = {
|
||||||
path: el.src,
|
path: el.src,
|
||||||
x: el.left / 100,
|
x: el.left / INCH_PX_RATIO,
|
||||||
y: el.top / 100,
|
y: el.top / INCH_PX_RATIO,
|
||||||
w: el.width / 100,
|
w: el.width / INCH_PX_RATIO,
|
||||||
h: el.height / 100,
|
h: el.height / INCH_PX_RATIO,
|
||||||
}
|
}
|
||||||
if (el.flipH) options.flipH = el.flipH
|
if (el.flipH) options.flipH = el.flipH
|
||||||
if (el.flipV) options.flipV = el.flipV
|
if (el.flipV) options.flipV = el.flipV
|
||||||
@ -470,18 +473,18 @@ export default () => {
|
|||||||
const [startX, startY] = start
|
const [startX, startY] = start
|
||||||
const [endX, endY] = end
|
const [endX, endY] = end
|
||||||
|
|
||||||
const originW = el.width / ((endX - startX) / 100)
|
const originW = el.width / ((endX - startX) / INCH_PX_RATIO)
|
||||||
const originH = el.height / ((endY - startY) / 100)
|
const originH = el.height / ((endY - startY) / INCH_PX_RATIO)
|
||||||
|
|
||||||
options.w = originW / 100
|
options.w = originW / INCH_PX_RATIO
|
||||||
options.h = originH / 100
|
options.h = originH / INCH_PX_RATIO
|
||||||
|
|
||||||
options.sizing = {
|
options.sizing = {
|
||||||
type: 'crop',
|
type: 'crop',
|
||||||
x: startX / 100 * originW / 100,
|
x: startX / INCH_PX_RATIO * originW / INCH_PX_RATIO,
|
||||||
y: startY / 100 * originH / 100,
|
y: startY / INCH_PX_RATIO * originH / INCH_PX_RATIO,
|
||||||
w: (endX - startX) / 100 * originW / 100,
|
w: (endX - startX) / INCH_PX_RATIO * originW / INCH_PX_RATIO,
|
||||||
h: (endY - startY) / 100 * originH / 100,
|
h: (endY - startY) / INCH_PX_RATIO * originH / INCH_PX_RATIO,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -495,10 +498,10 @@ export default () => {
|
|||||||
|
|
||||||
const options: pptxgen.ImageProps = {
|
const options: pptxgen.ImageProps = {
|
||||||
data: base64SVG,
|
data: base64SVG,
|
||||||
x: el.left / 100,
|
x: el.left / INCH_PX_RATIO,
|
||||||
y: el.top / 100,
|
y: el.top / INCH_PX_RATIO,
|
||||||
w: el.width / 100,
|
w: el.width / INCH_PX_RATIO,
|
||||||
h: el.height / 100,
|
h: el.height / INCH_PX_RATIO,
|
||||||
}
|
}
|
||||||
if (el.rotate) options.rotate = el.rotate
|
if (el.rotate) options.rotate = el.rotate
|
||||||
if (el.link) {
|
if (el.link) {
|
||||||
@ -519,10 +522,10 @@ export default () => {
|
|||||||
const opacity = el.opacity === undefined ? 1 : el.opacity
|
const opacity = el.opacity === undefined ? 1 : el.opacity
|
||||||
|
|
||||||
const options: pptxgen.ShapeProps = {
|
const options: pptxgen.ShapeProps = {
|
||||||
x: el.left / 100,
|
x: el.left / INCH_PX_RATIO,
|
||||||
y: el.top / 100,
|
y: el.top / INCH_PX_RATIO,
|
||||||
w: el.width / 100,
|
w: el.width / INCH_PX_RATIO,
|
||||||
h: el.height / 100,
|
h: el.height / INCH_PX_RATIO,
|
||||||
fill: { color: fillColor.color, transparency: (1 - fillColor.alpha * opacity) * 100 },
|
fill: { color: fillColor.color, transparency: (1 - fillColor.alpha * opacity) * 100 },
|
||||||
points,
|
points,
|
||||||
}
|
}
|
||||||
@ -541,14 +544,14 @@ export default () => {
|
|||||||
const textProps = formatHTML(el.text.content)
|
const textProps = formatHTML(el.text.content)
|
||||||
|
|
||||||
const options: pptxgen.TextPropsOptions = {
|
const options: pptxgen.TextPropsOptions = {
|
||||||
x: el.left / 100,
|
x: el.left / INCH_PX_RATIO,
|
||||||
y: el.top / 100,
|
y: el.top / INCH_PX_RATIO,
|
||||||
w: el.width / 100,
|
w: el.width / INCH_PX_RATIO,
|
||||||
h: el.height / 100,
|
h: el.height / INCH_PX_RATIO,
|
||||||
fontSize: 20 * 0.75,
|
fontSize: 20 * PT_PX_RATIO,
|
||||||
fontFace: '微软雅黑',
|
fontFace: '微软雅黑',
|
||||||
color: '#000000',
|
color: '#000000',
|
||||||
paraSpaceBefore: 5 * 0.75,
|
paraSpaceBefore: 5 * PT_PX_RATIO,
|
||||||
valign: el.text.align,
|
valign: el.text.align,
|
||||||
}
|
}
|
||||||
if (el.rotate) options.rotate = el.rotate
|
if (el.rotate) options.rotate = el.rotate
|
||||||
@ -566,14 +569,14 @@ export default () => {
|
|||||||
const c = formatColor(el.color)
|
const c = formatColor(el.color)
|
||||||
|
|
||||||
const options: pptxgen.ShapeProps = {
|
const options: pptxgen.ShapeProps = {
|
||||||
x: el.left / 100,
|
x: el.left / INCH_PX_RATIO,
|
||||||
y: el.top / 100,
|
y: el.top / INCH_PX_RATIO,
|
||||||
w: (maxX - minX) / 100,
|
w: (maxX - minX) / INCH_PX_RATIO,
|
||||||
h: (maxY - minY) / 100,
|
h: (maxY - minY) / INCH_PX_RATIO,
|
||||||
line: {
|
line: {
|
||||||
color: c.color,
|
color: c.color,
|
||||||
transparency: (1 - c.alpha) * 100,
|
transparency: (1 - c.alpha) * 100,
|
||||||
width: el.width * 0.75,
|
width: el.width * PT_PX_RATIO,
|
||||||
dashType: el.style === 'solid' ? 'solid' : 'dash',
|
dashType: el.style === 'solid' ? 'solid' : 'dash',
|
||||||
beginArrowType: el.points[0] ? 'arrow' : 'none',
|
beginArrowType: el.points[0] ? 'arrow' : 'none',
|
||||||
endArrowType: el.points[1] ? 'arrow' : 'none',
|
endArrowType: el.points[1] ? 'arrow' : 'none',
|
||||||
@ -606,19 +609,19 @@ export default () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const options: pptxgen.IChartOpts = {
|
const options: pptxgen.IChartOpts = {
|
||||||
x: el.left / 100,
|
x: el.left / INCH_PX_RATIO,
|
||||||
y: el.top / 100,
|
y: el.top / INCH_PX_RATIO,
|
||||||
w: el.width / 100,
|
w: el.width / INCH_PX_RATIO,
|
||||||
h: el.height / 100,
|
h: el.height / INCH_PX_RATIO,
|
||||||
chartColors: el.chartType === 'pie' ? chartColors : chartColors.slice(0, el.data.series.length),
|
chartColors: el.chartType === 'pie' ? chartColors : chartColors.slice(0, el.data.series.length),
|
||||||
}
|
}
|
||||||
|
|
||||||
if (el.fill) options.fill = formatColor(el.fill).color
|
if (el.fill) options.plotArea = { fill: { color: formatColor(el.fill).color } }
|
||||||
if (el.legend) {
|
if (el.legend) {
|
||||||
options.showLegend = true
|
options.showLegend = true
|
||||||
options.legendPos = el.legend === 'top' ? 't' : 'b'
|
options.legendPos = el.legend === 'top' ? 't' : 'b'
|
||||||
options.legendColor = formatColor(el.gridColor || '#000000').color
|
options.legendColor = formatColor(el.gridColor || '#000000').color
|
||||||
options.legendFontSize = 14 * 0.75
|
options.legendFontSize = 14 * PT_PX_RATIO
|
||||||
}
|
}
|
||||||
|
|
||||||
let type = pptx.ChartType.bar
|
let type = pptx.ChartType.bar
|
||||||
@ -689,7 +692,7 @@ export default () => {
|
|||||||
align: cell.style?.align || 'left',
|
align: cell.style?.align || 'left',
|
||||||
valign: 'middle',
|
valign: 'middle',
|
||||||
fontFace: cell.style?.fontname || '微软雅黑',
|
fontFace: cell.style?.fontname || '微软雅黑',
|
||||||
fontSize: (cell.style?.fontsize ? parseInt(cell.style?.fontsize) : 14) * 0.75,
|
fontSize: (cell.style?.fontsize ? parseInt(cell.style?.fontsize) : 14) * PT_PX_RATIO,
|
||||||
}
|
}
|
||||||
if (theme && themeColor) {
|
if (theme && themeColor) {
|
||||||
let c: FormatColor
|
let c: FormatColor
|
||||||
@ -720,17 +723,17 @@ export default () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const options: pptxgen.TableProps = {
|
const options: pptxgen.TableProps = {
|
||||||
x: el.left / 100,
|
x: el.left / INCH_PX_RATIO,
|
||||||
y: el.top / 100,
|
y: el.top / INCH_PX_RATIO,
|
||||||
w: el.width / 100,
|
w: el.width / INCH_PX_RATIO,
|
||||||
h: el.height / 100,
|
h: el.height / INCH_PX_RATIO,
|
||||||
colW: el.colWidths.map(item => el.width * item / 100),
|
colW: el.colWidths.map(item => el.width * item / INCH_PX_RATIO),
|
||||||
}
|
}
|
||||||
if (el.theme) options.fill = { color: '#ffffff' }
|
if (el.theme) options.fill = { color: '#ffffff' }
|
||||||
if (el.outline.width && el.outline.color) {
|
if (el.outline.width && el.outline.color) {
|
||||||
options.border = {
|
options.border = {
|
||||||
type: el.outline.style === 'solid' ? 'solid' : 'dash',
|
type: el.outline.style === 'solid' ? 'solid' : 'dash',
|
||||||
pt: el.outline.width * 0.75,
|
pt: el.outline.width * PT_PX_RATIO,
|
||||||
color: formatColor(el.outline.color).color,
|
color: formatColor(el.outline.color).color,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -744,10 +747,10 @@ export default () => {
|
|||||||
|
|
||||||
const options: pptxgen.ImageProps = {
|
const options: pptxgen.ImageProps = {
|
||||||
data: base64SVG,
|
data: base64SVG,
|
||||||
x: el.left / 100,
|
x: el.left / INCH_PX_RATIO,
|
||||||
y: el.top / 100,
|
y: el.top / INCH_PX_RATIO,
|
||||||
w: el.width / 100,
|
w: el.width / INCH_PX_RATIO,
|
||||||
h: el.height / 100,
|
h: el.height / INCH_PX_RATIO,
|
||||||
}
|
}
|
||||||
if (el.link) {
|
if (el.link) {
|
||||||
const linkOption = getLinkOption(el.link)
|
const linkOption = getLinkOption(el.link)
|
||||||
@ -758,10 +761,13 @@ export default () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pptx.writeFile({ fileName: `pptist.pptx` }).then(() => exporting.value = false).catch(() => {
|
|
||||||
exporting.value = false
|
setTimeout(() => {
|
||||||
message.error('导出失败')
|
pptx.writeFile({ fileName: `pptist.pptx` }).then(() => exporting.value = false).catch(() => {
|
||||||
})
|
exporting.value = false
|
||||||
|
message.error('导出失败')
|
||||||
|
})
|
||||||
|
}, 200)
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user