Unable to render using Ivisual interface

I am currently trying to use Three.js to visualise meshes in microsoft Power BI. The PowerBI template uses an interface called IVisual, I have as yet been unable to make three.js objects appear within the PowerBI window though. Code is below, any help would be much appreciated
code:

"use strict";

import "core-js/stable";

import "./../style/visual.less";

import powerbi from "powerbi-visuals-api";

import VisualConstructorOptions = powerbi.extensibility.visual.VisualConstructorOptions;

import VisualUpdateOptions = powerbi.extensibility.visual.VisualUpdateOptions;

import IVisual = powerbi.extensibility.visual.IVisual;

import EnumerateVisualObjectInstancesOptions = powerbi.EnumerateVisualObjectInstancesOptions;

import VisualObjectInstance = powerbi.VisualObjectInstance;

import DataView = powerbi.DataView;

import VisualObjectInstanceEnumerationObject = powerbi.VisualObjectInstanceEnumerationObject;

import * as THREE from 'three'

import { VisualSettings } from "./settings";

export class Visual implements IVisual {

    private target: HTMLElement;

    private updateCount: number;

    private settings: VisualSettings;

    private textNode: Text;

    private camera: THREE.PerspectiveCamera;

    private renderer: THREE.WebGLRenderer;

    private geometry: THREE.PolyhedronGeometry;

    private materials: THREE.MeshStandardMaterial;

    private mesh: THREE.Mesh;

    private light: THREE.PointLight;

    constructor(options: VisualConstructorOptions) {

        let scene = new THREE.Scene();

        console.log('Visual constructor', options);

        this.target = options.element;

        this.updateCount = 0;

        if (document) {

            const new_p: HTMLElement = document.createElement("p");

            new_p.appendChild(document.createTextNode("Updates: "));

            const new_em: HTMLElement = document.createElement("em");

            this.textNode = document.createTextNode(this.updateCount.toString());

            const new_m: HTMLElement = document.createElement("M");

            

            new_em.appendChild(this.textNode);

            new_p.appendChild(new_em);

            this.target.appendChild(new_p);

            this.camera = new THREE.PerspectiveCamera(100,window.innerWidth/window.innerHeight,0.1,1000);

            this.camera.position.z=5;

            

            this.renderer = new THREE.WebGLRenderer();

            this.renderer.setSize(window.innerWidth,window.innerHeight);

            this.renderer.setClearColor('#D13D1D'); 

            

            window.addEventListener('resize',()=>{

              this.renderer.setSize(window.innerWidth,window.innerHeight);

              this.camera.aspect = window.innerWidth/window.innerHeight;

              this.camera.updateProjectMatrix();

            })

            this.geometry = new THREE.SphereGeometry(1.5,10,10);         

         

            this.materials = new THREE.MeshStandardMaterial({color: 0xFFFFFF})

                        

            this.mesh = new THREE.Mesh(this.geometry,this.materials);

            this.mesh.material.color.set("green");

         

            this.light = new THREE.PointLight(0xFFFFFF,1,500);

            this.light.position.set(10,0,40);

         

            scene.add(this.light);

            

            scene.add(this.mesh);

            document.appendChild(new_m);

            this.renderer.render(scene,this.camera);

            this.target.append(this.renderer);

         

        }

    }

    public update(options: VisualUpdateOptions) {

       this.settings = Visual.parseSettings(options && options.dataViews && options.dataViews[0]);

        console.log('Visual update', options);

        if (this.textNode) {

       this.textNode.textContent = (this.updateCount++).toString();

                        }

        }

    private static parseSettings(dataView: DataView): VisualSettings {

        return <VisualSettings>VisualSettings.parse(dataView);

    }

    /**

     * This function gets called for each of the objects defined in the capabilities files and allows you to select which of the

     * objects and properties you want to expose to the users in the property pane.

     *

     */

    public enumerateObjectInstances(options: EnumerateVisualObjectInstancesOptions): VisualObjectInstance[] | VisualObjectInstanceEnumerationObject {

        return VisualSettings.enumerateObjectInstances(this.settings || VisualSettings.getDefault(), options);

    }

}

This line looks wrong. It should be:

this.target.append(this.renderer.domElement);

Also using appendChild() seems more robust to me.

Ok have changed the method and cleaned up the code. Still don’t get the three mesh coming through but if it does seem to come up with a blank page as opposed to the textnode elements. Not sure if this means that it is creating a blank canvas over the top of the textnodes or just not rendering the canvas at all.
code:

“use strict”;

import “core-js/stable”;

import “./…/style/visual.less”;

import powerbi from “powerbi-visuals-api”;

import VisualConstructorOptions = powerbi.extensibility.visual.VisualConstructorOptions;

import VisualUpdateOptions = powerbi.extensibility.visual.VisualUpdateOptions;

import IVisual = powerbi.extensibility.visual.IVisual;

import EnumerateVisualObjectInstancesOptions = powerbi.EnumerateVisualObjectInstancesOptions;

import VisualObjectInstance = powerbi.VisualObjectInstance;

import DataView = powerbi.DataView;

import VisualObjectInstanceEnumerationObject = powerbi.VisualObjectInstanceEnumerationObject;

import * as THREE from ‘three’

import { VisualSettings } from “./settings”;

export class Visual implements IVisual {

private target: HTMLElement;

private updateCount: number;

private settings: VisualSettings;

private textNode: Text;

private scene: THREE.Scene;

private camera: THREE.PerspectiveCamera;

private renderer: THREE.WebGLRenderer;

private geometry: THREE.BoxGeometry;

private materials: THREE.MeshBasicMaterial;

private mesh: THREE.Mesh;

constructor(options: VisualConstructorOptions) {

    console.log('Visual constructor', options);

    this.target = options.element;

    this.updateCount = 0;

    this.scene = new THREE.Scene();

    this.camera = new THREE.PerspectiveCamera(100,200,0.1,1000);

    this.renderer = new THREE.WebGLRenderer();

    this.renderer.setSize(window.innerWidth,window.innerHeight);

       

    if (document) {

        this.target.appendChild(this.renderer.domElement)

        const new_p: HTMLElement = document.createElement("p");

        new_p.appendChild(document.createTextNode("Update counting:"));

        const new_em: HTMLElement = document.createElement("em");

        this.textNode = document.createTextNode(this.updateCount.toString());

        new_em.appendChild(this.textNode);

        new_p.appendChild(new_em);

        this.target.appendChild(new_p); 

        

        this.geometry = new THREE.BoxGeometry(1,1,1);

        this.materials = new THREE.MeshBasicMaterial({color: 0x00ff00});

        this.mesh = new THREE.Mesh(this.geometry, this.materials);

        this.scene.add(this.mesh);

        this.camera.position.z=5;

    }

}

public update(options: VisualUpdateOptions) {

    this.settings = Visual.parseSettings(options && options.dataViews && options.dataViews[0]);

    console.log('Visual update', options);

    if (this.textNode) {

        this.textNode.textContent = (this.updateCount++).toString();

    }

}

private static parseSettings(dataView: DataView): VisualSettings {

    return <VisualSettings>VisualSettings.parse(dataView);

}

/**

 * This function gets called for each of the objects defined in the capabilities files and allows you to select which of the

 * objects and properties you want to expose to the users in the property pane.

 *

 */

public enumerateObjectInstances(options: EnumerateVisualObjectInstancesOptions): VisualObjectInstance[] | VisualObjectInstanceEnumerationObject {

    return VisualSettings.enumerateObjectInstances(this.settings || VisualSettings.getDefault(), options);

}

}