伪造具有多层的 MarkupUtils renderToCanvas?
Forge MarkupUtils renderToCanvas with multiple layers?
我们目前将一个 PDF 加载到 Forge 查看器中,其中包含多个标记层(使用自定义 DrawMode 创建),每个层的可见性均可切换。
我们想让用户能够打印他们当前看到的内容(带有分层标记的 PDF)。我能够找到 posts 提供潜在的打印解决方案(使用 canvas、getScreenshot 和 MarkupUtils renderToCanvas)。
示例 post:
该解决方案起初看起来效果很好,但我注意到只有一个标记层被渲染到 canvas(似乎是最后添加的一个),其他层被忽略。
所有标记均已加载并在屏幕上可见。此外,如果我隐藏该层,它仍会打印出来。
有没有办法使用 renderToCanvas 从所有加载的标记层添加标记?
或者任何潜在的已知解决方法?
感谢任何帮助。提前致谢。
我编写的有效函数的代码片段(但仅加载最近添加的图层)。
export const printViewerToPDF = (markupsCore: MarkupsCore, jsPDF: any) => {
// Create new image
var screenshot = new Image();
// Get the canvas element
var canvas = document.getElementById('snapshot') as HTMLCanvasElement;
// Fit canvas to match viewer
if (canvas) {
canvas.width = markupsCore.bounds.width;
canvas.height = markupsCore.bounds.height;
// Create a context
var ctx = canvas.getContext('2d');
// Clear
if (ctx) {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(screenshot, 0, 0, canvas.width, canvas.height);
}
// Screenshot viewer and render to canvas
markupsCore.viewer.getScreenShot(canvas.width, canvas.height, function(
blobUrl: any,
) {
screenshot.onload = function() {
if (ctx) {
ctx.drawImage(screenshot, 0, 0);
}
};
screenshot.src = blobUrl;
});
// Render markup to canvas
setTimeout(function() {
markupsCore.renderToCanvas(ctx, function() {
var pdf = new jsPDF('l', 'px', [canvas.height, canvas.width]);
pdf.addImage(ctx!.canvas, 0, 0, canvas.width, canvas.height);
pdf.save(Date.now().toString() + '.pdf');
});
}, 300);
}
};
这是 renderToCanvas
方法的样子(您可以在 https://developer.api.autodesk.com/modelderivative/v2/viewers/7.*/extensions/Markup/Markup.js 中找到它):
MarkupsCore.prototype.renderToCanvas = function(context, callback, renderAllMarkups) {
var width = this.bounds.width;
var height = this.bounds.height;
var viewBox = this.getSvgViewBox(width, height);
var numberOfScreenshotsTaken = 0;
var markups = [];
var layer;
var onMarkupScreenshotTaken = function () {
if (callback && (++numberOfScreenshotsTaken === markups.length)) {
callback();
}
}.bind(this);
if (renderAllMarkups) {
var svgKeys = Object.keys(this.svg.childNodes);
var layersKeys = Object.keys(this.svgLayersMap);
// Append only markups that their parent layer is contained inside the svg main container.
for (var i = 0; i < svgKeys.length; i++) {
for (var j = 0; j < layersKeys.length; j++) {
layer = this.svgLayersMap[layersKeys[j]];
if (this.svg.childNodes[svgKeys[i]] === layer.svg) {
markups = markups.concat(layer.markups);
}
}
}
} else {
layer = this.svgLayersMap[this.activeLayer] || this.editModeSvgLayerNode;
markups = layer.markups;
}
if (markups.length === 0) {
callback();
} else {
markups.forEach(function(markup) {
markup.renderToCanvas(context, viewBox, width, height, onMarkupScreenshotTaken);
});
}
};
如您所见,如果您未定义第 3 个参数或将其设置为 false
,则只会呈现来自 active 层的标记。如果将第三个参数设置为 true
,则应呈现所有层的标记。
在为列表中的每个项目调用 markup.renderToCanvas
之前,尝试自己进入该方法并在最后仔细检查标记列表。
我们目前将一个 PDF 加载到 Forge 查看器中,其中包含多个标记层(使用自定义 DrawMode 创建),每个层的可见性均可切换。
我们想让用户能够打印他们当前看到的内容(带有分层标记的 PDF)。我能够找到 posts 提供潜在的打印解决方案(使用 canvas、getScreenshot 和 MarkupUtils renderToCanvas)。
示例 post:
该解决方案起初看起来效果很好,但我注意到只有一个标记层被渲染到 canvas(似乎是最后添加的一个),其他层被忽略。
所有标记均已加载并在屏幕上可见。此外,如果我隐藏该层,它仍会打印出来。
有没有办法使用 renderToCanvas 从所有加载的标记层添加标记? 或者任何潜在的已知解决方法?
感谢任何帮助。提前致谢。
我编写的有效函数的代码片段(但仅加载最近添加的图层)。
export const printViewerToPDF = (markupsCore: MarkupsCore, jsPDF: any) => {
// Create new image
var screenshot = new Image();
// Get the canvas element
var canvas = document.getElementById('snapshot') as HTMLCanvasElement;
// Fit canvas to match viewer
if (canvas) {
canvas.width = markupsCore.bounds.width;
canvas.height = markupsCore.bounds.height;
// Create a context
var ctx = canvas.getContext('2d');
// Clear
if (ctx) {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(screenshot, 0, 0, canvas.width, canvas.height);
}
// Screenshot viewer and render to canvas
markupsCore.viewer.getScreenShot(canvas.width, canvas.height, function(
blobUrl: any,
) {
screenshot.onload = function() {
if (ctx) {
ctx.drawImage(screenshot, 0, 0);
}
};
screenshot.src = blobUrl;
});
// Render markup to canvas
setTimeout(function() {
markupsCore.renderToCanvas(ctx, function() {
var pdf = new jsPDF('l', 'px', [canvas.height, canvas.width]);
pdf.addImage(ctx!.canvas, 0, 0, canvas.width, canvas.height);
pdf.save(Date.now().toString() + '.pdf');
});
}, 300);
}
};
这是 renderToCanvas
方法的样子(您可以在 https://developer.api.autodesk.com/modelderivative/v2/viewers/7.*/extensions/Markup/Markup.js 中找到它):
MarkupsCore.prototype.renderToCanvas = function(context, callback, renderAllMarkups) {
var width = this.bounds.width;
var height = this.bounds.height;
var viewBox = this.getSvgViewBox(width, height);
var numberOfScreenshotsTaken = 0;
var markups = [];
var layer;
var onMarkupScreenshotTaken = function () {
if (callback && (++numberOfScreenshotsTaken === markups.length)) {
callback();
}
}.bind(this);
if (renderAllMarkups) {
var svgKeys = Object.keys(this.svg.childNodes);
var layersKeys = Object.keys(this.svgLayersMap);
// Append only markups that their parent layer is contained inside the svg main container.
for (var i = 0; i < svgKeys.length; i++) {
for (var j = 0; j < layersKeys.length; j++) {
layer = this.svgLayersMap[layersKeys[j]];
if (this.svg.childNodes[svgKeys[i]] === layer.svg) {
markups = markups.concat(layer.markups);
}
}
}
} else {
layer = this.svgLayersMap[this.activeLayer] || this.editModeSvgLayerNode;
markups = layer.markups;
}
if (markups.length === 0) {
callback();
} else {
markups.forEach(function(markup) {
markup.renderToCanvas(context, viewBox, width, height, onMarkupScreenshotTaken);
});
}
};
如您所见,如果您未定义第 3 个参数或将其设置为 false
,则只会呈现来自 active 层的标记。如果将第三个参数设置为 true
,则应呈现所有层的标记。
在为列表中的每个项目调用 markup.renderToCanvas
之前,尝试自己进入该方法并在最后仔细检查标记列表。