Autodesk Forge Viewer Api 无法在屏幕截图中加载标记

Autodesk Forge Viewer Api Cannot load markups inside screenshot

美好的一天,

我使用的是最新的 Autodesk Forge 查看器,我正在尝试截取同时呈现我的标记的屏幕截图。现在我的代码截取了一张没有任何标记的屏幕截图。下面是我的查看器代码。我正在加载标记核心和标记 Gui 扩展。注意 onDocumentLoadSuccess(viewerDocument) 中的“takeSnapshot(viewer)”函数。该函数在初始化函数之前定义。

function takeSnapshot(target){
    $('#snipViewer').click( () => {
        target.getScreenShot(1600, 920, (blobURL) => {
            let snip = blobURL;
            $('#sniplink').attr("href", snip);
            $('#sniplink').html('Not Empty');
            $('#sniplink').css({"background-image": `url(${blobURL})`});
        });
    });        
}

//Autodesk Viewer Code

instance.data.showViewer = function showViewer(viewerAccessToken, viewerUrn){
    localStorage.setItem("viewerAccessTokentoken", viewerAccessToken);
    localStorage.setItem("viewerUrn", viewerUrn);  
    var viewer;
    var options = {
        env: 'AutodeskProduction',
        api: 'derivativeV2',
        getAccessToken: function(onTokenReady) {
            var token = viewerAccessToken;
            var timeInSeconds = 3600;
            onTokenReady(token, timeInSeconds);
        }
    };
    Autodesk.Viewing.Initializer(options, function() {
        let htmlDiv = document.getElementById('forgeViewer');
        viewer = new Autodesk.Viewing.GuiViewer3D(htmlDiv);
        let startedCode = viewer.start();
        viewer.setTheme("light-theme");
        viewer.loadExtension("Autodesk.CustomDocumentBrowser").then(() => {
            viewer.loadExtension("Autodesk.Viewing.MarkupsCore");
            viewer.loadExtension("Autodesk.Viewing.MarkupsGui");
        });
        if (startedCode > 0) {
            console.error('Failed to create a Viewer: WebGL not supported.');
            $("#loadingStatus").html("Failed to create a Viewer: WebGL not supported.");
            return;
        }
        console.log('Initialization complete, loading a model next...');
    });
    var documentId = `urn:` + viewerUrn;
    var derivativeId = `urn:` + instance.derivativeUrn;
    Autodesk.Viewing.Document.load(documentId, onDocumentLoadSuccess, onDocumentLoadFailure);
    function onDocumentLoadSuccess(viewerDocument) {
        var defaultModel = viewerDocument.getRoot().getDefaultGeometry();
        viewer.loadDocumentNode(viewerDocument, defaultModel);
        takeSnapshot(viewer);
    }
    function onDocumentLoadFailure() {
        console.error('Failed fetching Forge manifest');
        $("#loadingStatus").html("Failed fetching Forge manifest.");
    }
}

我已经读过这篇文章:https://forge.autodesk.com/blog/screenshot-markups 我试过使用这种方法,但说明对我来说非常不清楚。 <div style="width:49vw; height:100vh;display:inline-block;"><canvas id="snapshot" style="position:absolute;"></canvas><button onclick="snaphot();" style="position:absolute;">Snapshot!</button></div>

这里的 canvas 元素是做什么用的?当我在初始化函数或屏幕截图函数中加载标记扩展时,我是否应该 renderToCanvas() ?有什么方法可以实现 renderToCanvas() 而无需过多更改我已经在此处使用的内容吗?我不是查看器专家 API 所以如果你能帮助我,我将不胜感激,我是初学者,请不要跳过很多步骤。

非常感谢!

这里有一些在 Forge Viewer 中生成带标记的屏幕截图的更简化的逻辑,下面还有一些关于为什么需要这样做的更多解释:

function getViewerScreenshot(viewer) {
    return new Promise(function (resolve, reject) {
        const screenshot = new Image();
        screenshot.onload = () => resolve(screenshot);
        screenshot.onerror = err => reject(err);
        viewer.getScreenShot(viewer.container.clientWidth, viewer.container.clientHeight, function (blobURL) {
            screenshot.src = blobURL;
        });
    });
}
function addMarkupsToScreenshot(viewer, screenshot) {
    return new Promise(function (resolve, reject) {
        const markupCoreExt = viewer.getExtension('Autodesk.Viewing.MarkupsCore');
        const canvas = document.createElement('canvas');
        canvas.width = viewer.container.clientWidth;
        canvas.height = viewer.container.clientHeight;
        const context = canvas.getContext('2d');
        context.clearRect(0, 0, canvas.width, canvas.height);
        context.drawImage(screenshot, 0, 0, canvas.width, canvas.height);
        markupCoreExt.renderToCanvas(context, function () {
            resolve(canvas);
        });
    });
}
const screenshot = await getViewerScreenshot(viewer);
const canvas = await addMarkupsToScreenshot(viewer, screenshot);
const link = document.createElement('a');
link.href = canvas.toDataURL();
link.download = 'screenshot.png';
link.click();

基本上,标记扩展只能将其标记(而不是底层 2D/3D 场景)渲染到现有的 <canvas> 元素中。这就是为什么这是一个多步骤过程:

  1. 您使用 viewer.getScreenShot 渲染底层 2D/3D 场景,获取包含屏幕截图图像数据的 blob URL
  2. 您创建了一个新的 <canvas> 元素
  3. 您将屏幕截图插入 canvas(在本例中,我们创建一个新的 Image 实例并使用 context.drawImage 将其渲染到 canvas)
  4. 您调用扩展程序的 renderToCanvas,它将在屏幕截图图像 canvas 顶部 中呈现标记