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