Create a separate toolbar button for image export #221
This commit is contained in:
parent
f4f6228426
commit
da1c019fd0
@ -13,22 +13,15 @@ import { DownloadArrayBufferAsFile, DownloadUrlAsFile } from './utils.js';
|
||||
import { CookieGetStringVal, CookieSetStringVal } from './cookiehandler.js';
|
||||
import { HandleEvent } from './eventhandler.js';
|
||||
|
||||
const ExportType =
|
||||
class ModelExporterUI
|
||||
{
|
||||
Model : 0,
|
||||
Image : 1
|
||||
};
|
||||
|
||||
class ExporterUI
|
||||
{
|
||||
constructor (name)
|
||||
constructor (name, format, extension)
|
||||
{
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
GetType ()
|
||||
{
|
||||
return null;
|
||||
this.format = format;
|
||||
this.extension = extension;
|
||||
this.visibleOnlySelect = null;
|
||||
this.rotationSelect = null;
|
||||
}
|
||||
|
||||
GetName ()
|
||||
@ -38,38 +31,16 @@ class ExporterUI
|
||||
|
||||
GenerateParametersUI (parametersDiv)
|
||||
{
|
||||
function AddSelectItem (parametersDiv, name, values, defaultIndex)
|
||||
{
|
||||
let parameterRow = AddDiv (parametersDiv, 'ov_dialog_row');
|
||||
AddDiv (parameterRow, 'ov_dialog_row_name', name);
|
||||
let parameterValueDiv = AddDiv (parameterRow, 'ov_dialog_row_value');
|
||||
return AddSelect (parameterValueDiv, values, defaultIndex);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
AddSelectItem (parametersDiv, name, values, defaultIndex)
|
||||
{
|
||||
let parameterRow = AddDiv (parametersDiv, 'ov_dialog_row');
|
||||
AddDiv (parameterRow, 'ov_dialog_row_name', name);
|
||||
let parameterValueDiv = AddDiv (parameterRow, 'ov_dialog_row_value');
|
||||
return AddSelect (parameterValueDiv, values, defaultIndex);
|
||||
}
|
||||
}
|
||||
|
||||
class ModelExporterUI extends ExporterUI
|
||||
{
|
||||
constructor (name, format, extension)
|
||||
{
|
||||
super (name);
|
||||
this.format = format;
|
||||
this.extension = extension;
|
||||
this.visibleOnlySelect = null;
|
||||
this.rotationSelect = null;
|
||||
}
|
||||
|
||||
GetType ()
|
||||
{
|
||||
return ExportType.Model;
|
||||
}
|
||||
|
||||
GenerateParametersUI (parametersDiv)
|
||||
{
|
||||
this.visibleOnlySelect = this.AddSelectItem (parametersDiv, 'Scope', ['Entire Model', 'Visible Only'], 1);
|
||||
this.rotationSelect = this.AddSelectItem (parametersDiv, 'Rotation', ['No Rotation', '-90 Degrees', '90 Degrees'], 0);
|
||||
this.visibleOnlySelect = AddSelectItem (parametersDiv, 'Scope', ['Entire Model', 'Visible Only'], 1);
|
||||
this.rotationSelect = AddSelectItem (parametersDiv, 'Rotation', ['No Rotation', '-90 Degrees', '90 Degrees'], 0);
|
||||
}
|
||||
|
||||
ExportModel (model, callbacks)
|
||||
@ -136,45 +107,6 @@ class ModelExporterUI extends ExporterUI
|
||||
}
|
||||
}
|
||||
|
||||
class ImageExporterUI extends ExporterUI
|
||||
{
|
||||
constructor (name, extension)
|
||||
{
|
||||
super (name);
|
||||
this.extension = extension;
|
||||
this.sizeSelect = null;
|
||||
this.sizes = [
|
||||
{ name : 'Current size', value : null },
|
||||
{ name : '1280 x 720', value : [1280, 720] },
|
||||
{ name : '1920 x 1080', value : [1920, 1080] }
|
||||
];
|
||||
}
|
||||
|
||||
GetType ()
|
||||
{
|
||||
return ExportType.Image;
|
||||
}
|
||||
|
||||
GenerateParametersUI (parametersDiv)
|
||||
{
|
||||
let sizeNames = this.sizes.map (size => size.name);
|
||||
this.sizeSelect = this.AddSelectItem (parametersDiv, 'Image size', sizeNames, 1);
|
||||
}
|
||||
|
||||
ExportImage (viewer)
|
||||
{
|
||||
let selectedSize = this.sizes[this.sizeSelect.selectedIndex];
|
||||
let url = null;
|
||||
if (selectedSize.value === null) {
|
||||
let size = viewer.GetImageSize ();
|
||||
url = viewer.GetImageAsDataUrl (size.width, size.height);
|
||||
} else {
|
||||
url = viewer.GetImageAsDataUrl (selectedSize.value[0], selectedSize.value[1]);
|
||||
}
|
||||
DownloadUrlAsFile (url, 'model.' + this.extension);
|
||||
}
|
||||
}
|
||||
|
||||
class ExportDialog
|
||||
{
|
||||
constructor (callbacks)
|
||||
@ -192,8 +124,7 @@ class ExportDialog
|
||||
new ModelExporterUI ('glTF Text (.gltf)', FileFormat.Text, 'gltf'),
|
||||
new ModelExporterUI ('glTF Binary (.glb)', FileFormat.Binary, 'glb'),
|
||||
new ModelExporterUI ('Object File Format Text (.off)', FileFormat.Text, 'off'),
|
||||
new ModelExporterUI ('Rhinoceros 3D (.3dm)', FileFormat.Binary, '3dm'),
|
||||
new ImageExporterUI ('PNG Image (.png)', 'png')
|
||||
new ModelExporterUI ('Rhinoceros 3D (.3dm)', FileFormat.Binary, '3dm')
|
||||
];
|
||||
}
|
||||
|
||||
@ -246,16 +177,12 @@ class ExportDialog
|
||||
|
||||
ExportFormat (model, viewer)
|
||||
{
|
||||
if (this.selectedExporter.GetType () === ExportType.Model) {
|
||||
this.selectedExporter.ExportModel (model, {
|
||||
isMeshVisible : (meshInstanceId) => {
|
||||
return this.callbacks.isMeshVisible (meshInstanceId);
|
||||
}
|
||||
});
|
||||
HandleEvent ('model_exported', this.selectedExporter.GetName ());
|
||||
} else if (this.selectedExporter.GetType () === ExportType.Image) {
|
||||
this.selectedExporter.ExportImage (viewer);
|
||||
}
|
||||
this.selectedExporter.ExportModel (model, {
|
||||
isMeshVisible : (meshInstanceId) => {
|
||||
return this.callbacks.isMeshVisible (meshInstanceId);
|
||||
}
|
||||
});
|
||||
HandleEvent ('model_exported', this.selectedExporter.GetName ());
|
||||
}
|
||||
}
|
||||
|
||||
@ -318,6 +245,7 @@ export function ShowSnapshotDialog (viewer)
|
||||
name : 'Create',
|
||||
onClick () {
|
||||
dialog.Close ();
|
||||
HandleEvent ('snapshot_created', sizes[selectedIndex].name);
|
||||
let url = GetImageUrl (viewer, sizes[selectedIndex]);
|
||||
DownloadUrlAsFile (url, 'model.png');
|
||||
}
|
||||
@ -327,7 +255,7 @@ export function ShowSnapshotDialog (viewer)
|
||||
let optionsDiv = AddDiv (contentDiv, 'ov_snapshot_dialog_left');
|
||||
let previewImage = CreateDomElement ('img', 'ov_snapshot_dialog_preview');
|
||||
|
||||
let lastSnapshotSizeName = CookieGetStringVal ('ov_last_snapshot_size', sizes[0].name);
|
||||
let lastSnapshotSizeName = CookieGetStringVal ('ov_last_snapshot_size', sizes[1].name);
|
||||
for (let i = 0; i < sizes.length; i++) {
|
||||
if (lastSnapshotSizeName === sizes[i].name) {
|
||||
selectedIndex = i;
|
||||
|
||||
@ -11,7 +11,7 @@ import { Sidebar } from './sidebar.js';
|
||||
import { ThemeHandler } from './themehandler.js';
|
||||
import { ThreeModelLoaderUI } from './threemodelloaderui.js';
|
||||
import { Toolbar } from './toolbar.js';
|
||||
import { ShowExportDialog } from './exportdialog.js';
|
||||
import { ShowExportDialog, ShowSnapshotDialog } from './exportdialog.js';
|
||||
import { AddSmallWidthChangeEventListener, GetFilesFromDataTransfer, IsSmallWidth } from './utils.js';
|
||||
import { ShowOpenUrlDialog } from './openurldialog.js';
|
||||
import { ShowSharingDialog } from './sharingdialog.js';
|
||||
@ -565,6 +565,9 @@ export class Website
|
||||
});
|
||||
this.measureTool.SetButton (measureToolButton);
|
||||
AddSeparator (this.toolbar, ['only_full_width', 'only_on_model']);
|
||||
AddButton (this.toolbar, 'snapshot', 'Create snapshot', ['only_full_width', 'only_on_model'], () => {
|
||||
ShowSnapshotDialog (this.viewer);
|
||||
});
|
||||
AddButton (this.toolbar, 'export', 'Export model', ['only_full_width', 'only_on_model'], () => {
|
||||
ShowExportDialog (this.model, this.viewer, {
|
||||
isMeshVisible : (meshInstanceId) => {
|
||||
|
||||
Binary file not shown.
@ -258,8 +258,9 @@ div.ov_snapshot_dialog_left
|
||||
img.ov_snapshot_dialog_preview
|
||||
{
|
||||
background: var(--ov_border_color);
|
||||
width: 250px;
|
||||
height: 140px;
|
||||
border: 1px solid var(--ov_border_color);
|
||||
width: 240px;
|
||||
height: 135px;
|
||||
object-fit: contain;
|
||||
float: right;
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
@font-face {
|
||||
font-family: "O3DVIcons";
|
||||
src: url("O3DVIcons/O3DVIcons.woff?8e8ff80e3f2f51d21873c070a35e0f3c") format("woff");
|
||||
src: url("O3DVIcons/O3DVIcons.woff?3aa6f39e888e50c0858037b7381ba7ac") format("woff");
|
||||
}
|
||||
|
||||
i[class^="icon-"]:before, i[class*=" icon-"]:before {
|
||||
@ -119,24 +119,27 @@ i[class^="icon-"]:before, i[class*=" icon-"]:before {
|
||||
.icon-share:before {
|
||||
content: "\f123";
|
||||
}
|
||||
.icon-tree_mesh:before {
|
||||
.icon-snapshot:before {
|
||||
content: "\f124";
|
||||
}
|
||||
.icon-tree_view:before {
|
||||
.icon-tree_mesh:before {
|
||||
content: "\f125";
|
||||
}
|
||||
.icon-twitter:before {
|
||||
.icon-tree_view:before {
|
||||
content: "\f126";
|
||||
}
|
||||
.icon-up_y:before {
|
||||
.icon-twitter:before {
|
||||
content: "\f127";
|
||||
}
|
||||
.icon-up_z:before {
|
||||
.icon-up_y:before {
|
||||
content: "\f128";
|
||||
}
|
||||
.icon-visible:before {
|
||||
.icon-up_z:before {
|
||||
content: "\f129";
|
||||
}
|
||||
.icon-warning:before {
|
||||
.icon-visible:before {
|
||||
content: "\f12a";
|
||||
}
|
||||
.icon-warning:before {
|
||||
content: "\f12b";
|
||||
}
|
||||
|
||||
Binary file not shown.
@ -1,6 +1,6 @@
|
||||
@font-face {
|
||||
font-family: "O3DVIcons";
|
||||
src: url("./O3DVIcons.woff?8e8ff80e3f2f51d21873c070a35e0f3c") format("woff");
|
||||
src: url("./O3DVIcons.woff?3aa6f39e888e50c0858037b7381ba7ac") format("woff");
|
||||
}
|
||||
|
||||
i[class^="icon-"]:before, i[class*=" icon-"]:before {
|
||||
@ -119,24 +119,27 @@ i[class^="icon-"]:before, i[class*=" icon-"]:before {
|
||||
.icon-share:before {
|
||||
content: "\f123";
|
||||
}
|
||||
.icon-tree_mesh:before {
|
||||
.icon-snapshot:before {
|
||||
content: "\f124";
|
||||
}
|
||||
.icon-tree_view:before {
|
||||
.icon-tree_mesh:before {
|
||||
content: "\f125";
|
||||
}
|
||||
.icon-twitter:before {
|
||||
.icon-tree_view:before {
|
||||
content: "\f126";
|
||||
}
|
||||
.icon-up_y:before {
|
||||
.icon-twitter:before {
|
||||
content: "\f127";
|
||||
}
|
||||
.icon-up_z:before {
|
||||
.icon-up_y:before {
|
||||
content: "\f128";
|
||||
}
|
||||
.icon-visible:before {
|
||||
.icon-up_z:before {
|
||||
content: "\f129";
|
||||
}
|
||||
.icon-warning:before {
|
||||
.icon-visible:before {
|
||||
content: "\f12a";
|
||||
}
|
||||
.icon-warning:before {
|
||||
content: "\f12b";
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user