Source: export/export_image.js

import { 
    PerspectiveCamera, Scene, WebGLRenderer
} from '../../node_modules/three/build/three.module.js';


import { Reporter } from '../reporter/reporter.js';
import { LoadableComponent } from '../package/component/loadable_component.js';
import { checkPropTypes, UUIDRegex } from '../lib.js';
import { LoadingBase } from '../package/loader/loading_base.js';

import { Export } from './export.js';
import { Composer } from '../scene/composer.js';
import { EffectComposer } from '../../node_modules/three/examples/jsm/postprocessing/EffectComposer.js';

import { View } from '../view/view.js';
import { DefaultView } from '../view/default_view.js';

import html2canvas from '../../node_modules/html2canvas/dist/html2canvas.esm.js';

/** @class
 * 
 */





class ImageExporter { //extends Export {

    constructor(reporter, settings) {

        //super( reporter, settings )
        this.revision = 1;
        //throw new Error( 'Not implemented' );

        checkPropTypes(
            settings,
            {
                view: View || DefaultView,
                //scene: Scene,
                //camera: PerspectiveCamera,
                //renderer: WebGLRenderer,
                //composer: EffectComposer

            },
            {}
        );

        this._view = settings.view
        //this._scene = settings.scene
        //this._camera = settings.camera
        //this._renderer = settings.renderer
        //this._composer = settings.composer

    };

    //DATA TO BLOB
	_dataURIToBlob( dataURI ) {

		const binStr = window.atob( dataURI.split( ',' )[1] );
		const len = binStr.length;
        const arr = new Uint8Array( len );
        
		for ( let i = 0; i < len; i++ ) {
			arr[i] = binStr.charCodeAt( i );
        }
        
        return new window.Blob( [arr] );
        
    };
    
    //SAVE FILE TO DOWNLOADS
    _saveDataURI( name, dataURI ) {

        const blob = this._dataURIToBlob( dataURI );

        // force download
        const link = document.createElement( 'a' );
        link.download = name;
        link.href = window.URL.createObjectURL( blob );
        link.onclick = () => {

            window.setTimeout( () => {
            window.URL.revokeObjectURL( blob );
            link.removeAttribute( 'href' );
            }, 500 );

        };

        link.click();

    };
    
    //FILENAME
	_defaultFileName ( ext ) {

		const str = `${new Date().toLocaleDateString()} at ${new Date().toLocaleTimeString()}${ext}`;
        return str.replace(/\//g, '-').replace(/:/g, '.');
        
	};


    async export( width, height, { saveToFile, transparent, html, extension } = {}){

        //console.log(  saveToFile )

        width = width || 800
        height = height || 600
        extension = extension ?? "png"
        
        
        //set camera to desired screenshot dimension
        this._view.perspectiveCamera.aspect = width / height;
        this._view.perspectiveCamera.updateProjectionMatrix();
        //console.log( camera.aspect )

        // set the renderer alpha en dimensions to desired screenshot dimension
        if( transparent ){
            this._view.renderer.setClearColor( 0xFFFFFF, 0 );  // set the background to transparent 
        }

        await this._view.update()
                         
        this._view.renderer.setSize(  width, height );
        this._view.composer.setSize(  width, height );
        this._view.css2dRenderer.setSize(  width, height );
        this._view.composer.render( this._view.scene, this._view.perspectiveCamera, null, false );
        
        var dataUri = null;

        if( html ){

            console.log( "save html")

            //get the existing dom element
            const domElement = this._view.domElement

            //create div for html2canvas
            const div = document.createElement("div");
            div.style.width = width.toString() + "px";
            div.style.height = height.toString() + "px";
            div.id = 'htmlCanvas';
            div.style.zIndex = "-10"
            div.style.background = "white";
    
            ///this.domElement = div
            //this.domElement.id = 'htmlCanvas';
            div.appendChild(this._view.renderer.domElement);
            div.appendChild(this._view.css2dRenderer.domElement);

            var canvasElement = document.getElementsByClassName("canvas-container")[0];
    
            canvasElement.appendChild(div);

            this._view.renderer.setClearColor( 0xFFFFFF, 1 );

            this._view.composer.render( this._view.scene, this._view.perspectiveCamera, null, false );
            this._view.css2dRenderer.render( this._view.scene, this._view.perspectiveCamera, null, false );


            await html2canvas(document.querySelector("#htmlCanvas")).then( (canvas) => {      //   /(document.body)

                dataUri = canvas.toDataURL( `image/${extension}` );

                //console.log( dataUri)

                // save to file/downloads if saveToFile is set to true
                if( saveToFile ){

                    // save
                    this._saveDataURI( this._defaultFileName( `.${extension}`), dataUri);

                }

            });

            this._view.domElement.appendChild(this._view.renderer.domElement);
            this._view.domElement.appendChild(this._view.css2dRenderer.domElement);

            div.remove();

        }
        else{

            console.log( "save renderer")

            dataUri = this._view.renderer.domElement.toDataURL( `image/${extension}` ); //mimetype

            // save to file/downloads if saveToFile is set to true
            if( saveToFile ){

                // save
                this._saveDataURI( this._defaultFileName( `.${extension}` ), dataUri);

            }

        }

    
        // reset the background color 
        if( transparent ){
            this._view.renderer.setClearColor( 0xFFFFFF, 1 );
        }

        // reset to old dimensions by invoking the on window resize function
        this._view.updateDOMElementDimensions()

        return dataUri

    }

}


export { ImageExporter }