From fb130e76a05b5b86c35a60bbcea1421c15e91e14 Mon Sep 17 00:00:00 2001 From: veasion Date: Tue, 24 Sep 2024 16:13:57 +0800 Subject: [PATCH] modify --- static/cover.js | 2 +- static/element.js | 696 ++++++------ static/ppt2canvas.js | 2558 +++++++++++++++++++++--------------------- static/ppt2svg.js | 2 +- 4 files changed, 1629 insertions(+), 1629 deletions(-) diff --git a/static/cover.js b/static/cover.js index a1fb256..9ae2df2 100644 --- a/static/cover.js +++ b/static/cover.js @@ -1,4 +1,4 @@ -// import { Ppt2Canvas } from './ppt2Canvas.js' +// import { Ppt2Canvas } from './ppt2canvas.js' async function drawPptxFun(pptxObj, idx) { let canvas = document.createElement('canvas') diff --git a/static/element.js b/static/element.js index 7ffe889..e08ace5 100644 --- a/static/element.js +++ b/static/element.js @@ -1,23 +1,23 @@ // 创建空白页 function createPage(page, width, height) { return { - page: page || 1, - extInfo: { - background: { - realType: 'Background', - anchor: [0, 0, width || 960, height || 540], - fillStyle: { - type: 'color', - color: { - color: -1, - realColor: -1 - } - } - }, - slideMasterIdx: 0, - slideLayoutIdx: 0 - }, - children: [] + page: page || 1, + extInfo: { + background: { + realType: 'Background', + anchor: [0, 0, width || 960, height || 540], + fillStyle: { + type: 'color', + color: { + color: -1, + realColor: -1 + } + } + }, + slideMasterIdx: 0, + slideLayoutIdx: 0 + }, + children: [] } } @@ -158,48 +158,48 @@ function createGeometry(geometryName, fillStyle, strokeStylePaint) { } return { id: `${id}`, - type: 'text', - depth: 1, - point: [...anchor], - extInfo: { - property: { - realType: 'Auto', - shapeType: geometryName, - anchor: [...anchor], - fillStyle: {...fillStyle}, - strokeStyle: { - paint: {...strokeStylePaint}, - lineWidth: 1, - lineCap: 'FLAT', - lineDash: 'SOLID', - lineCompound: 'SINGLE' - }, - geometry: { - name: geometryName, - data: null, - avLst: null - }, - textAutofit: 'NORMAL', - textDirection: 'HORIZONTAL', - textVerticalAlignment: 'MIDDLE', - textInsets: [3.6, 7.2, 3.6, 7.2] - } - }, - children: [ - { - id: `${id}_p`, - pid: `${id}`, - type: 'p', - depth: 2, - extInfo: { - property: { - textAlign: 'CENTER', - leftMargin: 0 - } - }, + type: 'text', + depth: 1, + point: [...anchor], + extInfo: { + property: { + realType: 'Auto', + shapeType: geometryName, + anchor: [...anchor], + fillStyle: {...fillStyle}, + strokeStyle: { + paint: {...strokeStylePaint}, + lineWidth: 1, + lineCap: 'FLAT', + lineDash: 'SOLID', + lineCompound: 'SINGLE' + }, + geometry: { + name: geometryName, + data: null, + avLst: null + }, + textAutofit: 'NORMAL', + textDirection: 'HORIZONTAL', + textVerticalAlignment: 'MIDDLE', + textInsets: [3.6, 7.2, 3.6, 7.2] + } + }, + children: [ + { + id: `${id}_p`, + pid: `${id}`, + type: 'p', + depth: 2, + extInfo: { + property: { + textAlign: 'CENTER', + leftMargin: 0 + } + }, children: [] - } - ] + } + ] } } @@ -217,36 +217,36 @@ function createImage(src, width, height) { const anchor = [(960 - width) / 2, (540 - height) / 2, width, height] const contentType = extension == '.png' ? 'image/png' : 'image/jpeg' return { - id: id, - depth: 1, - type: 'image', - point: [...anchor], - extInfo: { - property: { + id: id, + depth: 1, + type: 'image', + point: [...anchor], + extInfo: { + property: { image: src, - anchor: [...anchor], - extension: extension, - fileName: 'image' + extension, - contentType: contentType, - fillStyle: { - type: 'texture', - texture: { - imageData: '$image', - flipMode: 'NONE', - insets: [0, 0, 0, 0], - stretch: [0, 0, 0, 0], - contentType: contentType - } - }, - flipHorizontal: false, - flipVertical: false, - realType: 'Picture', - geometry: { - name: 'rect' - } - } - }, - children: [] + anchor: [...anchor], + extension: extension, + fileName: 'image' + extension, + contentType: contentType, + fillStyle: { + type: 'texture', + texture: { + imageData: '$image', + flipMode: 'NONE', + insets: [0, 0, 0, 0], + stretch: [0, 0, 0, 0], + contentType: contentType + } + }, + flipHorizontal: false, + flipVertical: false, + realType: 'Picture', + geometry: { + name: 'rect' + } + } + }, + children: [] } } @@ -279,13 +279,13 @@ function createTable(rowColumnDataList, rowFillStyles, borderColor, fontColor) { } }, { - type: 'color', - color: { - color: -7555288, - realColor: -2823519, - lumMod: 40000, - lumOff: 60000 - } + type: 'color', + color: { + color: -7555288, + realColor: -2823519, + lumMod: 40000, + lumOff: 60000 + } } ] } @@ -308,117 +308,117 @@ function createTable(rowColumnDataList, rowFillStyles, borderColor, fontColor) { for (let j = 0; j < columnNum; j++) { let text = rowColumnDataList[i][j] columns.push({ - id: `${id}_r${i}_c${j}`, - pid: `${id}_r${i}`, - type: 'tableColumn', - depth: 3, - extInfo: { - property: { - realType: 'TableCell', - anchor: [tableAnchor[0] + colWidth * j + lineWidth * (j + 1), tableAnchor[1] + rowHeight * i + lineWidth * (i + 1), colWidth, rowHeight], - fillStyle: {...fillStyle}, - strokeStyle: {}, - geometry: { - name: 'tableColumn' - }, - textAutofit: 'NORMAL', - textDirection: 'HORIZONTAL', - textVerticalAlignment: 'MIDDLE', - textInsets: [3.6, 7.2, 3.6, 7.2], - columnWidth: colWidth, - borders: [ - { - color: borderColor, - lineWidth: lineWidth, - lineCap: 'FLAT', - lineDash: 'SOLID', - lineCompound: 'SINGLE' - }, - { - color: borderColor, - lineWidth: lineWidth, - lineCap: 'FLAT', - lineDash: 'SOLID', - lineCompound: 'SINGLE' - }, - { - color: borderColor, - lineWidth: lineWidth, - lineCap: 'FLAT', - lineDash: 'SOLID', - lineCompound: 'SINGLE' - }, - { - color: borderColor, - lineWidth: lineWidth, - lineCap: 'FLAT', - lineDash: 'SOLID', - lineCompound: 'SINGLE' - } - ] - } - }, - children: [ - { - id: `${id}_r${i}_c${j}_p`, - pid: `${id}_r${i}_c${j}`, - type: 'p', - depth: 4, - extInfo: { - property: { - textAlign: textAlign, - leftMargin: 0 - } - }, - children: [ - { - id: `${id}_r${i}_c${j}_p_r`, - pid: `${id}_r${i}_c${j}_p`, - type: 'r', - text: text, - depth: 5, - extInfo: { - property: { - fontSize: fontSize, - fontColor: {...fontColor}, - lang: 'zh-CN' - } - } - } - ] - } - ] + id: `${id}_r${i}_c${j}`, + pid: `${id}_r${i}`, + type: 'tableColumn', + depth: 3, + extInfo: { + property: { + realType: 'TableCell', + anchor: [tableAnchor[0] + colWidth * j + lineWidth * (j + 1), tableAnchor[1] + rowHeight * i + lineWidth * (i + 1), colWidth, rowHeight], + fillStyle: {...fillStyle}, + strokeStyle: {}, + geometry: { + name: 'tableColumn' + }, + textAutofit: 'NORMAL', + textDirection: 'HORIZONTAL', + textVerticalAlignment: 'MIDDLE', + textInsets: [3.6, 7.2, 3.6, 7.2], + columnWidth: colWidth, + borders: [ + { + color: borderColor, + lineWidth: lineWidth, + lineCap: 'FLAT', + lineDash: 'SOLID', + lineCompound: 'SINGLE' + }, + { + color: borderColor, + lineWidth: lineWidth, + lineCap: 'FLAT', + lineDash: 'SOLID', + lineCompound: 'SINGLE' + }, + { + color: borderColor, + lineWidth: lineWidth, + lineCap: 'FLAT', + lineDash: 'SOLID', + lineCompound: 'SINGLE' + }, + { + color: borderColor, + lineWidth: lineWidth, + lineCap: 'FLAT', + lineDash: 'SOLID', + lineCompound: 'SINGLE' + } + ] + } + }, + children: [ + { + id: `${id}_r${i}_c${j}_p`, + pid: `${id}_r${i}_c${j}`, + type: 'p', + depth: 4, + extInfo: { + property: { + textAlign: textAlign, + leftMargin: 0 + } + }, + children: [ + { + id: `${id}_r${i}_c${j}_p_r`, + pid: `${id}_r${i}_c${j}_p`, + type: 'r', + text: text, + depth: 5, + extInfo: { + property: { + fontSize: fontSize, + fontColor: {...fontColor}, + lang: 'zh-CN' + } + } + } + ] + } + ] }) } rows.push({ - id: `${id}_r${i}`, - pid: `${id}`, - type: 'tableRow', - depth: 2, - extInfo: { - property: { - rowHeight: rowHeight - } - }, - children: columns + id: `${id}_r${i}`, + pid: `${id}`, + type: 'tableRow', + depth: 2, + extInfo: { + property: { + rowHeight: rowHeight + } + }, + children: columns }) } return { - id: `${id}`, - pid: null, - type: 'table', - text: null, - depth: 1, - point: [...tableAnchor], - extInfo: { - property: { - anchor: [...tableAnchor], - realType: 'table', + id: `${id}`, + pid: null, + type: 'table', + text: null, + depth: 1, + point: [...tableAnchor], + extInfo: { + property: { + anchor: [...tableAnchor], + realType: 'table', numberOfRows: rowNum, - numberOfColumns: columnNum - } - }, - children: rows + numberOfColumns: columnNum + } + }, + children: rows } } @@ -477,70 +477,70 @@ function createPieChart(rowColumnDataList, holeSize, colors) { }) } const chartData = { - chartType: holeSize ? 'doughnut' : 'pie', - series: [ - { - text: { - formula: 'Sheet1!$B$1', - formatCode: null, - data: [rowColumnDataList[0][1]] - }, - category: { - formula: 'Sheet1!$A$2:$A$' + rowColumnDataList.length, - formatCode: null, - data: rowColumnDataList.map(s => s[0]).splice(1) - }, - value: { - formula: 'Sheet1!$B$2:$B$' + rowColumnDataList.length, - formatCode: 'General', - data: rowColumnDataList.map(s => s[1]).splice(1) - }, - dataPoint: dataPoint, - property: null - } - ], - categoryAxis: null, - valueAxes: null, - extInfo: holeSize ? { holeSize: holeSize } : {} + chartType: holeSize ? 'doughnut' : 'pie', + series: [ + { + text: { + formula: 'Sheet1!$B$1', + formatCode: null, + data: [rowColumnDataList[0][1]] + }, + category: { + formula: 'Sheet1!$A$2:$A$' + rowColumnDataList.length, + formatCode: null, + data: rowColumnDataList.map(s => s[0]).splice(1) + }, + value: { + formula: 'Sheet1!$B$2:$B$' + rowColumnDataList.length, + formatCode: 'General', + data: rowColumnDataList.map(s => s[1]).splice(1) + }, + dataPoint: dataPoint, + property: null + } + ], + categoryAxis: null, + valueAxes: null, + extInfo: holeSize ? { holeSize: holeSize } : {} } return { - id: id, - type: 'graphicFrame', - depth: 1, - point: [...anchor], - extInfo: { - property: { - anchor: [...anchor], - chart: { - title: '', - legend: { - position: 'BOTTOM', - property: { - anchor: null, - fillStyle: { - type: 'noFill' - }, - strokeStyle: { - paint: { - type: 'noFill' - } - }, - geometry: null, - shadow: null - } - }, - excelData: [ - { - sheetName: 'Sheet1', - rows: rowColumnDataList - } - ], - chartData: [chartData] - }, - realType: 'graphicFrame' - } - }, - children: [] + id: id, + type: 'graphicFrame', + depth: 1, + point: [...anchor], + extInfo: { + property: { + anchor: [...anchor], + chart: { + title: '', + legend: { + position: 'BOTTOM', + property: { + anchor: null, + fillStyle: { + type: 'noFill' + }, + strokeStyle: { + paint: { + type: 'noFill' + } + }, + geometry: null, + shadow: null + } + }, + excelData: [ + { + sheetName: 'Sheet1', + rows: rowColumnDataList + } + ], + chartData: [chartData] + }, + realType: 'graphicFrame' + } + }, + children: [] } } @@ -598,94 +598,94 @@ function createBarLineChart(title, chartType, rowColumnDataList, colors) { extInfo = { majorGridlines: 'true' } } return { - id: id, - type: 'graphicFrame', - depth: 1, - point: [...anchor], - extInfo: { - property: { - anchor: [...anchor], - chart: { - title: title, - legend: { - position: 'BOTTOM', - property: { - anchor: null, - fillStyle: { - type: 'noFill' - }, - strokeStyle: { - paint: { - type: 'noFill' - } - }, - geometry: null, - shadow: null - } - }, - excelData: [ - { - sheetName: 'Sheet1', - rows: rowColumnDataList - } - ], - chartData: [ - { - chartType: chartType, - series: series, - categoryAxis: { - position: 'BOTTOM', - deleted: false, - property: { - anchor: null, - fillStyle: { - type: 'noFill' - }, - strokeStyle: { - paint: { - type: 'color', - color: { - realColor: -2500135, - color: -16777216, - lumMod: 15000, - lumOff: 85000 - } - }, - lineWidth: 0.75, - lineCap: 'FLAT', - lineCompound: 'SINGLE' - }, - geometry: null, - shadow: null - } - }, - valueAxes: [ - { - position: 'LEFT', - deleted: false, - property: { - anchor: null, - fillStyle: { - type: 'noFill' - }, - strokeStyle: { - paint: { - type: 'noFill' - } - }, - geometry: null, - shadow: null - } - } - ], - extInfo: extInfo - } - ] - }, - realType: 'graphicFrame' - } - }, - children: [] + id: id, + type: 'graphicFrame', + depth: 1, + point: [...anchor], + extInfo: { + property: { + anchor: [...anchor], + chart: { + title: title, + legend: { + position: 'BOTTOM', + property: { + anchor: null, + fillStyle: { + type: 'noFill' + }, + strokeStyle: { + paint: { + type: 'noFill' + } + }, + geometry: null, + shadow: null + } + }, + excelData: [ + { + sheetName: 'Sheet1', + rows: rowColumnDataList + } + ], + chartData: [ + { + chartType: chartType, + series: series, + categoryAxis: { + position: 'BOTTOM', + deleted: false, + property: { + anchor: null, + fillStyle: { + type: 'noFill' + }, + strokeStyle: { + paint: { + type: 'color', + color: { + realColor: -2500135, + color: -16777216, + lumMod: 15000, + lumOff: 85000 + } + }, + lineWidth: 0.75, + lineCap: 'FLAT', + lineCompound: 'SINGLE' + }, + geometry: null, + shadow: null + } + }, + valueAxes: [ + { + position: 'LEFT', + deleted: false, + property: { + anchor: null, + fillStyle: { + type: 'noFill' + }, + strokeStyle: { + paint: { + type: 'noFill' + } + }, + geometry: null, + shadow: null + } + } + ], + extInfo: extInfo + } + ] + }, + realType: 'graphicFrame' + } + }, + children: [] } } diff --git a/static/ppt2canvas.js b/static/ppt2canvas.js index 894c09e..0e6bad5 100644 --- a/static/ppt2canvas.js +++ b/static/ppt2canvas.js @@ -1,1327 +1,1327 @@ -/* eslint-disable @typescript-eslint/no-unused-vars */ +/* eslint-disable no-unused-vars */ /* eslint-disable no-self-assign */ // import { geometryPaths } from './geometry.js' // import { drawChart } from './chart.js' function Ppt2Canvas(_canvas, imageCrossOrigin) { - var canvas = (typeof _canvas == 'string') ? document.getElementById(_canvas) : _canvas - var ctx = canvas.getContext('2d') - var pptx = null - var page = null - var idMap = {} - var imageCache = {} - var pageIndex = 0 - var templateHandle = null + var canvas = (typeof _canvas == 'string') ? document.getElementById(_canvas) : _canvas + var ctx = canvas.getContext('2d') + var pptx = null + var page = null + var idMap = {} + var imageCache = {} + var pageIndex = 0 + var templateHandle = null - this.drawPptx = async (pptxObj, pageIdx) => { - idMap = {} - imageCache = {} - pptx = pptxObj - pageIndex = pageIdx - page = pptxObj.pages[pageIdx] - canvas.width = canvas.width - canvas.height = canvas.height - ctx.scaleX = canvas.width / pptxObj.width - ctx.scaleY = canvas.height / pptxObj.height - ctx.scale(ctx.scaleX, ctx.scaleY) - ctx.interior = ctx._interior = null - let placeholder = {} - let slideMasterIdx = page.extInfo.slideMasterIdx - if (slideMasterIdx != null && pptxObj.slideMasters) { - let slideMaster = pptxObj.slideMasters[slideMasterIdx] - let slideLayoutIdx = page.extInfo.slideLayoutIdx - let slideLayout = slideLayoutIdx != null ? slideMaster.slideLayouts[slideLayoutIdx] : null - await drawBackground(page.extInfo.background || (slideLayout || {}).background || slideMaster.background) - await drawSlideMaster(slideMaster, slideLayout, placeholder) - if (slideLayout) { - await drawSlideLayout(slideLayout, placeholder) - } - } else { - await drawBackground(page.extInfo.background) - } - if (!page.children) { - return - } - recursion(page.children, obj => { - idMap[obj.id] = obj - if (obj.extInfo.property && obj.extInfo.property.placeholder) { - // 继承母版占位符 - let element_property = obj.extInfo.property - let placeholder_property = placeholder[element_property.placeholder.type] || {} - for (let k in placeholder_property) { - if (element_property[k] == null) { - element_property[k] = placeholder_property[k] - } - } - } - }) - for (let i = 0; i < page.children.length; i++) { - await drawElement(page.children[i]) - } - recursion(page.children, obj => { - idMap[obj.id] = obj - }) - } + this.drawPptx = async (pptxObj, pageIdx) => { + idMap = {} + imageCache = {} + pptx = pptxObj + pageIndex = pageIdx + page = pptxObj.pages[pageIdx] + canvas.width = canvas.width + canvas.height = canvas.height + ctx.scaleX = canvas.width / pptxObj.width + ctx.scaleY = canvas.height / pptxObj.height + ctx.scale(ctx.scaleX, ctx.scaleY) + ctx.interior = ctx._interior = null + let placeholder = {} + let slideMasterIdx = page.extInfo.slideMasterIdx + if (slideMasterIdx != null && pptxObj.slideMasters) { + let slideMaster = pptxObj.slideMasters[slideMasterIdx] + let slideLayoutIdx = page.extInfo.slideLayoutIdx + let slideLayout = slideLayoutIdx != null ? slideMaster.slideLayouts[slideLayoutIdx] : null + await drawBackground(page.extInfo.background || (slideLayout || {}).background || slideMaster.background) + await drawSlideMaster(slideMaster, slideLayout, placeholder) + if (slideLayout) { + await drawSlideLayout(slideLayout, placeholder) + } + } else { + await drawBackground(page.extInfo.background) + } + if (!page.children) { + return + } + recursion(page.children, obj => { + idMap[obj.id] = obj + if (obj.extInfo.property && obj.extInfo.property.placeholder) { + // 继承母版占位符 + let element_property = obj.extInfo.property + let placeholder_property = placeholder[element_property.placeholder.type] || {} + for (let k in placeholder_property) { + if (element_property[k] == null) { + element_property[k] = placeholder_property[k] + } + } + } + }) + for (let i = 0; i < page.children.length; i++) { + await drawElement(page.children[i]) + } + recursion(page.children, obj => { + idMap[obj.id] = obj + }) + } - this.getCanvas = () => { - return canvas - } + this.getCanvas = () => { + return canvas + } - this.resetSize = (width, height) => { - canvas.width = width * 2 - canvas.height = height * 2 - canvas.style.width = width + 'px' - canvas.style.height = height + 'px' - if (pptx) { - this.drawPptx(pptx, pageIndex) - } - } + this.resetSize = (width, height) => { + canvas.width = width * 2 + canvas.height = height * 2 + canvas.style.width = width + 'px' + canvas.style.height = height + 'px' + if (pptx) { + this.drawPptx(pptx, pageIndex) + } + } - async function drawElement(obj) { - ctx.fillStyle = 'transparent' - ctx.strokeStyle = 'transparent' - if (obj.noDraw || !obj.extInfo.property.anchor || obj.extInfo.property.hidden) { - // console.log('ignore element:', obj) - return - } - if (obj.type == 'text' || obj.type == 'freeform') { - await drawText(obj) - } else if (obj.type == 'image') { - await drawImage(obj) - } else if (obj.type == 'diagram') { - await drawDiagram(obj) - } else if (obj.type == 'container') { - await drawContainer(obj) - } else if (obj.type == 'table') { - await drawTable(obj) - } else if (obj.type == 'connector') { - await drawConnector(obj) - } else if (obj.type == 'graphicFrame') { - await drawGraphicFrame(obj) - } - } + async function drawElement(obj) { + ctx.fillStyle = 'transparent' + ctx.strokeStyle = 'transparent' + if (obj.noDraw || !obj.extInfo.property.anchor || obj.extInfo.property.hidden) { + // console.log('ignore element:', obj) + return + } + if (obj.type == 'text' || obj.type == 'freeform') { + await drawText(obj) + } else if (obj.type == 'image') { + await drawImage(obj) + } else if (obj.type == 'diagram') { + await drawDiagram(obj) + } else if (obj.type == 'container') { + await drawContainer(obj) + } else if (obj.type == 'table') { + await drawTable(obj) + } else if (obj.type == 'connector') { + await drawConnector(obj) + } else if (obj.type == 'graphicFrame') { + await drawGraphicFrame(obj) + } + } - async function drawText(obj) { - let property = obj.extInfo.property - let geometryName = (property.geometry || {}).name || 'rect' - ctx.save() - shapeHandle(property) - let marginTop = property.strokeStyle ? (property.strokeStyle.lineWidth || 1) : 0 - if (geometryName == 'tableColumn') { - await drawTableColumn(property) - } else { - await drawGeometry(property) - } - let anchor = property.anchor - let cx = anchor[0] + anchor[2] / 2 - let cy = anchor[1] + anchor[3] / 2 - let x = ctx.groupFlipX || 1 - let y = ctx.groupFlipY || 1 - if (property.flipHorizontal) { - x *= -1 - } - if (property.flipVertical) { - y *= -1 - } - if (y == -1) { - if (x == 1) { - ctx.translate(cx, cy) - ctx.scale(-1, 1) - ctx.translate(-cx, -cy) - } - } else if (x == -1) { - ctx.translate(cx, cy) - ctx.scale(-1, 1) - ctx.translate(-cx, -cy) - } - if (templateHandle) { - await templateHandle('text', obj, ctx) - } - if (obj.children) { - let textInsets = property.textInsets || [0, 0, 0, 0] - let isVertical = property.textDirection && property.textDirection.indexOf('VERTICAL') > -1 - let verticalAlignment = property.textVerticalAlignment - if (!isVertical && (verticalAlignment == 'MIDDLE' || verticalAlignment == 'BOTTOM')) { - let totalTextHeight = calcTextHeight(obj) - if (totalTextHeight < property.anchor[3]) { - if (verticalAlignment == 'MIDDLE') { - marginTop += (property.anchor[3] - totalTextHeight - textInsets[0] - textInsets[2]) / 2 + textInsets[0] - } else if (verticalAlignment == 'BOTTOM') { - marginTop += (property.anchor[3] - totalTextHeight - textInsets[2]) - } - } - } else { - marginTop += textInsets[0] - } - for (let i = 0; i < obj.children.length; i++) { - let p = obj.children[i] - if (isVertical) { - await drawTextP(obj, p, isVertical, 0, i) - } else { - marginTop += await drawTextP(obj, p, isVertical, marginTop, i) - } - } - } - ctx.restore() - } + async function drawText(obj) { + let property = obj.extInfo.property + let geometryName = (property.geometry || {}).name || 'rect' + ctx.save() + shapeHandle(property) + let marginTop = property.strokeStyle ? (property.strokeStyle.lineWidth || 1) : 0 + if (geometryName == 'tableColumn') { + await drawTableColumn(property) + } else { + await drawGeometry(property) + } + let anchor = property.anchor + let cx = anchor[0] + anchor[2] / 2 + let cy = anchor[1] + anchor[3] / 2 + let x = ctx.groupFlipX || 1 + let y = ctx.groupFlipY || 1 + if (property.flipHorizontal) { + x *= -1 + } + if (property.flipVertical) { + y *= -1 + } + if (y == -1) { + if (x == 1) { + ctx.translate(cx, cy) + ctx.scale(-1, 1) + ctx.translate(-cx, -cy) + } + } else if (x == -1) { + ctx.translate(cx, cy) + ctx.scale(-1, 1) + ctx.translate(-cx, -cy) + } + if (templateHandle) { + await templateHandle('text', obj, ctx) + } + if (obj.children) { + let textInsets = property.textInsets || [0, 0, 0, 0] + let isVertical = property.textDirection && property.textDirection.indexOf('VERTICAL') > -1 + let verticalAlignment = property.textVerticalAlignment + if (!isVertical && (verticalAlignment == 'MIDDLE' || verticalAlignment == 'BOTTOM')) { + let totalTextHeight = calcTextHeight(obj) + if (totalTextHeight < property.anchor[3]) { + if (verticalAlignment == 'MIDDLE') { + marginTop += (property.anchor[3] - totalTextHeight - textInsets[0] - textInsets[2]) / 2 + textInsets[0] + } else if (verticalAlignment == 'BOTTOM') { + marginTop += (property.anchor[3] - totalTextHeight - textInsets[2]) + } + } + } else { + marginTop += textInsets[0] + } + for (let i = 0; i < obj.children.length; i++) { + let p = obj.children[i] + if (isVertical) { + await drawTextP(obj, p, isVertical, 0, i) + } else { + marginTop += await drawTextP(obj, p, isVertical, marginTop, i) + } + } + } + ctx.restore() + } - function calcTextHeight(obj) { - let totalTextHeight = 0 - let wordWrap = obj.extInfo.property.textWordWrap ?? true - let textInsets = obj.extInfo.property.textInsets || [0, 0, 0, 0] - let wInset = textInsets[1] + textInsets[3] - for (let i = 0; i < obj.children.length; i++) { - let p = obj.children[i] - let lineSpacing = p.extInfo.property.lineSpacing > 0 ? (p.extInfo.property.lineSpacing / 100) : (1 + Math.abs(p.extInfo.property.lineSpacing || 0) / 100) - let maxFontSize = 0 - let underlined = false - let totalTextWidth = 0 - for (let j = 0; j < p.children.length; j++) { - let r_property = p.children[j].extInfo.property - let fontSize = r_property.fontSize || 16 - let text = p.children[j].text - if (text == '\n') { - totalTextHeight += lineSpacing * fontSize - continue - } - if (fontSize > maxFontSize) { - maxFontSize = fontSize - } - if (r_property.underlined) { - underlined = true - } - let fonts = [] - if (r_property.bold) { - fonts.push('bold') - } - if (r_property.italic) { - fonts.push('italic') - } - fonts.push(fontSize + 'px') - fonts.push('"' + (r_property.fontFamily || '等线') + '"') - ctx.font = fonts.join(' ') - let lines = text.split('\n') - let maxTextWidth = 0 - for (let s = 0; s < lines.length; s++) { - let width = ctx.measureText(lines[s]).width - if (width > maxTextWidth) { - maxTextWidth = width - } - } - totalTextWidth += maxTextWidth - if (lines.length > 1) { - totalTextHeight += (lines.length - 1) * lineSpacing * fontSize - } - } - if (wordWrap) { - let lineNum = parseInt((totalTextWidth - 1) / (obj.extInfo.property.anchor[2] - wInset)) + 1 - totalTextHeight += lineNum * lineSpacing * maxFontSize - } else { - totalTextHeight += lineSpacing * maxFontSize - } - if (underlined) { - totalTextHeight += 1 - } - } - return totalTextHeight - } + function calcTextHeight(obj) { + let totalTextHeight = 0 + let wordWrap = obj.extInfo.property.textWordWrap ?? true + let textInsets = obj.extInfo.property.textInsets || [0, 0, 0, 0] + let wInset = textInsets[1] + textInsets[3] + for (let i = 0; i < obj.children.length; i++) { + let p = obj.children[i] + let lineSpacing = p.extInfo.property.lineSpacing > 0 ? (p.extInfo.property.lineSpacing / 100) : (1 + Math.abs(p.extInfo.property.lineSpacing || 0) / 100) + let maxFontSize = 0 + let underlined = false + let totalTextWidth = 0 + for (let j = 0; j < p.children.length; j++) { + let r_property = p.children[j].extInfo.property + let fontSize = r_property.fontSize || 16 + let text = p.children[j].text + if (text == '\n') { + totalTextHeight += lineSpacing * fontSize + continue + } + if (fontSize > maxFontSize) { + maxFontSize = fontSize + } + if (r_property.underlined) { + underlined = true + } + let fonts = [] + if (r_property.bold) { + fonts.push('bold') + } + if (r_property.italic) { + fonts.push('italic') + } + fonts.push(fontSize + 'px') + fonts.push('"' + (r_property.fontFamily || '等线') + '"') + ctx.font = fonts.join(' ') + let lines = text.split('\n') + let maxTextWidth = 0 + for (let s = 0; s < lines.length; s++) { + let width = ctx.measureText(lines[s]).width + if (width > maxTextWidth) { + maxTextWidth = width + } + } + totalTextWidth += maxTextWidth + if (lines.length > 1) { + totalTextHeight += (lines.length - 1) * lineSpacing * fontSize + } + } + if (wordWrap) { + let lineNum = parseInt((totalTextWidth - 1) / (obj.extInfo.property.anchor[2] - wInset)) + 1 + totalTextHeight += lineNum * lineSpacing * maxFontSize + } else { + totalTextHeight += lineSpacing * maxFontSize + } + if (underlined) { + totalTextHeight += 1 + } + } + return totalTextHeight + } - async function drawTextP(textObj, p, isVertical, marginTop, pIdx) { - if (!p.children) { - return - } - let fontList = [] - let underlined = false - let totalTextWidth = 0 - let anchor = textObj.extInfo.property.anchor - let wordWrap = textObj.extInfo.property.textWordWrap ?? true - for (let i = 0; i < p.children.length; i++) { - let r = p.children[i] - let property = r.extInfo.property - let fontSize = property.fontSize || 16 - let fonts = [] - if (property.bold) { - fonts.push('bold') - } - if (property.italic) { - fonts.push('italic') - } - if (property.slideNum) { - r.text = (pageIndex + 1) + '' - } - fonts.push(fontSize + 'px') - fonts.push('"' + (property.fontFamily || '等线') + '"') - let font = fonts.join(' ') - fontList.push(font) - ctx.font = font - if (isVertical) { - if (property.lang == 'en-US' && /^[0-9a-zA-Z]+$/.test(r.text)) { - if (fontSize > totalTextWidth) { - totalTextWidth = fontSize - } - } else if (r.text.length > 0) { - let width = ctx.measureText(r.text[0]).width - if (width > totalTextWidth) { - totalTextWidth = width - } - } - } else { - let lines = r.text.split('\n') - let maxTextWidth = 0 - for (let s = 0; s < lines.length; s++) { - let width = ctx.measureText(lines[s]).width - if (width > maxTextWidth) { - maxTextWidth = width - } - } - totalTextWidth += maxTextWidth - } - if (property.underlined) { - underlined = true - } - } - if (wordWrap) { - totalTextWidth = Math.min(totalTextWidth, anchor[2]) - } - let textAlign = p.extInfo.property.textAlign - let verticalAlignment = textObj.extInfo.property.textVerticalAlignment - let textInsets = textObj.extInfo.property.textInsets || [0, 0, 0, 0] - let lineSpacing = p.extInfo.property.lineSpacing > 0 ? (p.extInfo.property.lineSpacing / 100) : (1 + Math.abs(p.extInfo.property.lineSpacing || 0) / 100) - let x = anchor[0] - let y = anchor[1] + (marginTop || 0) - let endX = anchor[0] + anchor[2] - textInsets[3] - ctx.textAlign = 'left' - ctx.textBaseline = 'top' - if (textAlign == 'CENTER') { - x = x + (anchor[2] - totalTextWidth - textInsets[1] - textInsets[3]) / 2 + textInsets[1] - } else if (textAlign == 'RIGHT') { - x = x + anchor[2] - textInsets[3] - totalTextWidth - } else { - x = x + textInsets[1] - } - const _x = x - const _y = y - let lastWord = null - let maxFontSize = 0 - for (let i = 0; i < p.children.length; i++) { - let r = p.children[i] - let property = r.extInfo.property - let fontSize = property.fontSize || 16 - let drawString = (s, x, y) => { - doShadow(ctx, property.shadow) - ctx.translate(x, y) - ctx.fillText(s, 0, 0) - ctx.translate(-x, -y) - } - let fillStyle = await toPaint(property.fontColor, anchor) - ctx.fillStyle = fillStyle - if (property.line && (property.fontColor == null || property.fontColor.type == 'noFill')) { - drawString = (s, x, y) => { - doShadow(ctx, property.shadow) - ctx.translate(x, y) - ctx.strokeText(s, 0, 0) - ctx.translate(-x, -y) - } - ctx.strokeStyle = await toPaint(property.line.paint, anchor) - } - ctx.font = fontList[i] - if (fontSize > maxFontSize) { - maxFontSize = fontSize - } - if (r.text == '\n') { - y += lineSpacing * fontSize - x = _x - continue - } - if (isVertical) { - // 竖版 - x = x + fontSize * pIdx - if (property.lang == 'en-US' && /^[0-9a-zA-Z]+$/.test(r.text)) { - // 数字英文竖着的时候需要旋转90°方式呈现 - let textWidth = ctx.measureText(r.text).width - let fontSize = property.fontSize || 16 - ctx.save() - ctx.translate(x, y + fontSize) - ctx.rotate(90 * Math.PI / 180) - ctx.translate(-x, -y - fontSize) - drawString(r.text, x - fontSize, y) - ctx.restore() - y += textWidth - } else { - for (let j = 0; j < r.text.length; j++) { - let text = r.text[j] - drawString(text, x, y) - y += fontSize - } - } - if (property.underlined) { - let lineX = x - let lineY = _y - ctx.lineWidth = 1 - ctx.strokeStyle = fillStyle - ctx.beginPath() - ctx.moveTo(lineX, lineY) - ctx.lineTo(lineX, lineY + (y - _y)) - ctx.closePath() - ctx.stroke() - } - } else if (wordWrap) { - // 横版-自动换行 - let texts = splitWords(r.text) - let drawLine = (textWidth) => { - if (property.underlined) { - let lineX = _x - let lineY = y - if (verticalAlignment == 'MIDDLE') { - lineY = lineY + fontSize / 2 + 1 - } else if (verticalAlignment == 'BOTTOM') { - lineY = lineY + 1 - } else { - lineY = lineY + fontSize + 1 - } - ctx.lineWidth = 1 - ctx.strokeStyle = fillStyle - ctx.beginPath() - ctx.moveTo(lineX, lineY) - ctx.lineTo(lineX + textWidth, lineY) - ctx.closePath() - ctx.stroke() - } - } - for (let j = 0; j < texts.length; j++) { - let item = texts[j] - if (item.text == '\n') { - x = _x - y += lineSpacing * fontSize - lastWord = null - continue - } - if (item.word && lastWord != null && !lastWord) { - let textWidth = ctx.measureText(item.text).width - if (x + textWidth > endX + fontSize / 4) { - drawLine(x - _x) - x = _x - y += lineSpacing * fontSize - } - } - for (let s = 0; s < item.text.length; s++) { - let text = item.text[s] - let textWidth = ctx.measureText(text).width - if (x + textWidth > endX + fontSize / 4 && !isSymbol(text)) { - drawLine(x - _x) - x = _x - y += lineSpacing * fontSize - } - let ty = y - if (verticalAlignment == 'MIDDLE') { - ctx.textBaseline = 'middle' - ty = ty + (lineSpacing * fontSize) / 2 - } else if (verticalAlignment == 'BOTTOM') { - ctx.textBaseline = 'bottom' - ty = ty + (lineSpacing * fontSize) - } else { - ctx.textBaseline = 'top' - } - drawString(text, x, ty) - x += textWidth - } - lastWord = item.word - } - if (i == p.children.length - 1) { - drawLine(x - _x) - } - } else { - // 横版-不自动换行 - let lines = r.text.split('\n') - for (let s = 0; s < lines.length; s++) { - if (s != 0) { - x = _x - y += lineSpacing * fontSize - } - let ty = y - if (verticalAlignment == 'MIDDLE') { - ctx.textBaseline = 'middle' - ty = ty + (lineSpacing * fontSize) / 2 - } else if (verticalAlignment == 'BOTTOM') { - ctx.textBaseline = 'bottom' - ty = ty + (lineSpacing * fontSize) - } else { - ctx.textBaseline = 'top' - } - drawString(lines[s], x, ty) - let textWidth = ctx.measureText(lines[s]).width - if (property.underlined) { - let lineX = x - let lineY = y - if (verticalAlignment == 'MIDDLE') { - lineY = lineY + fontSize / 2 + 1 - } else if (verticalAlignment == 'BOTTOM') { - lineY = lineY + 1 - } else { - lineY = lineY + fontSize + 1 - } - ctx.lineWidth = 1 - ctx.strokeStyle = fillStyle - ctx.beginPath() - ctx.moveTo(lineX, lineY) - ctx.lineTo(lineX + textWidth, lineY) - ctx.closePath() - ctx.stroke() - } - x += textWidth - } - } - } - return (y - _y) + (underlined && !isVertical ? 1 : 0) + lineSpacing * maxFontSize - } + async function drawTextP(textObj, p, isVertical, marginTop, pIdx) { + if (!p.children) { + return + } + let fontList = [] + let underlined = false + let totalTextWidth = 0 + let anchor = textObj.extInfo.property.anchor + let wordWrap = textObj.extInfo.property.textWordWrap ?? true + for (let i = 0; i < p.children.length; i++) { + let r = p.children[i] + let property = r.extInfo.property + let fontSize = property.fontSize || 16 + let fonts = [] + if (property.bold) { + fonts.push('bold') + } + if (property.italic) { + fonts.push('italic') + } + if (property.slideNum) { + r.text = (pageIndex + 1) + '' + } + fonts.push(fontSize + 'px') + fonts.push('"' + (property.fontFamily || '等线') + '"') + let font = fonts.join(' ') + fontList.push(font) + ctx.font = font + if (isVertical) { + if (property.lang == 'en-US' && /^[0-9a-zA-Z]+$/.test(r.text)) { + if (fontSize > totalTextWidth) { + totalTextWidth = fontSize + } + } else if (r.text.length > 0) { + let width = ctx.measureText(r.text[0]).width + if (width > totalTextWidth) { + totalTextWidth = width + } + } + } else { + let lines = r.text.split('\n') + let maxTextWidth = 0 + for (let s = 0; s < lines.length; s++) { + let width = ctx.measureText(lines[s]).width + if (width > maxTextWidth) { + maxTextWidth = width + } + } + totalTextWidth += maxTextWidth + } + if (property.underlined) { + underlined = true + } + } + if (wordWrap) { + totalTextWidth = Math.min(totalTextWidth, anchor[2]) + } + let textAlign = p.extInfo.property.textAlign + let verticalAlignment = textObj.extInfo.property.textVerticalAlignment + let textInsets = textObj.extInfo.property.textInsets || [0, 0, 0, 0] + let lineSpacing = p.extInfo.property.lineSpacing > 0 ? (p.extInfo.property.lineSpacing / 100) : (1 + Math.abs(p.extInfo.property.lineSpacing || 0) / 100) + let x = anchor[0] + let y = anchor[1] + (marginTop || 0) + let endX = anchor[0] + anchor[2] - textInsets[3] + ctx.textAlign = 'left' + ctx.textBaseline = 'top' + if (textAlign == 'CENTER') { + x = x + (anchor[2] - totalTextWidth - textInsets[1] - textInsets[3]) / 2 + textInsets[1] + } else if (textAlign == 'RIGHT') { + x = x + anchor[2] - textInsets[3] - totalTextWidth + } else { + x = x + textInsets[1] + } + const _x = x + const _y = y + let lastWord = null + let maxFontSize = 0 + for (let i = 0; i < p.children.length; i++) { + let r = p.children[i] + let property = r.extInfo.property + let fontSize = property.fontSize || 16 + let drawString = (s, x, y) => { + doShadow(ctx, property.shadow) + ctx.translate(x, y) + ctx.fillText(s, 0, 0) + ctx.translate(-x, -y) + } + let fillStyle = await toPaint(property.fontColor, anchor) + ctx.fillStyle = fillStyle + if (property.line && (property.fontColor == null || property.fontColor.type == 'noFill')) { + drawString = (s, x, y) => { + doShadow(ctx, property.shadow) + ctx.translate(x, y) + ctx.strokeText(s, 0, 0) + ctx.translate(-x, -y) + } + ctx.strokeStyle = await toPaint(property.line.paint, anchor) + } + ctx.font = fontList[i] + if (fontSize > maxFontSize) { + maxFontSize = fontSize + } + if (r.text == '\n') { + y += lineSpacing * fontSize + x = _x + continue + } + if (isVertical) { + // 竖版 + x = x + fontSize * pIdx + if (property.lang == 'en-US' && /^[0-9a-zA-Z]+$/.test(r.text)) { + // 数字英文竖着的时候需要旋转90°方式呈现 + let textWidth = ctx.measureText(r.text).width + let fontSize = property.fontSize || 16 + ctx.save() + ctx.translate(x, y + fontSize) + ctx.rotate(90 * Math.PI / 180) + ctx.translate(-x, -y - fontSize) + drawString(r.text, x - fontSize, y) + ctx.restore() + y += textWidth + } else { + for (let j = 0; j < r.text.length; j++) { + let text = r.text[j] + drawString(text, x, y) + y += fontSize + } + } + if (property.underlined) { + let lineX = x + let lineY = _y + ctx.lineWidth = 1 + ctx.strokeStyle = fillStyle + ctx.beginPath() + ctx.moveTo(lineX, lineY) + ctx.lineTo(lineX, lineY + (y - _y)) + ctx.closePath() + ctx.stroke() + } + } else if (wordWrap) { + // 横版-自动换行 + let texts = splitWords(r.text) + let drawLine = (textWidth) => { + if (property.underlined) { + let lineX = _x + let lineY = y + if (verticalAlignment == 'MIDDLE') { + lineY = lineY + fontSize / 2 + 1 + } else if (verticalAlignment == 'BOTTOM') { + lineY = lineY + 1 + } else { + lineY = lineY + fontSize + 1 + } + ctx.lineWidth = 1 + ctx.strokeStyle = fillStyle + ctx.beginPath() + ctx.moveTo(lineX, lineY) + ctx.lineTo(lineX + textWidth, lineY) + ctx.closePath() + ctx.stroke() + } + } + for (let j = 0; j < texts.length; j++) { + let item = texts[j] + if (item.text == '\n') { + x = _x + y += lineSpacing * fontSize + lastWord = null + continue + } + if (item.word && lastWord != null && !lastWord) { + let textWidth = ctx.measureText(item.text).width + if (x + textWidth > endX + fontSize / 4) { + drawLine(x - _x) + x = _x + y += lineSpacing * fontSize + } + } + for (let s = 0; s < item.text.length; s++) { + let text = item.text[s] + let textWidth = ctx.measureText(text).width + if (x + textWidth > endX + fontSize / 4 && !isSymbol(text)) { + drawLine(x - _x) + x = _x + y += lineSpacing * fontSize + } + let ty = y + if (verticalAlignment == 'MIDDLE') { + ctx.textBaseline = 'middle' + ty = ty + (lineSpacing * fontSize) / 2 + } else if (verticalAlignment == 'BOTTOM') { + ctx.textBaseline = 'bottom' + ty = ty + (lineSpacing * fontSize) + } else { + ctx.textBaseline = 'top' + } + drawString(text, x, ty) + x += textWidth + } + lastWord = item.word + } + if (i == p.children.length - 1) { + drawLine(x - _x) + } + } else { + // 横版-不自动换行 + let lines = r.text.split('\n') + for (let s = 0; s < lines.length; s++) { + if (s != 0) { + x = _x + y += lineSpacing * fontSize + } + let ty = y + if (verticalAlignment == 'MIDDLE') { + ctx.textBaseline = 'middle' + ty = ty + (lineSpacing * fontSize) / 2 + } else if (verticalAlignment == 'BOTTOM') { + ctx.textBaseline = 'bottom' + ty = ty + (lineSpacing * fontSize) + } else { + ctx.textBaseline = 'top' + } + drawString(lines[s], x, ty) + let textWidth = ctx.measureText(lines[s]).width + if (property.underlined) { + let lineX = x + let lineY = y + if (verticalAlignment == 'MIDDLE') { + lineY = lineY + fontSize / 2 + 1 + } else if (verticalAlignment == 'BOTTOM') { + lineY = lineY + 1 + } else { + lineY = lineY + fontSize + 1 + } + ctx.lineWidth = 1 + ctx.strokeStyle = fillStyle + ctx.beginPath() + ctx.moveTo(lineX, lineY) + ctx.lineTo(lineX + textWidth, lineY) + ctx.closePath() + ctx.stroke() + } + x += textWidth + } + } + } + return (y - _y) + (underlined && !isVertical ? 1 : 0) + lineSpacing * maxFontSize + } - async function drawImage(obj) { - let property = obj.extInfo.property - ctx.save() - shapeHandle(property) - if (property.fillStyle && property.fillStyle.texture) { - property.fillStyle.texture.imageData = property.image - // 图片自带拉伸 - property.fillStyle.texture.stretch = property.fillStyle.texture.stretch || [0, 0, 0, 0] - } else { - property.fillStyle = { 'type': 'texture', texture: { 'imageData': property.image, insets: property.clipping, stretch: [0, 0, 0, 0] } } - } - if (!property.geometry) { - property.geometry = { name: 'rect' } - } - await drawGeometry(property) - if (templateHandle) { - await templateHandle('image', obj, ctx) - } - ctx.restore() - } + async function drawImage(obj) { + let property = obj.extInfo.property + ctx.save() + shapeHandle(property) + if (property.fillStyle && property.fillStyle.texture) { + property.fillStyle.texture.imageData = property.image + // 图片自带拉伸 + property.fillStyle.texture.stretch = property.fillStyle.texture.stretch || [0, 0, 0, 0] + } else { + property.fillStyle = { 'type': 'texture', texture: { 'imageData': property.image, insets: property.clipping, stretch: [0, 0, 0, 0] } } + } + if (!property.geometry) { + property.geometry = { name: 'rect' } + } + await drawGeometry(property) + if (templateHandle) { + await templateHandle('image', obj, ctx) + } + ctx.restore() + } - async function drawTableColumn(property) { - let anchor = property.anchor - let x = anchor[0] - 1 - let endX = anchor[0] + anchor[2] + 1 - let y = anchor[1] - 1 - let endY = anchor[1] + anchor[3] + 1 - let borders = property.borders // top/left/bottom/right - ctx.beginPath() - ctx.moveTo(x, y) - let top = borders[0] - ctx.strokeStyle = toColor({ color: top.color }, 'white') - ctx.lineWidth = top.lineWidth - ctx.lineTo(endX, y) - let right = borders[3] - ctx.strokeStyle = toColor({ color: right.color }, 'white') - ctx.lineWidth = right.lineWidth - ctx.lineTo(endX, endY) - let bottom = borders[2] - ctx.strokeStyle = toColor({ color: bottom.color }, 'white') - ctx.lineWidth = bottom.lineWidth - ctx.lineTo(x, endY) - let left = borders[1] - ctx.strokeStyle = toColor({ color: left.color }, 'white') - ctx.lineWidth = left.lineWidth - ctx.lineTo(x, anchor[1]) - ctx.closePath() - ctx.fillStyle = await toPaint(property.fillStyle, property.anchor) - ctx.fill() - ctx.stroke() - } + async function drawTableColumn(property) { + let anchor = property.anchor + let x = anchor[0] - 1 + let endX = anchor[0] + anchor[2] + 1 + let y = anchor[1] - 1 + let endY = anchor[1] + anchor[3] + 1 + let borders = property.borders // top/left/bottom/right + ctx.beginPath() + ctx.moveTo(x, y) + let top = borders[0] + ctx.strokeStyle = toColor({ color: top.color }, 'white') + ctx.lineWidth = top.lineWidth + ctx.lineTo(endX, y) + let right = borders[3] + ctx.strokeStyle = toColor({ color: right.color }, 'white') + ctx.lineWidth = right.lineWidth + ctx.lineTo(endX, endY) + let bottom = borders[2] + ctx.strokeStyle = toColor({ color: bottom.color }, 'white') + ctx.lineWidth = bottom.lineWidth + ctx.lineTo(x, endY) + let left = borders[1] + ctx.strokeStyle = toColor({ color: left.color }, 'white') + ctx.lineWidth = left.lineWidth + ctx.lineTo(x, anchor[1]) + ctx.closePath() + ctx.fillStyle = await toPaint(property.fillStyle, property.anchor) + ctx.fill() + ctx.stroke() + } - async function drawDiagram(obj) { - let property = obj.extInfo.property - ctx.save() - ctx.translate(property.anchor[0], property.anchor[1]) - if (templateHandle) { - await templateHandle('diagram', obj, ctx) - } - for (let i = 0; i < obj.children.length; i++) { - await drawElement(obj.children[i]) - } - ctx.translate(-property.anchor[0], -property.anchor[1]) - ctx.restore() - } + async function drawDiagram(obj) { + let property = obj.extInfo.property + ctx.save() + ctx.translate(property.anchor[0], property.anchor[1]) + if (templateHandle) { + await templateHandle('diagram', obj, ctx) + } + for (let i = 0; i < obj.children.length; i++) { + await drawElement(obj.children[i]) + } + ctx.translate(-property.anchor[0], -property.anchor[1]) + ctx.restore() + } - async function drawContainer(obj) { - let property = obj.extInfo.property - if (property.realType == 'Group') { - ctx.save() - let _groupFlipX = ctx.groupFlipX - let _groupFlipY = ctx.groupFlipY - let _groupRotation = ctx.groupRotation - if (templateHandle) { - await templateHandle('container', obj, ctx) - } - shapeHandle(property) - let parentGroupFillStyle = ctx.groupFillStyle - let groupFillStyle = property.groupFillStyle - if (groupFillStyle) { - groupFillStyle = JSON.parse(JSON.stringify(groupFillStyle)) - groupFillStyle.groupAnchor = property.anchor - if (parentGroupFillStyle) { - groupFillStyle.parentGroupFillStyle = parentGroupFillStyle - } - } - ctx.groupFillStyle = groupFillStyle - let copyChildren = JSON.parse(JSON.stringify(obj.children)) - recursionGroupChildren(copyChildren, c => { - if (c.extInfo && c.extInfo.property && c.extInfo.property.anchor) { - let anchor = c.extInfo.property.anchor - anchor[0] *= ctx.interior.scaleX - anchor[1] *= ctx.interior.scaleY - anchor[2] *= ctx.interior.scaleX - anchor[3] *= ctx.interior.scaleY - } - }) - for (let i = 0; i < copyChildren.length; i++) { - await drawElement(copyChildren[i]) - } - ctx.interior = ctx._interior - ctx.groupFlipX = _groupFlipX - ctx.groupFlipY = _groupFlipY - ctx.groupRotation = _groupRotation - ctx.restore() - } else { - for (let i = 0; i < obj.children.length; i++) { - await drawElement(obj.children[i]) - } - } - } + async function drawContainer(obj) { + let property = obj.extInfo.property + if (property.realType == 'Group') { + ctx.save() + let _groupFlipX = ctx.groupFlipX + let _groupFlipY = ctx.groupFlipY + let _groupRotation = ctx.groupRotation + if (templateHandle) { + await templateHandle('container', obj, ctx) + } + shapeHandle(property) + let parentGroupFillStyle = ctx.groupFillStyle + let groupFillStyle = property.groupFillStyle + if (groupFillStyle) { + groupFillStyle = JSON.parse(JSON.stringify(groupFillStyle)) + groupFillStyle.groupAnchor = property.anchor + if (parentGroupFillStyle) { + groupFillStyle.parentGroupFillStyle = parentGroupFillStyle + } + } + ctx.groupFillStyle = groupFillStyle + let copyChildren = JSON.parse(JSON.stringify(obj.children)) + recursionGroupChildren(copyChildren, c => { + if (c.extInfo && c.extInfo.property && c.extInfo.property.anchor) { + let anchor = c.extInfo.property.anchor + anchor[0] *= ctx.interior.scaleX + anchor[1] *= ctx.interior.scaleY + anchor[2] *= ctx.interior.scaleX + anchor[3] *= ctx.interior.scaleY + } + }) + for (let i = 0; i < copyChildren.length; i++) { + await drawElement(copyChildren[i]) + } + ctx.interior = ctx._interior + ctx.groupFlipX = _groupFlipX + ctx.groupFlipY = _groupFlipY + ctx.groupRotation = _groupRotation + ctx.restore() + } else { + for (let i = 0; i < obj.children.length; i++) { + await drawElement(obj.children[i]) + } + } + } - function recursionGroupChildren(children, fn) { - if (!children) { - return - } - for (let i = 0; i < children.length; i++) { - let c = children[i] - fn(c) - if (c.extInfo && c.extInfo.property.realType == 'Group') { - continue - } - if (c.children && c.children.length > 0) { - recursionGroupChildren(c.children, fn) - } - } - } + function recursionGroupChildren(children, fn) { + if (!children) { + return + } + for (let i = 0; i < children.length; i++) { + let c = children[i] + fn(c) + if (c.extInfo && c.extInfo.property.realType == 'Group') { + continue + } + if (c.children && c.children.length > 0) { + recursionGroupChildren(c.children, fn) + } + } + } - async function drawConnector(obj) { - let property = obj.extInfo.property - ctx.save() - shapeHandle(property) - await drawGeometry(property) - if (templateHandle) { - await templateHandle('connector', obj, ctx) - } - ctx.restore() - } + async function drawConnector(obj) { + let property = obj.extInfo.property + ctx.save() + shapeHandle(property) + await drawGeometry(property) + if (templateHandle) { + await templateHandle('connector', obj, ctx) + } + ctx.restore() + } - async function drawGraphicFrame(obj) { - let property = obj.extInfo.property - ctx.save() - shapeHandle(property) - if (templateHandle) { - await templateHandle('graphicFrame', obj, ctx) - } - if (property.chart && property.chart.chartData && property.chart.chartData.length > 0) { - await drawChart(property.chart, property.anchor, canvas, ctx) - } - ctx.restore() - } + async function drawGraphicFrame(obj) { + let property = obj.extInfo.property + ctx.save() + shapeHandle(property) + if (templateHandle) { + await templateHandle('graphicFrame', obj, ctx) + } + if (property.chart && property.chart.chartData && property.chart.chartData.length > 0) { + await drawChart(property.chart, property.anchor, canvas, ctx) + } + ctx.restore() + } - async function drawTable(obj) { - let property = obj.extInfo.property - for (let i = 0; i < obj.children.length; i++) { - let row = obj.children[i] - await drawTableRow(obj, row) - } - } + async function drawTable(obj) { + let property = obj.extInfo.property + for (let i = 0; i < obj.children.length; i++) { + let row = obj.children[i] + await drawTableRow(obj, row) + } + } - async function drawTableRow(table, row) { - let property = row.extInfo.property - for (let i = 0; i < row.children.length; i++) { - let column = row.children[i] - await drawText(column) - } - } + async function drawTableRow(table, row) { + let property = row.extInfo.property + for (let i = 0; i < row.children.length; i++) { + let column = row.children[i] + await drawText(column) + } + } - async function drawGeometry(property) { - let geometry = property.geometry - let anchor = property.anchor - if (!geometry || !anchor || (anchor[2] == 0 && anchor[3] == 0)) { - return - } - ctx.save() - ctx.translate(anchor[0], anchor[1]) - let paths = geometryPaths(property) - let _anchor = [0, 0, anchor[2], anchor[3]] - if (geometry.name == 'custom') { - await drawPaths(paths, property, _anchor, anchor) - } else if (geometry.name == 'line' || geometry.name == 'straightConnector1') { - await drawPaths(paths, property, _anchor, anchor) - } else { - await drawPaths(paths, property, _anchor, anchor) - } - ctx.translate(-anchor[0], -anchor[1]) - ctx.restore() - } + async function drawGeometry(property) { + let geometry = property.geometry + let anchor = property.anchor + if (!geometry || !anchor || (anchor[2] == 0 && anchor[3] == 0)) { + return + } + ctx.save() + ctx.translate(anchor[0], anchor[1]) + let paths = geometryPaths(property) + let _anchor = [0, 0, anchor[2], anchor[3]] + if (geometry.name == 'custom') { + await drawPaths(paths, property, _anchor, anchor) + } else if (geometry.name == 'line' || geometry.name == 'straightConnector1') { + await drawPaths(paths, property, _anchor, anchor) + } else { + await drawPaths(paths, property, _anchor, anchor) + } + ctx.translate(-anchor[0], -anchor[1]) + ctx.restore() + } - async function drawPaths(paths, property, anchor, real_anchor) { - for (let i = 0; i < paths.length; i++) { - let path = paths[i] - // console.log('path: ', path) - ctx.save() - let scaleX = path.scaleX - let scaleY = path.scaleY - ctx.scale(scaleX, scaleY) - let _anchor = [anchor[0], anchor[1], anchor[2], anchor[3]] - if (scaleX != 1 || scaleY != 1) { - _anchor[0] = _anchor[0] / scaleX - _anchor[1] = _anchor[1] / scaleY - _anchor[2] = _anchor[2] / scaleX - _anchor[3] = _anchor[3] / scaleY - } - ctx.beginPath() - let split = path.path.replace(/\s+/g, ' ').trim().split(' ') - for (let j = 0; j < split.length; j++) { - switch (split[j]) { - case 'M': - ctx.moveTo(split[++j], split[++j]) - break - case 'L': - ctx.lineTo(split[++j], split[++j]) - break - case 'Q': - ctx.quadraticCurveTo(split[++j], split[++j], split[++j], split[++j]) - break - case 'C': - ctx.bezierCurveTo(split[++j], split[++j], split[++j], split[++j], split[++j], split[++j]) - break - case 'Z': - ctx.closePath() - break - } - } - let strokeStyle = null - if (property.strokeStyle) { - ctx.lineWidth = (property.strokeStyle.lineWidth || 1) / scaleY - let lineCap = property.strokeStyle.lineCap - if (!lineCap || lineCap == 'FLAT') { - lineCap = 'butt' - } - ctx.lineCap = lineCap.toLowerCase() - strokeStyle = await toPaint(property.strokeStyle.paint, _anchor) - } - doShadow(ctx, property.shadow) - if (path.stroked && strokeStyle) { - ctx.strokeStyle = strokeStyle - } else { - ctx.strokeStyle = 'transparent' - } - ctx.stroke() - ctx.scale(1 / scaleX, 1 / scaleY) - let fillStyle = await toPaint(property.fillStyle, anchor) - if (path.filled) { - ctx.fillStyle = fillStyle - } else { - ctx.fillStyle = 'transparent' - } - if (property.fillStyle && property.fillStyle.type == 'bgFill') { - let rotation = (property.rotation || 0) + (ctx.groupRotation || 0) - if (rotation) { - ctx.translate(real_anchor[2] / 2, real_anchor[3] / 2) - ctx.rotate(-rotation * Math.PI / 180) - ctx.translate(-real_anchor[2] / 2, -real_anchor[3] / 2) - } - let tx = 0, ty = 0 - if (ctx.interior) { - tx = -ctx.interior.tx - real_anchor[0] - ty = -ctx.interior.ty - real_anchor[1] - } else { - tx = -real_anchor[0] - ty = -real_anchor[1] - } - ctx.translate(tx, ty) - ctx.fill() - ctx.translate(-tx, -ty) - } else { - ctx.fill() - } - ctx.restore() - } - } + async function drawPaths(paths, property, anchor, real_anchor) { + for (let i = 0; i < paths.length; i++) { + let path = paths[i] + // console.log('path: ', path) + ctx.save() + let scaleX = path.scaleX + let scaleY = path.scaleY + ctx.scale(scaleX, scaleY) + let _anchor = [anchor[0], anchor[1], anchor[2], anchor[3]] + if (scaleX != 1 || scaleY != 1) { + _anchor[0] = _anchor[0] / scaleX + _anchor[1] = _anchor[1] / scaleY + _anchor[2] = _anchor[2] / scaleX + _anchor[3] = _anchor[3] / scaleY + } + ctx.beginPath() + let split = path.path.replace(/\s+/g, ' ').trim().split(' ') + for (let j = 0; j < split.length; j++) { + switch (split[j]) { + case 'M': + ctx.moveTo(split[++j], split[++j]) + break + case 'L': + ctx.lineTo(split[++j], split[++j]) + break + case 'Q': + ctx.quadraticCurveTo(split[++j], split[++j], split[++j], split[++j]) + break + case 'C': + ctx.bezierCurveTo(split[++j], split[++j], split[++j], split[++j], split[++j], split[++j]) + break + case 'Z': + ctx.closePath() + break + } + } + let strokeStyle = null + if (property.strokeStyle) { + ctx.lineWidth = (property.strokeStyle.lineWidth || 1) / scaleY + let lineCap = property.strokeStyle.lineCap + if (!lineCap || lineCap == 'FLAT') { + lineCap = 'butt' + } + ctx.lineCap = lineCap.toLowerCase() + strokeStyle = await toPaint(property.strokeStyle.paint, _anchor) + } + doShadow(ctx, property.shadow) + if (path.stroked && strokeStyle) { + ctx.strokeStyle = strokeStyle + } else { + ctx.strokeStyle = 'transparent' + } + ctx.stroke() + ctx.scale(1 / scaleX, 1 / scaleY) + let fillStyle = await toPaint(property.fillStyle, anchor) + if (path.filled) { + ctx.fillStyle = fillStyle + } else { + ctx.fillStyle = 'transparent' + } + if (property.fillStyle && property.fillStyle.type == 'bgFill') { + let rotation = (property.rotation || 0) + (ctx.groupRotation || 0) + if (rotation) { + ctx.translate(real_anchor[2] / 2, real_anchor[3] / 2) + ctx.rotate(-rotation * Math.PI / 180) + ctx.translate(-real_anchor[2] / 2, -real_anchor[3] / 2) + } + let tx = 0, ty = 0 + if (ctx.interior) { + tx = -ctx.interior.tx - real_anchor[0] + ty = -ctx.interior.ty - real_anchor[1] + } else { + tx = -real_anchor[0] + ty = -real_anchor[1] + } + ctx.translate(tx, ty) + ctx.fill() + ctx.translate(-tx, -ty) + } else { + ctx.fill() + } + ctx.restore() + } + } - function shapeHandle(property) { - let anchor = property.anchor - if (!anchor) { - return - } - let cx = anchor[0] + anchor[2] / 2 - let cy = anchor[1] + anchor[3] / 2 - if (property.rotation) { - // 旋转 - ctx.translate(cx, cy) - ctx.rotate(property.rotation * Math.PI / 180) - ctx.translate(-cx, -cy) - if (property.realType == 'Group') { - ctx.groupRotation = (ctx.groupRotation || 0) + property.rotation - } - } - if (property.flipVertical) { - ctx.translate(cx, cy) - ctx.scale(1, -1) - ctx.translate(-cx, -cy) - if (property.realType == 'Group') { - ctx.groupFlipY = -(ctx.groupFlipY || 1) - } - } - if (property.flipHorizontal) { - ctx.translate(cx, cy) - ctx.scale(-1, 1) - ctx.translate(-cx, -cy) - if (property.realType == 'Group') { - ctx.groupFlipX = -(ctx.groupFlipX || 1) - } - } - // 嵌套容器 Group - let interior = property.interiorAnchor - if (interior && interior.length > 0) { - /* - // 缩放 - let scaleX = interior[2] == 0 || anchor[2] == interior[2] ? 1 : anchor[2] / interior[2] - let scaleY = interior[3] == 0 || anchor[3] == interior[3] ? 1 : anchor[3] / interior[3] - ctx.scale(scaleX, scaleY) - ctx.translate(anchor[0] / scaleX - interior[0], anchor[1] / scaleY - interior[1]) - */ - let scaleX = interior[2] == 0 || anchor[2] == interior[2] ? 1 : anchor[2] / interior[2] - let scaleY = interior[3] == 0 || anchor[3] == interior[3] ? 1 : anchor[3] / interior[3] - let tx = anchor[0] - interior[0] * scaleX - let ty = anchor[1] - interior[1] * scaleY - ctx.translate(tx, ty) - ctx._interior = ctx.interior - ctx.interior = { scaleX, scaleY, tx, ty } - } else if (property.realType == 'Group') { - ctx._interior = ctx.interior - ctx.interior = { scaleX: 1, scaleY: 1, tx: 0, ty: 0 } - } - } + function shapeHandle(property) { + let anchor = property.anchor + if (!anchor) { + return + } + let cx = anchor[0] + anchor[2] / 2 + let cy = anchor[1] + anchor[3] / 2 + if (property.rotation) { + // 旋转 + ctx.translate(cx, cy) + ctx.rotate(property.rotation * Math.PI / 180) + ctx.translate(-cx, -cy) + if (property.realType == 'Group') { + ctx.groupRotation = (ctx.groupRotation || 0) + property.rotation + } + } + if (property.flipVertical) { + ctx.translate(cx, cy) + ctx.scale(1, -1) + ctx.translate(-cx, -cy) + if (property.realType == 'Group') { + ctx.groupFlipY = -(ctx.groupFlipY || 1) + } + } + if (property.flipHorizontal) { + ctx.translate(cx, cy) + ctx.scale(-1, 1) + ctx.translate(-cx, -cy) + if (property.realType == 'Group') { + ctx.groupFlipX = -(ctx.groupFlipX || 1) + } + } + // 嵌套容器 Group + let interior = property.interiorAnchor + if (interior && interior.length > 0) { + /* + // 缩放 + let scaleX = interior[2] == 0 || anchor[2] == interior[2] ? 1 : anchor[2] / interior[2] + let scaleY = interior[3] == 0 || anchor[3] == interior[3] ? 1 : anchor[3] / interior[3] + ctx.scale(scaleX, scaleY) + ctx.translate(anchor[0] / scaleX - interior[0], anchor[1] / scaleY - interior[1]) + */ + let scaleX = interior[2] == 0 || anchor[2] == interior[2] ? 1 : anchor[2] / interior[2] + let scaleY = interior[3] == 0 || anchor[3] == interior[3] ? 1 : anchor[3] / interior[3] + let tx = anchor[0] - interior[0] * scaleX + let ty = anchor[1] - interior[1] * scaleY + ctx.translate(tx, ty) + ctx._interior = ctx.interior + ctx.interior = { scaleX, scaleY, tx, ty } + } else if (property.realType == 'Group') { + ctx._interior = ctx.interior + ctx.interior = { scaleX: 1, scaleY: 1, tx: 0, ty: 0 } + } + } - async function drawBackground(background) { - if (!background) { - ctx.bgFillStyle = null - return - } - ctx.fillStyle = await toPaint(background.fillStyle, background.anchor, true) - ctx.fillRect(background.anchor[0], background.anchor[1], background.anchor[2], background.anchor[3]) - ctx.bgFillStyle = ctx.fillStyle - } + async function drawBackground(background) { + if (!background) { + ctx.bgFillStyle = null + return + } + ctx.fillStyle = await toPaint(background.fillStyle, background.anchor, true) + ctx.fillRect(background.anchor[0], background.anchor[1], background.anchor[2], background.anchor[3]) + ctx.bgFillStyle = ctx.fillStyle + } - async function drawSlideMaster(slideMaster, slideLayout, placeholder) { - recursion(slideMaster.children, obj => { - if (obj.extInfo.property && obj.extInfo.property.placeholder) { - obj.noDraw = true - placeholder[obj.extInfo.property.placeholder.type] = obj.extInfo.property - } - }) - if (slideLayout && slideLayout.noMaster) { - return - } - for (let i = 0; slideMaster.children && i < slideMaster.children.length; i++) { - await drawElement(slideMaster.children[i]) - } - } + async function drawSlideMaster(slideMaster, slideLayout, placeholder) { + recursion(slideMaster.children, obj => { + if (obj.extInfo.property && obj.extInfo.property.placeholder) { + obj.noDraw = true + placeholder[obj.extInfo.property.placeholder.type] = obj.extInfo.property + } + }) + if (slideLayout && slideLayout.noMaster) { + return + } + for (let i = 0; slideMaster.children && i < slideMaster.children.length; i++) { + await drawElement(slideMaster.children[i]) + } + } - async function drawSlideLayout(slideLayout, placeholder) { - recursion(slideLayout.children, obj => { - if (obj.extInfo.property && obj.extInfo.property.placeholder) { - obj.noDraw = true - placeholder[obj.extInfo.property.placeholder.type] = obj.extInfo.property - } - }) - for (let i = 0; slideLayout.children && i < slideLayout.children.length; i++) { - await drawElement(slideLayout.children[i]) - } - } + async function drawSlideLayout(slideLayout, placeholder) { + recursion(slideLayout.children, obj => { + if (obj.extInfo.property && obj.extInfo.property.placeholder) { + obj.noDraw = true + placeholder[obj.extInfo.property.placeholder.type] = obj.extInfo.property + } + }) + for (let i = 0; slideLayout.children && i < slideLayout.children.length; i++) { + await drawElement(slideLayout.children[i]) + } + } - function recursion(children, fn) { - if (!children) { - return - } - for (let i = 0; i < children.length; i++) { - let c = children[i] - fn(c) - if (c.children && c.children.length > 0) { - recursion(c.children, fn) - } - } - } + function recursion(children, fn) { + if (!children) { + return + } + for (let i = 0; i < children.length; i++) { + let c = children[i] + fn(c) + if (c.children && c.children.length > 0) { + recursion(c.children, fn) + } + } + } - function doShadow(ctx, shadow) { - if (!shadow) { - return - } - ctx.shadowBlur = shadow.blur || 0 - ctx.shadowColor = toColor(shadow.fillStyle.color) - if (shadow.distance) { - let radians = (shadow.angle || 0) * Math.PI / 180 - let x = 0, y = 0, r = shadow.distance * 2 - ctx.shadowOffsetX = x + r * Math.cos(radians) - ctx.shadowOffsetY = y + r * Math.sin(radians) - } - } + function doShadow(ctx, shadow) { + if (!shadow) { + return + } + ctx.shadowBlur = shadow.blur || 0 + ctx.shadowColor = toColor(shadow.fillStyle.color) + if (shadow.distance) { + let radians = (shadow.angle || 0) * Math.PI / 180 + let x = 0, y = 0, r = shadow.distance * 2 + ctx.shadowOffsetX = x + r * Math.cos(radians) + ctx.shadowOffsetY = y + r * Math.sin(radians) + } + } - function toPaint(paint, anchor, isBackground, defaultColor) { - return new Promise((resolve, reject) => { - if (!paint) { - resolve(defaultColor || 'transparent') - } else if (paint.type == 'noFill') { - // 无填充 - resolve('transparent') - } else if (paint.type == 'color') { - // 颜色 - resolve(toColor(paint.color, defaultColor)) - } else if (paint.type == 'bgFill') { - // 背景填充 - resolve(ctx.bgFillStyle || defaultColor || 'transparent') - } else if (paint.type == 'groupFill') { - // 组合背景 - let groupFillStyle = paint.parentGroupFillStyle || ctx.groupFillStyle - if (groupFillStyle) { - toPaint(groupFillStyle, anchor || groupFillStyle.groupAnchor, false, defaultColor).then(res => { - resolve(res) - }) - } else { - resolve(defaultColor || 'transparent') - } - } else if (paint.type == 'gradient') { - // 渐变 - let gradient = paint.gradient - let x = anchor[0], y = anchor[1], width = anchor[2], height = anchor[3] - let centerX = x + width / 2 - let centerY = y + height / 2 - let gradientObj - // linear,circular,rectangular,shape - if (gradient.gradientType == 'circular') { - // 射线 - let radius = Math.sqrt(width * width + height * height) * (gradient.insets[1] == 0.5 ? 0.5 : 1) - let cx = centerX + width * (gradient.insets[1] - gradient.insets[3]) / 2 - let cy = centerY + height * (gradient.insets[0] - gradient.insets[2]) / 2 - gradientObj = ctx.createRadialGradient(cx, cy, 0, cx, cy, radius) - } else { - // 线性 - let startX = x - let startY = centerY - let endX = x + width - let endY = centerY - if (gradient.angle) { - let radians = gradient.angle * Math.PI / 180 - let midX = (startX + endX) / 2 - let midY = (startY + endY) / 2 - let newStartX = midX + (startX - midX) * Math.cos(radians) - (startY - midY) * Math.sin(radians) - let newStartY = midY + (startX - midX) * Math.sin(radians) + (startY - midY) * Math.cos(radians) - let newEndX = midX + (endX - midX) * Math.cos(radians) - (endY - midY) * Math.sin(radians) - let newEndY = midY + (endX - midX) * Math.sin(radians) + (endY - midY) * Math.cos(radians) - startX = newStartX - startY = newStartY - endX = newEndX - endY = newEndY - } - gradientObj = ctx.createLinearGradient(startX, startY, endX, endY) - } - for (let i = 0; i < gradient.colors.length; i++) { - let color = gradient.colors[i] - gradientObj.addColorStop(gradient.fractions[i], toColor(color)) - } - resolve(gradientObj) - } else if (anchor && anchor[2] == 0 && anchor[3] == 0) { - resolve('transparent') - } else if (paint.type == 'texture') { - // 图片或纹理 - let texture = paint.texture - let anonymous = texture.duoTone && texture.duoTone.length > 0 && texture.duoTonePrst - loadImage(texture.imageData, anonymous).then(img => { - if (img) { - let pat = createTexturePattern(img, texture, anchor, isBackground) - resolve(pat) - } else { - resolve('transparent') - } - }) - } else if (paint.type == 'pattern') { - // 图案 - let pattern = paint.pattern - // let prst = pattern.prst - let fgColor = pattern.fgColor.realColor - let bgColor = pattern.bgColor.realColor - let width = anchor[2], height = anchor[3] - let imgCanvas = document.createElement('canvas') - imgCanvas.width = width - imgCanvas.height = height - let imgCtx = imgCanvas.getContext('2d') - imgCtx.imageSmoothingEnabled = true - imgCtx.imageSmoothingQuality = 'high' - let imgData = imgCtx.createImageData(width, height) - let line = 0 - for (let i = 0; i < imgData.data.length; i += 4) { - if (++line % 16 == 0) { - // 前景 - imgData.data[i + 0] = (fgColor >> 16) & 255 - imgData.data[i + 1] = (fgColor >> 8) & 255 - imgData.data[i + 2] = (fgColor >> 0) & 255 - imgData.data[i + 3] = (fgColor >> 24) & 255 - } else { - // 背景 - imgData.data[i + 0] = (bgColor >> 16) & 255 - imgData.data[i + 1] = (bgColor >> 8) & 255 - imgData.data[i + 2] = (bgColor >> 0) & 255 - imgData.data[i + 3] = (bgColor >> 24) & 255 - } - if (i % 400 == 0) { - line += 2 - } - } - imgCtx.putImageData(imgData, 0, 0) - let imgSrc = imgCanvas.toDataURL() - let image = new Image() - image.src = imgSrc - image.onload = async function() { - resolve(ctx.createPattern(image, 'no-repeat')) - } - } - }) - } + function toPaint(paint, anchor, isBackground, defaultColor) { + return new Promise((resolve, reject) => { + if (!paint) { + resolve(defaultColor || 'transparent') + } else if (paint.type == 'noFill') { + // 无填充 + resolve('transparent') + } else if (paint.type == 'color') { + // 颜色 + resolve(toColor(paint.color, defaultColor)) + } else if (paint.type == 'bgFill') { + // 背景填充 + resolve(ctx.bgFillStyle || defaultColor || 'transparent') + } else if (paint.type == 'groupFill') { + // 组合背景 + let groupFillStyle = paint.parentGroupFillStyle || ctx.groupFillStyle + if (groupFillStyle) { + toPaint(groupFillStyle, anchor || groupFillStyle.groupAnchor, false, defaultColor).then(res => { + resolve(res) + }) + } else { + resolve(defaultColor || 'transparent') + } + } else if (paint.type == 'gradient') { + // 渐变 + let gradient = paint.gradient + let x = anchor[0], y = anchor[1], width = anchor[2], height = anchor[3] + let centerX = x + width / 2 + let centerY = y + height / 2 + let gradientObj + // linear,circular,rectangular,shape + if (gradient.gradientType == 'circular') { + // 射线 + let radius = Math.sqrt(width * width + height * height) * (gradient.insets[1] == 0.5 ? 0.5 : 1) + let cx = centerX + width * (gradient.insets[1] - gradient.insets[3]) / 2 + let cy = centerY + height * (gradient.insets[0] - gradient.insets[2]) / 2 + gradientObj = ctx.createRadialGradient(cx, cy, 0, cx, cy, radius) + } else { + // 线性 + let startX = x + let startY = centerY + let endX = x + width + let endY = centerY + if (gradient.angle) { + let radians = gradient.angle * Math.PI / 180 + let midX = (startX + endX) / 2 + let midY = (startY + endY) / 2 + let newStartX = midX + (startX - midX) * Math.cos(radians) - (startY - midY) * Math.sin(radians) + let newStartY = midY + (startX - midX) * Math.sin(radians) + (startY - midY) * Math.cos(radians) + let newEndX = midX + (endX - midX) * Math.cos(radians) - (endY - midY) * Math.sin(radians) + let newEndY = midY + (endX - midX) * Math.sin(radians) + (endY - midY) * Math.cos(radians) + startX = newStartX + startY = newStartY + endX = newEndX + endY = newEndY + } + gradientObj = ctx.createLinearGradient(startX, startY, endX, endY) + } + for (let i = 0; i < gradient.colors.length; i++) { + let color = gradient.colors[i] + gradientObj.addColorStop(gradient.fractions[i], toColor(color)) + } + resolve(gradientObj) + } else if (anchor && anchor[2] == 0 && anchor[3] == 0) { + resolve('transparent') + } else if (paint.type == 'texture') { + // 图片或纹理 + let texture = paint.texture + let anonymous = texture.duoTone && texture.duoTone.length > 0 && texture.duoTonePrst + loadImage(texture.imageData, anonymous).then(img => { + if (img) { + let pat = createTexturePattern(img, texture, anchor, isBackground) + resolve(pat) + } else { + resolve('transparent') + } + }) + } else if (paint.type == 'pattern') { + // 图案 + let pattern = paint.pattern + // let prst = pattern.prst + let fgColor = pattern.fgColor.realColor + let bgColor = pattern.bgColor.realColor + let width = anchor[2], height = anchor[3] + let imgCanvas = document.createElement('canvas') + imgCanvas.width = width + imgCanvas.height = height + let imgCtx = imgCanvas.getContext('2d') + imgCtx.imageSmoothingEnabled = true + imgCtx.imageSmoothingQuality = 'high' + let imgData = imgCtx.createImageData(width, height) + let line = 0 + for (let i = 0; i < imgData.data.length; i += 4) { + if (++line % 16 == 0) { + // 前景 + imgData.data[i + 0] = (fgColor >> 16) & 255 + imgData.data[i + 1] = (fgColor >> 8) & 255 + imgData.data[i + 2] = (fgColor >> 0) & 255 + imgData.data[i + 3] = (fgColor >> 24) & 255 + } else { + // 背景 + imgData.data[i + 0] = (bgColor >> 16) & 255 + imgData.data[i + 1] = (bgColor >> 8) & 255 + imgData.data[i + 2] = (bgColor >> 0) & 255 + imgData.data[i + 3] = (bgColor >> 24) & 255 + } + if (i % 400 == 0) { + line += 2 + } + } + imgCtx.putImageData(imgData, 0, 0) + let imgSrc = imgCanvas.toDataURL() + let image = new Image() + image.src = imgSrc + image.onload = async function() { + resolve(ctx.createPattern(image, 'no-repeat')) + } + } + }) + } - function createTexturePattern(img, texture, anchor, isBackground) { - let width = anchor[2] - let height = anchor[3] - let mode = texture.alignment || !texture.stretch ? 'repeat' : 'no-repeat' - if (width < 1 && height < 1 || isNaN(width) || isNaN(height)) { - return ctx.createPattern(img, mode) - } - if (texture.alignment || !texture.stretch) { - width = img.width - height = img.height - } - let patternCanvas = document.createElement('canvas') - patternCanvas.width = Math.max(1, width) - patternCanvas.height = Math.max(1, height) - let patternCtx = patternCanvas.getContext('2d') - patternCtx.imageSmoothingEnabled = true - patternCtx.imageSmoothingQuality = 'high' - if (texture.alpha >= 0 && texture.alpha < 100000) { - patternCtx.globalAlpha = texture.alpha / 100000 - } - let imgInsets = null - if (texture.insets) { - let top = texture.insets[0] / 100000 - let left = texture.insets[1] / 100000 - let bottom = texture.insets[2] / 100000 - let right = texture.insets[3] / 100000 - let x = img.width * left - let y = img.height * top - let w = img.width * (1 - left - right) - let h = img.height * (1 - top - bottom) - imgInsets = [x, y, w, h] - } - if (texture.stretch) { - let top = texture.stretch[0] / 100000 - let left = texture.stretch[1] / 100000 - let bottom = texture.stretch[2] / 100000 - let right = texture.stretch[3] / 100000 - let x = width * left - let y = height * top - let w = width * (1 - left - right) - let h = height * (1 - top - bottom) - if (imgInsets) { - patternCtx.drawImage(img, imgInsets[0], imgInsets[1], imgInsets[2], imgInsets[3], x, y, w, h) - } else { - patternCtx.drawImage(img, x, y, w, h) - } - } else if (texture.alignment) { - let x = 0, y = 0 - if (texture.alignment == 'CENTER') { - if (width > anchor[2]) { - x = (width - anchor[2]) / 2 - } - if (height > anchor[3]) { - y = (height - anchor[3]) / 2 - } - } - patternCtx.drawImage(img, x, y, width, height, 0, 0, width, height) - } else { - if (imgInsets) { - patternCtx.drawImage(img, imgInsets[0], imgInsets[1], imgInsets[2], imgInsets[3], 0, 0, width, height) - } else { - patternCtx.drawImage(img, 0, 0, width, height) - } - } - if (texture.duoTone && texture.duoTone.length > 0 && texture.duoTonePrst) { - try { - // 重新着色 - let color = texture.duoTone[0].realColor - let r = (color >> 16) & 255 - let g = (color >> 8) & 255 - let b = (color >> 0) & 255 - let imageData = patternCtx.getImageData(0, 0, patternCanvas.width, patternCanvas.height) - let data = imageData.data - for(var i = 0; i < data.length; i += 4) { - let gray = (data[i] * 0.3 + data[i + 1] * 0.59 + data[i + 2] * 0.11) / 255 - // black / white - let prst = texture.duoTonePrst == 'white' ? 255 : 0 - data[i] = gray * r + (1 - gray) * prst - data[i + 1] = gray * g + (1 - gray) * prst - data[i + 2] = gray * b + (1 - gray) * prst - } - patternCtx.putImageData(imageData, 0, 0) - } catch(e) { /* empty */ } - } - return ctx.createPattern(patternCanvas, mode) - } + function createTexturePattern(img, texture, anchor, isBackground) { + let width = anchor[2] + let height = anchor[3] + let mode = texture.alignment || !texture.stretch ? 'repeat' : 'no-repeat' + if (width < 1 && height < 1 || isNaN(width) || isNaN(height)) { + return ctx.createPattern(img, mode) + } + if (texture.alignment || !texture.stretch) { + width = img.width + height = img.height + } + let patternCanvas = document.createElement('canvas') + patternCanvas.width = Math.max(1, width) + patternCanvas.height = Math.max(1, height) + let patternCtx = patternCanvas.getContext('2d') + patternCtx.imageSmoothingEnabled = true + patternCtx.imageSmoothingQuality = 'high' + if (texture.alpha >= 0 && texture.alpha < 100000) { + patternCtx.globalAlpha = texture.alpha / 100000 + } + let imgInsets = null + if (texture.insets) { + let top = texture.insets[0] / 100000 + let left = texture.insets[1] / 100000 + let bottom = texture.insets[2] / 100000 + let right = texture.insets[3] / 100000 + let x = img.width * left + let y = img.height * top + let w = img.width * (1 - left - right) + let h = img.height * (1 - top - bottom) + imgInsets = [x, y, w, h] + } + if (texture.stretch) { + let top = texture.stretch[0] / 100000 + let left = texture.stretch[1] / 100000 + let bottom = texture.stretch[2] / 100000 + let right = texture.stretch[3] / 100000 + let x = width * left + let y = height * top + let w = width * (1 - left - right) + let h = height * (1 - top - bottom) + if (imgInsets) { + patternCtx.drawImage(img, imgInsets[0], imgInsets[1], imgInsets[2], imgInsets[3], x, y, w, h) + } else { + patternCtx.drawImage(img, x, y, w, h) + } + } else if (texture.alignment) { + let x = 0, y = 0 + if (texture.alignment == 'CENTER') { + if (width > anchor[2]) { + x = (width - anchor[2]) / 2 + } + if (height > anchor[3]) { + y = (height - anchor[3]) / 2 + } + } + patternCtx.drawImage(img, x, y, width, height, 0, 0, width, height) + } else { + if (imgInsets) { + patternCtx.drawImage(img, imgInsets[0], imgInsets[1], imgInsets[2], imgInsets[3], 0, 0, width, height) + } else { + patternCtx.drawImage(img, 0, 0, width, height) + } + } + if (texture.duoTone && texture.duoTone.length > 0 && texture.duoTonePrst) { + try { + // 重新着色 + let color = texture.duoTone[0].realColor + let r = (color >> 16) & 255 + let g = (color >> 8) & 255 + let b = (color >> 0) & 255 + let imageData = patternCtx.getImageData(0, 0, patternCanvas.width, patternCanvas.height) + let data = imageData.data + for(var i = 0; i < data.length; i += 4) { + let gray = (data[i] * 0.3 + data[i + 1] * 0.59 + data[i + 2] * 0.11) / 255 + // black / white + let prst = texture.duoTonePrst == 'white' ? 255 : 0 + data[i] = gray * r + (1 - gray) * prst + data[i + 1] = gray * g + (1 - gray) * prst + data[i + 2] = gray * b + (1 - gray) * prst + } + patternCtx.putImageData(imageData, 0, 0) + } catch(e) { /* empty */ } + } + return ctx.createPattern(patternCanvas, mode) + } - function toColor(colorObj, defaultColor) { - if (colorObj == null || (colorObj.color == null && colorObj.realColor == null)) { - return defaultColor || 'transparent' - } - let color = colorObj.realColor != null ? colorObj.realColor : colorObj.color - let r = (color >> 16) & 255 - let g = (color >> 8) & 255 - let b = (color >> 0) & 255 - let a = ((color >> 24) & 255) / 255 - if (colorObj.realColor == null) { - if (colorObj.alpha != null && colorObj.alpha != -1) { - if (colorObj.alpha > 1000) { - a = colorObj.alpha / 100000 - } else { - a = (colorObj.alpha > 0 && colorObj.alpha < 1) ? colorObj.alpha : colorObj.alpha / 255 - } - a = Math.min(1, Math.max(0, a)) - } - if (colorObj.lumMod && colorObj.lumMod > 0) { - let value = colorObj.lumMod / 100000 - r = r * value - g = g * value - b = b * value - } - if (colorObj.lumOff && colorObj.lumOff > 0) { - let value = colorObj.lumOff / 100000 - r += 255 * value - g += 255 * value - b += 255 * value - } - } - return `rgba(${r}, ${g}, ${b}, ${a})` - } + function toColor(colorObj, defaultColor) { + if (colorObj == null || (colorObj.color == null && colorObj.realColor == null)) { + return defaultColor || 'transparent' + } + let color = colorObj.realColor != null ? colorObj.realColor : colorObj.color + let r = (color >> 16) & 255 + let g = (color >> 8) & 255 + let b = (color >> 0) & 255 + let a = ((color >> 24) & 255) / 255 + if (colorObj.realColor == null) { + if (colorObj.alpha != null && colorObj.alpha != -1) { + if (colorObj.alpha > 1000) { + a = colorObj.alpha / 100000 + } else { + a = (colorObj.alpha > 0 && colorObj.alpha < 1) ? colorObj.alpha : colorObj.alpha / 255 + } + a = Math.min(1, Math.max(0, a)) + } + if (colorObj.lumMod && colorObj.lumMod > 0) { + let value = colorObj.lumMod / 100000 + r = r * value + g = g * value + b = b * value + } + if (colorObj.lumOff && colorObj.lumOff > 0) { + let value = colorObj.lumOff / 100000 + r += 255 * value + g += 255 * value + b += 255 * value + } + } + return `rgba(${r}, ${g}, ${b}, ${a})` + } - function toColorValue(r, g, b, a) { - a = (a == null ? 255 : a) - return (a & 255) << 24 | (r & 255) << 16 | (g & 255) << 8 | (b & 255) << 0 - } + function toColorValue(r, g, b, a) { + a = (a == null ? 255 : a) + return (a & 255) << 24 | (r & 255) << 16 | (g & 255) << 8 | (b & 255) << 0 + } - function loadImage(src, anonymous) { - return new Promise(resolve => { - if (!src) { - resolve() - return - } - let cacheKey - if (src.length < 15) { - cacheKey = src - } else { - cacheKey = src.length + '_' + src.substring(src.length - 15) - } - let img = imageCache[cacheKey] - if (img == null) { - img = new Image() - if (imageCrossOrigin || anonymous) { - let eqOrigin = src.startsWith('data:') || src.startsWith(document.location.origin) || (src.startsWith('//') && (document.location.protocol + src).startsWith(document.location.origin)) - if (!eqOrigin) { - // anonymous / use-credentials - img.crossOrigin = imageCrossOrigin || 'anonymous' - } - } - img.src = src - img.onload = function() { - imageCache[cacheKey] = img - resolve(img) - } - img.onerror = function (e) { - resolve() - console.log('图片加载失败: ', src, e) - } - } else { - resolve(img) - } - }) - } + function loadImage(src, anonymous) { + return new Promise(resolve => { + if (!src) { + resolve() + return + } + let cacheKey + if (src.length < 15) { + cacheKey = src + } else { + cacheKey = src.length + '_' + src.substring(src.length - 15) + } + let img = imageCache[cacheKey] + if (img == null) { + img = new Image() + if (imageCrossOrigin || anonymous) { + let eqOrigin = src.startsWith('data:') || src.startsWith(document.location.origin) || (src.startsWith('//') && (document.location.protocol + src).startsWith(document.location.origin)) + if (!eqOrigin) { + // anonymous / use-credentials + img.crossOrigin = imageCrossOrigin || 'anonymous' + } + } + img.src = src + img.onload = function() { + imageCache[cacheKey] = img + resolve(img) + } + img.onerror = function (e) { + resolve() + console.log('图片加载失败: ', src, e) + } + } else { + resolve(img) + } + }) + } - function value2px(v, isEmu) { - if (isEmu) { - return +v / 12700 - } else { - return +v - } - } + function value2px(v, isEmu) { + if (isEmu) { + return +v / 12700 + } else { + return +v + } + } - function value2emu(v) { - return +v * 12700 - } + function value2emu(v) { + return +v * 12700 + } - function getTfx(x, div) { - if (div) { - return x / (ctx.getTransform().a / ctx.scaleX) - } else { - return x * (ctx.getTransform().a / ctx.scaleX) - } - } + function getTfx(x, div) { + if (div) { + return x / (ctx.getTransform().a / ctx.scaleX) + } else { + return x * (ctx.getTransform().a / ctx.scaleX) + } + } - function getTfy(y, div) { - if (div) { - return y / (ctx.getTransform().d / ctx.scaleY) - } else { - return y * (ctx.getTransform().d / ctx.scaleY) - } - } + function getTfy(y, div) { + if (div) { + return y / (ctx.getTransform().d / ctx.scaleY) + } else { + return y * (ctx.getTransform().d / ctx.scaleY) + } + } - function splitWords(str) { - if (!str) { - return [] - } - let pattern = /^[0-9a-zA-Z]+$/ - let array = [] - let item = '' - let math = null - for (let i = 0; i < str.length; i++) { - if (str[i] == '\n') { - if (item) { - array.push({ text: item, word: math }) - } - array.push({ text: '\n', word: false }) - item = '' - math = null - } else { - let _math = pattern.test(str[i]) - if (math == null) { - math = _math - item += str[i] - } else if (_math == math) { - item += str[i] - } else { - array.push({ text: item, word: math }) - item = str[i] - math = _math - } - } - } - if (item) { - array.push({ text: item, word: math }) - } - return array - } + function splitWords(str) { + if (!str) { + return [] + } + let pattern = /^[0-9a-zA-Z]+$/ + let array = [] + let item = '' + let math = null + for (let i = 0; i < str.length; i++) { + if (str[i] == '\n') { + if (item) { + array.push({ text: item, word: math }) + } + array.push({ text: '\n', word: false }) + item = '' + math = null + } else { + let _math = pattern.test(str[i]) + if (math == null) { + math = _math + item += str[i] + } else if (_math == math) { + item += str[i] + } else { + array.push({ text: item, word: math }) + item = str[i] + math = _math + } + } + } + if (item) { + array.push({ text: item, word: math }) + } + return array + } - function isSymbol(s) { - switch (s) { - case ',': - case '.': - case '!': - case '?': - case ')': - case ';': - case ',': - case '。': - case '!': - case '?': - case ')': - case ';': - case '”': - case ' ': - return true - } - return false - } + function isSymbol(s) { + switch (s) { + case ',': + case '.': + case '!': + case '?': + case ')': + case ';': + case ',': + case '。': + case '!': + case '?': + case ')': + case ';': + case '”': + case ' ': + return true + } + return false + } - function rgb2hsv(r, g, b) { - r /= 255, g /= 255, b /= 255 - let max = Math.max(r, g, b), min = Math.min(r, g, b) - let h, s, v = max - let d = max - min - s = max == 0 ? 0 : d / max - if (max == min) { - h = 0 - } else { - switch (max) { - case r: h = (g - b) / d + (g < b ? 6 : 0); break - case g: h = (b - r) / d + 2; break - case b: h = (r - g) / d + 4; break - } - h /= 6 - } - return [h, s, v] - } + function rgb2hsv(r, g, b) { + r /= 255, g /= 255, b /= 255 + let max = Math.max(r, g, b), min = Math.min(r, g, b) + let h, s, v = max + let d = max - min + s = max == 0 ? 0 : d / max + if (max == min) { + h = 0 + } else { + switch (max) { + case r: h = (g - b) / d + (g < b ? 6 : 0); break + case g: h = (b - r) / d + 2; break + case b: h = (r - g) / d + 4; break + } + h /= 6 + } + return [h, s, v] + } - function hsv2rgb(h, s, v) { - let r, g, b - let i = Math.floor(h * 6) - let f = h * 6 - i - let p = v * (1 - s) - let q = v * (1 - f * s) - let t = v * (1 - (1 - f) * s) - switch (i % 6) { - case 0: r = v, g = t, b = p; break - case 1: r = q, g = v, b = p; break - case 2: r = p, g = v, b = t; break - case 3: r = p, g = q, b = v; break - case 4: r = t, g = p, b = v; break - case 5: r = v, g = p, b = q; break - } - return [r * 255, g * 255, b * 255] - } + function hsv2rgb(h, s, v) { + let r, g, b + let i = Math.floor(h * 6) + let f = h * 6 - i + let p = v * (1 - s) + let q = v * (1 - f * s) + let t = v * (1 - (1 - f) * s) + switch (i % 6) { + case 0: r = v, g = t, b = p; break + case 1: r = q, g = v, b = p; break + case 2: r = p, g = v, b = t; break + case 3: r = p, g = q, b = v; break + case 4: r = t, g = p, b = v; break + case 5: r = v, g = p, b = q; break + } + return [r * 255, g * 255, b * 255] + } - function text(obj) { - if (obj == null) { - return null - } - let text = obj.text - if (text != null) { - return text - } - if (obj.children != null && obj.children.length > 0) { - let textAll = '' - for (let i = 0; i < obj.children.length; i++) { - let p = obj.children[i] - if (p.children == null) { - continue - } - let pText = '' - for (let j = 0; j < p.children.length; j++) { - let r = p.children[j] - if (r.text == null) { - continue - } - pText += r.text - } - if (pText) { - textAll += (pText + '\n') - } - } - if (textAll.length > 0) { - textAll = textAll.substring(0, textAll.length - 1) - } - return textAll - } - return '' - } + function text(obj) { + if (obj == null) { + return null + } + let text = obj.text + if (text != null) { + return text + } + if (obj.children != null && obj.children.length > 0) { + let textAll = '' + for (let i = 0; i < obj.children.length; i++) { + let p = obj.children[i] + if (p.children == null) { + continue + } + let pText = '' + for (let j = 0; j < p.children.length; j++) { + let r = p.children[j] + if (r.text == null) { + continue + } + pText += r.text + } + if (pText) { + textAll += (pText + '\n') + } + } + if (textAll.length > 0) { + textAll = textAll.substring(0, textAll.length - 1) + } + return textAll + } + return '' + } - this.setTemplateHandle = (_templateHandle) => { - templateHandle = _templateHandle - } + this.setTemplateHandle = (_templateHandle) => { + templateHandle = _templateHandle + } - this.idMap = idMap - this.recursion = recursion - this.drawGeometry = drawGeometry - this.drawElement = drawElement - this.toPaint = toPaint - this.toColor = toColor - this.toColorValue = toColorValue - this.loadImage = loadImage - this.text = text + this.idMap = idMap + this.recursion = recursion + this.drawGeometry = drawGeometry + this.drawElement = drawElement + this.toPaint = toPaint + this.toColor = toColor + this.toColorValue = toColorValue + this.loadImage = loadImage + this.text = text } diff --git a/static/ppt2svg.js b/static/ppt2svg.js index 0ae6d44..f53764e 100644 --- a/static/ppt2svg.js +++ b/static/ppt2svg.js @@ -1,4 +1,4 @@ -/* eslint-disable @typescript-eslint/no-unused-vars */ +/* eslint-disable no-unused-vars */ // import { geometryPaths } from './geometry.js' // import { drawChart } from './chart.js'