Forge Viewer: Печать листов
Сейчас Forge Viewer не предоставлят функицонала печати. BIM 360 фактически создает скриншот листа, показанного в Forge Viewer, размещает созданную картинку в HTML и вызывает функцию window.print().
В нашем блоге уже есть статья о создании скриншотов в Forge Viewer и создании скриншотов листов модели на сервере.
Вместо того, чтобы самим определять границы листа модели в Forge Viewer, мы можем воспользоваться функционалом, предоставляемым методом Autodesk.Viewing.ScreenShot.getScreenShotWithBounds(), передав в качестве параметра следующие настройки:
- { fullPage: true, margin: 0 }
В метод getScreenShowWithBounds мы передаем callback - функцию onDone, в которую будут переданы ширина, высота и blob URL созданной картинки. Полученные ширину и высоту мы будем использовать в шаблоне страницы, которую мы отправляем на печать при помощи функции window.print().
Мы также можем автоматически закрывать дополнительную вкладку или окно, когда пользователь закроет диалог печати, используя для этого событие onafterprint.
Пример возможной реализации, см. функцию printSheet():
- <html>
- <head>
- <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1, user-scalable=no" />
- <meta charset="utf-8">
- <!-- Viewer CSS -->
- <link rel="stylesheet" href="https://developer.api.autodesk.com/modelderivative/v2/viewers/7.*/style.min.css" type="text/css">
- <!-- CSS приложения -->
- <style>
- body {
- margin: 0;
- position: relative;
- }
- #MyContainerDiv {
- width: 100vw;
- height: 100vh;
- position: relative;
- }
- </style>
- </head>
- <body>
- <!-- Forge Viewer будет размещен здесь -->
- <div id="MyContainerDiv">
- </div>
- <!-- Forge Viewer JS -->
- <!-- jQuery -->
- <!-- JS приложения -->
- <script>
- // iframe URL из A360, он показывается при нажатии кнопки Share
- var embedURLfromA360 = 'https://autodesk3743.autodesk360.com/shares/public/SH919a0QTf3c32634dcf07b66797ba369695?mode=embed' // PDF-файл
- var viewer
- function getURN(onURNCallback) {
- $.get({
- url: embedURLfromA360.replace('public', 'metadata').replace('mode=embed', ''),
- dataType: 'json',
- success: function (metadata) {
- if (onURNCallback) {
- let urn = btoa(metadata.success.body.urn).replace("/", "_").replace("=", "")
- onURNCallback(urn)
- }
- }
- })
- }
- function getForgeToken(onTokenCallback) {
- $.post({
- url: embedURLfromA360.replace('public', 'sign').replace('mode=embed', 'oauth2=true'),
- data: '{}',
- success: function (oauth) {
- if (onTokenCallback)
- onTokenCallback(oauth.accessToken, oauth.validitySeconds)
- }
- })
- }
- getURN(function (urn) {
- var options = {
- env: 'AutodeskProduction',
- getAccessToken: getForgeToken
- }
- var documentId = 'urn:' + urn
- Autodesk.Viewing.Initializer(options, function onInitialized() {
- Autodesk.Viewing.Document.load(documentId, onDocumentLoadSuccess)
- })
- })
- function onDocumentLoadSuccess(doc) {
- // Документ содержит 3D и 2D сцены.
- var items = doc.getRoot().search({
- 'type': 'geometry',
- 'role': '2d'
- }, true)
- if (items.length === 0) {
- console.error('Document contains no viewables.')
- return
- }
- var viewerDiv = document.getElementById('MyViewerDiv')
- viewer = new Autodesk.Viewing.GuiViewer3D(viewerDiv)
- viewer.start()
- viewer.loadDocumentNode(doc, items[1], {}).then(() => {
- let group = viewer.toolbar.getControl('printToolbar');
- if (!group) {
- group = new Autodesk.Viewing.UI.ControlGroup('printToolbar');
- viewer.toolbar.addControl(group);
- }
- // Добавляем новую кнопку в группу кнопок toolbar-а
- button = new Autodesk.Viewing.UI.Button('printButton');
- button.setIcon('adsk-icon-layers');
- button.onClick = () => {
- printSheet(viewer)
- }
- button.setToolTip('Print Sheet');
- group.addControl(button);
- })
- }
- function printSheet(viewer) {
- let onDone = async (blob, imageWidth, imageHeight) => {
- let res = await fetch("printpage.html")
- let content = await res.text()
- // Высота картинки должна быть чётной, для того чтобы в диалоге печати не появлялось дополнительное пустое место
- imageHeight = imageHeight % 2 ? imageHeight + 1 : imageHeight
- content = content
- .replace(new RegExp("%IMG_WIDTH%", "g"), imageWidth)
- .replace(new RegExp("%IMG_HEIGHT%", "g"), imageHeight)
- .replace("%IMG_SRC%", blob)
- let w = window.open('', '')
- if (w) {
- w.document.open()
- w.document.write(content)
- w.document.close()
- } else {
- console.info("Could not open a new window")
- }
- }
- const canvasBounds = viewer.impl.getCanvasBoundingClientRect()
- const originalWidth = canvasBounds.width
- const originalHeight = canvasBounds.height
- let widthInPixels
- let pageWidth = viewer.model.getMetadata('page_dimensions', 'page_width')
- const pageUnits = viewer.model.getMetadata('page_dimensions', 'page_units')
- // если page_units не указан, значит у нас растровое изображение и pageWidth уже в пикселях
- if (pageUnits) {
- const widthInInch = Autodesk.Viewing.Private.convertUnits(pageUnits.toLowerCase(), 'in', 1, pageWidth)
- const DPI = 150
- widthInPixels = Math.floor(widthInInch * DPI)
- } else {
- widthInPixels = pageWidth
- }
- const canvasRatio = originalHeight / originalWidth
- const width = widthInPixels
- const height = Math.floor(widthInPixels * canvasRatio)
- const screenshotOptions = {
- fullPage: true,
- margin: 0,
- }
- Autodesk.Viewing.ScreenShot.getScreenShotWithBounds(viewer, width, height, onDone, screenshotOptions)
- }
- </script>
- </body>
- </html>
А вот шаблон страницы (printpage.html), используемой для печати:
- <html>
- <head>
- <style>
- @page {
- size: %IMG_WIDTH%px %IMG_HEIGHT%px;
- margin: 0;
- }
- @media print {
- html,
- body {
- margin: 0;
- }
- }
- </style>
- <script>
- function onImageLoad() {
- window.print();
- }
- function onAfterPrint() {
- window.close();
- }
- </script>
- </head>
- <body onafterprint="onAfterPrint()">
- <img src="%IMG_SRC%" width="%IMG_WIDTH%px" height="%IMG_HEIGHT%px" onload="onImageLoad()" />
- </body>
- </html>
Источник: https://forge.autodesk.com/blog/print-sheet-viewer
Опубликовано 30.04.2021