FullScreenRenderWindow

Introduction

vtkFullScreenRenderWindow provides a skeleton for implementing a fullscreen
render window.

Methods

addController

Argument Type Required Description
html HTMLElement Yes

addRepresentation

Representation API

Argument Type Required Description
representation Yes

delete

Release GL context

extend

Method used to decorate a given object (publicAPI+model) with vtkFullScreenRenderWindow characteristics.

Argument Type Required Description
publicAPI Yes object on which methods will be bounds (public)
model Yes object on which data structure will be bounds (protected)
initialValues IFullScreenRenderWindowInitialValues No (default: {})

getApiSpecificRenderWindow

Returns vtkWebGPURenderWindow if ?viewAPI=’WebGPU’ is in URL, or if
vtkFullScreenRenderWindow has been created with “defaultViewAPI: ‘WebGPU”,
otherwise vtkOpenGLRenderWindow is returned.

getContainer

Get container element

getControlContainer

Get control container element

getInteractor

Get interactor object

getRenderWindow

Get Render windows object

getRenderer

Get Renderer object

getRootContainer

Get root container element

newInstance

Method used to create a new instance of vtkFullScreenRenderWindow

Argument Type Required Description
initialValues IFullScreenRenderWindowInitialValues No for pre-setting some of its content

removeController

Remove controller

removeRepresentation

Remove representation

Argument Type Required Description
representation Yes

resize

Handle window resize

setBackground

Set background color

Argument Type Required Description
background RGBColor or RGBAColor Yes The background color.

setControllerVisibility

Hide or show controller

Argument Type Required Description
visible Boolean Yes

setResizeCallback

Argument Type Required Description
cb Yes

toggleControllerVisibility

Toggle controller visibility

Source

index.d.ts
import { vtkObject } from '../../../interfaces';
import { RGBAColor, RGBColor } from '../../../types';
import vtkRenderer from '../../Core/Renderer';
import vtkRenderWindow from '../../Core/RenderWindow';
import vtkRenderWindowInteractor from '../../Core/RenderWindowInteractor';

// import vtkOpenGLRenderWindow from "../../../OpenGL/RenderWindow";
// import vtkWebGPURenderWindow from "../../../WebGPU/RenderWindow";

/**
*
*/
export interface IFullScreenRenderWindowInitialValues {
background?: RGBColor | RGBAColor;
container?: HTMLElement;
containerStyle?: object;
controlPanelStyle?: object;
controllerVisibility?: boolean;
defaultViewAPI?: boolean;
listenWindowResize?: boolean;
resizeCallback?: any;
}

export interface vtkFullScreenRenderWindow extends vtkObject {
/**
*
* @param {HTMLElement} html
*/
addController(html: HTMLElement): void;

/**
* Representation API
* @param representation
*/
addRepresentation(representation: any): void;

/**
* Release GL context
*/
delete(): void;

/**
* Returns vtkWebGPURenderWindow if ?viewAPI='WebGPU' is in URL, or if
* vtkFullScreenRenderWindow has been created with "defaultViewAPI: 'WebGPU",
* otherwise vtkOpenGLRenderWindow is returned.
*/
getApiSpecificRenderWindow(): any; // vtkOpenGLRenderWindow || vtkWebGPURenderWindow

/**
* Get container element
*/
getContainer(): HTMLElement;

/**
* Get control container element
*/
getControlContainer(): HTMLElement;

/**
* Get interactor object
*/
getInteractor(): vtkRenderWindowInteractor;

/**
* Get Render windows object
*/
getRenderWindow(): vtkRenderWindow;

/**
* Get Renderer object
*/
getRenderer(): vtkRenderer;

/**
* Get root container element
*/
getRootContainer(): HTMLElement;

/**
* Remove controller
*/
removeController(): void;

/**
* Remove representation
* @param representation
*/
removeRepresentation(representation: any): void;

/**
* Handle window resize
*/
resize(): void;

/**
* Set background color
* @param {RGBColor | RGBAColor} background The background color.
*/
setBackground(background: RGBColor | RGBAColor): boolean;

/**
* Hide or show controller
* @param {Boolean} visible
*/
setControllerVisibility(visible: boolean): void;

/**
*
* @param cb
*/
setResizeCallback(cb: any): void;

/**
* Toggle controller visibility
*/
toggleControllerVisibility(): void;
}

/**
* Method used to decorate a given object (publicAPI+model) with vtkFullScreenRenderWindow characteristics.
*
* @param publicAPI object on which methods will be bounds (public)
* @param model object on which data structure will be bounds (protected)
* @param {IFullScreenRenderWindowInitialValues} [initialValues] (default: {})
*/
export function extend(
publicAPI: object,
model: object,
initialValues?: IFullScreenRenderWindowInitialValues
): void;

/**
* Method used to create a new instance of vtkFullScreenRenderWindow
* @param {IFullScreenRenderWindowInitialValues} [initialValues] for pre-setting some of its content
*/
export function newInstance(
initialValues?: IFullScreenRenderWindowInitialValues
): vtkFullScreenRenderWindow;

/**
* vtkFullScreenRenderWindow provides a skeleton for implementing a fullscreen
* render window.
*/
export declare const vtkFullScreenRenderWindow: {
newInstance: typeof newInstance;
extend: typeof extend;
};
export default vtkFullScreenRenderWindow;
index.js
import macro from 'vtk.js/Sources/macros';
import vtkRenderer from 'vtk.js/Sources/Rendering/Core/Renderer';
import vtkRenderWindow from 'vtk.js/Sources/Rendering/Core/RenderWindow';
import vtkRenderWindowInteractor from 'vtk.js/Sources/Rendering/Core/RenderWindowInteractor';
import vtkInteractorStyleTrackballCamera from 'vtk.js/Sources/Interaction/Style/InteractorStyleTrackballCamera';
import vtkURLExtract from 'vtk.js/Sources/Common/Core/URLExtract';

// Load basic classes for vtk() factory
import 'vtk.js/Sources/Common/Core/Points';
import 'vtk.js/Sources/Common/Core/DataArray';
import 'vtk.js/Sources/Common/DataModel/PolyData';
import 'vtk.js/Sources/Rendering/Core/Actor';
import 'vtk.js/Sources/Rendering/Core/Mapper';
import 'vtk.js/Sources/Rendering/Misc/RenderingAPIs';

// Process arguments from URL
const userParams = vtkURLExtract.extractURLParameters();

const STYLE_CONTAINER = {
margin: '0',
padding: '0',
position: 'absolute',
top: '0',
left: '0',
width: '100%',
height: '100%',
overflow: 'hidden',
};

const STYLE_CONTROL_PANEL = {
position: 'absolute',
left: '25px',
top: '25px',
backgroundColor: 'white',
borderRadius: '5px',
listStyle: 'none',
padding: '5px 10px',
margin: '0',
display: 'block',
border: 'solid 1px black',
maxWidth: 'calc(100% - 70px)',
maxHeight: 'calc(100% - 60px)',
overflow: 'auto',
};

function applyStyle(el, style) {
Object.keys(style).forEach((key) => {
el.style[key] = style[key];
});
}

function vtkFullScreenRenderWindow(publicAPI, model) {
model.classHierarchy.push('vtkFullScreenRenderWindow');

const body = document.querySelector('body');

// Full screen DOM handler
if (!model.rootContainer) {
model.rootContainer = body;
}

if (!model.container) {
model.container = document.createElement('div');
applyStyle(model.container, model.containerStyle || STYLE_CONTAINER);
model.rootContainer.appendChild(model.container);
}

// apply 100% to html and body for fullscreen
if (model.rootContainer === body) {
document.documentElement.style.height = '100%';
body.style.height = '100%';
body.style.padding = '0';
body.style.margin = '0';
}

// VTK renderWindow/renderer
model.renderWindow = vtkRenderWindow.newInstance();
model.renderer = vtkRenderer.newInstance();
model.renderWindow.addRenderer(model.renderer);

// apiSpecificRenderWindow
model.apiSpecificRenderWindow = model.renderWindow.newAPISpecificView(
userParams.viewAPI ?? model.defaultViewAPI
);
model.apiSpecificRenderWindow.setContainer(model.container);
model.renderWindow.addView(model.apiSpecificRenderWindow);

// Interactor
model.interactor = vtkRenderWindowInteractor.newInstance();
model.interactor.setInteractorStyle(
vtkInteractorStyleTrackballCamera.newInstance()
);
model.interactor.setView(model.apiSpecificRenderWindow);
model.interactor.initialize();
model.interactor.bindEvents(model.container);

// Expose background
publicAPI.setBackground = model.renderer.setBackground;

publicAPI.removeController = () => {
const el = model.controlContainer;
if (el) {
el.parentNode.removeChild(el);
}
};

publicAPI.setControllerVisibility = (visible) => {
model.controllerVisibility = visible;
if (model.controlContainer) {
if (visible) {
model.controlContainer.style.display = 'block';
} else {
model.controlContainer.style.display = 'none';
}
}
};

publicAPI.toggleControllerVisibility = () => {
publicAPI.setControllerVisibility(!model.controllerVisibility);
};

function handleKeypress(e) {
if (String.fromCharCode(e.charCode) === 'c') {
publicAPI.toggleControllerVisibility();
}
}

publicAPI.addController = (html) => {
model.controlContainer = document.createElement('div');
applyStyle(
model.controlContainer,
model.controlPanelStyle || STYLE_CONTROL_PANEL
);
model.rootContainer.appendChild(model.controlContainer);
model.controlContainer.innerHTML = html;

publicAPI.setControllerVisibility(model.controllerVisibility);

model.rootContainer.addEventListener('keypress', handleKeypress);
};

// Update BG color
publicAPI.setBackground(...model.background);

// Representation API
publicAPI.addRepresentation = (representation) => {
representation.getActors().forEach((actor) => {
model.renderer.addActor(actor);
});
};
publicAPI.removeRepresentation = (representation) => {
representation
.getActors()
.forEach((actor) => model.renderer.removeActor(actor));
};

// Properly release GL context
publicAPI.delete = macro.chain(
publicAPI.setContainer,
model.apiSpecificRenderWindow.delete,
() => {
model.rootContainer?.removeEventListener('keypress', handleKeypress);
window.removeEventListener('resize', publicAPI.resize);
},
publicAPI.delete
);

// Handle window resize
publicAPI.resize = () => {
const dims = model.container.getBoundingClientRect();
const devicePixelRatio = window.devicePixelRatio || 1;
model.apiSpecificRenderWindow.setSize(
Math.floor(dims.width * devicePixelRatio),
Math.floor(dims.height * devicePixelRatio)
);
if (model.resizeCallback) {
model.resizeCallback(dims);
}
model.renderWindow.render();
};

publicAPI.setResizeCallback = (cb) => {
model.resizeCallback = cb;
publicAPI.resize();
};

if (model.listenWindowResize) {
window.addEventListener('resize', publicAPI.resize);
}
publicAPI.resize();
}

// ----------------------------------------------------------------------------
// Object factory
// ----------------------------------------------------------------------------

const DEFAULT_VALUES = {
background: [0.32, 0.34, 0.43],
containerStyle: null,
controlPanelStyle: null,
// defaultViewAPI: undefined,
listenWindowResize: true,
resizeCallback: null,
controllerVisibility: true,
};

// ----------------------------------------------------------------------------

export function extend(publicAPI, model, initialValues = {}) {
Object.assign(model, DEFAULT_VALUES, initialValues);

// Object methods
macro.obj(publicAPI, model);
macro.get(publicAPI, model, [
'renderWindow',
'renderer',
'apiSpecificRenderWindow',
'interactor',
'rootContainer',
'container',
'controlContainer',
]);

// Object specific methods
vtkFullScreenRenderWindow(publicAPI, model);
}

// ----------------------------------------------------------------------------

export const newInstance = macro.newInstance(extend);

// ----------------------------------------------------------------------------

export default { newInstance, extend };