【问题标题】:Typescript cannot access objects properties even though they are thereTypescript 无法访问对象属性,即使它们存在
【发布时间】:2018-01-24 00:01:47
【问题描述】:

我在访问属性时遇到了麻烦,即使它们存在于对象中,但 typescript 告诉我它们不存在。我创建了一个粒子对象,其中包含形状的几何形状和一种材质。我需要能够访问粒子的几何顶点,但是当我尝试时打字稿会抛出一个合适的。例如,this.particles.geometry.vertices.length 应该返回我的顶点的长度,但 typescript 说顶点在实际存在的几何中并不存在。

我的问题是在加载图像、创建顶点之后出现的,然后我需要将它们移动到目标索引,但它说 this.particles.geometry.vertices 不存在。

这是我的粒子对象,其中包含几何,几何内部是一个属性,它是包含我所有顶点的顶点,但我无法按照我显示的方式访问它们。

这是我的完整源代码。 drawImage 方法将正确绘制所有顶点,并将顶点对象推入我的几何对象中。然后一旦完成,我将几何图形添加到粒子中,它工作得很好,我将它添加到场景中并显示我的所有顶点。问题是我无法访问我的顶点来操作它们。所以我的粒子对象、drawImage 和包含我的 for 循环的渲染方法就是所有这些发生的地方。在我的渲染方法中,它只是说(TS)属性“顶点”不存在于类型“几何 |缓冲几何'。它确实存在,我用图像表明我的粒子对象是一个点对象,它包含我的几何图形,并且几何图形内部有一个属性,它包含我所有的顶点,称为顶点。

import { Component, AfterViewInit, ElementRef, Input, ViewChild, HostListener} from '@angular/core';
import { TweenLite } from 'gsap';
import * as THREE from 'three';
declare const require: (moduleId: string) => any;
var OrbitControls = require('three-orbit-controls')(THREE);

@Component({
    selector: 'shared-background-scene',
    templateUrl: './backgroundScene.component.html',
    styleUrls: ['./backgroundScene.component.scss']
})

export class BackgroundSceneComponent {

    public scene: THREE.Scene;
    private renderer: THREE.WebGLRenderer;
    private camera: THREE.PerspectiveCamera;
    private cameraTarget: THREE.Vector3;
    public controls: THREE.OrbitControls;

    public fieldOfView: number = 60;
    public nearClippingPane: number = 1;
    public farClippingPane: number = 1100;

    @ViewChild('canvas')
    private canvasRef: ElementRef;

    public particles: THREE.Points;
    public imageData: any;
    public geometry = new THREE.Geometry();
    public material = new THREE.PointsMaterial({
                size: 3,
                color: 0x313742,
                sizeAttenuation: false
    });
    public loadImage() {
        //load texture, which is the image, and then get the imagedata, and draw image.
        var texture = new THREE.TextureLoader().load("assets/img/example-clouds.png", () => { console.log(texture); this.imageData = this.getImageData(texture.image); this.drawImage(); this.startRendering(); })
    }

    public getImageData(image: any) {
        console.log(image);
        // Create canvas for the image
        let canvas = document.createElement("canvas");
        canvas.width = image.width;
        canvas.height = image.width;

        // Make sure context is 2d
        let context = canvas.getContext("2d");
        context!.drawImage(image, 0, 0);

        //return the context to be saved to the imageData.
        return context!.getImageData(0, 0, image.width, image.height);
    }

    public drawImage() {

        // Create vertices to draw the image.
        for (var y = 0, y2 = this.imageData.height; y < y2; y += 2) {
            for (var x = 0, x2 = this.imageData.width; x < x2; x += 2) {
                if (this.imageData.data[(x * 4 + y * 4 * this.imageData.width) + 3] > 128) {

                    let vertex:any = new THREE.Vector3();
                    vertex.x = Math.random() * 1000 - 500;
                    vertex.y = Math.random() * 1000 - 500;
                    vertex.z = -Math.random() * 500;

                    vertex.destination = {
                        x: x - this.imageData.width / 2,
                        y: -y + this.imageData.height / 2,
                        z: 0
                    };

                    vertex.speed = Math.random() / 200 + 0.015;

                    this.geometry.vertices.push(vertex);
                }
            }
        }

        console.log(this.geometry);
        this.particles = new THREE.Points(this.geometry, this.material);
        this.scene.add(this.particles);
        console.log(this.particles);
        requestAnimationFrame(this.render);
    }

    constructor() {
        this.render = this.render.bind(this);
    }

    private get canvas(): HTMLCanvasElement {
        return this.canvasRef.nativeElement;
    }

    private createScene() {
        this.scene = new THREE.Scene();
    }

    private createCamera() {
        let aspectRatio = this.getAspectRatio();
        this.camera = new THREE.PerspectiveCamera(
            this.fieldOfView,
            aspectRatio,
            this.nearClippingPane,
            this.farClippingPane
        );

        // Set position and look at
        this.camera.position.x = 10;
        this.camera.position.y = 10;
        this.camera.position.z = 100;
    }

    private getAspectRatio(): number {
        let height = this.canvas.clientHeight;
        if (height === 0) {
            return 0;
        }
        return this.canvas.clientWidth / this.canvas.clientHeight;
    }

    private startRendering() {
        this.renderer = new THREE.WebGLRenderer({
            canvas: this.canvas,
            antialias: true
        });
        this.renderer.setPixelRatio(devicePixelRatio);
        this.renderer.setSize(this.canvas.clientWidth, this.canvas.clientHeight);

        this.renderer.shadowMap.enabled = true;
        this.renderer.shadowMap.type = THREE.PCFSoftShadowMap;
        this.renderer.setClearColor(0xffffff, 1);
        this.renderer.autoClear = true;

        let component: BackgroundSceneComponent = this;

        (function render() {
            requestAnimationFrame(render);
            component.render();
        }());
    }

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

        for (var i = 0, j = this.particles.geometry.vertices; i < j; i++) {
            var particle = this.particles.geometry.vertices[i];
            particle.x += (particle.destination.x - particle.x) * particle.speed;
            particle.y += (particle.destination.y - particle.y) * particle.speed;
            particle.z += (particle.destination.z - particle.z) * particle.speed;
        }
        this.particles.geometry.verticesneedupdate = true;
    }

    public addControls() {
        this.controls = new OrbitControls(this.camera);
        this.controls.rotateSpeed = 1.0;
        this.controls.zoomSpeed = 1.2;
        this.controls.addEventListener('change', this.render);

    }

    private loadCubeModel() {
        var geometry = new THREE.BoxGeometry(1, 1, 1);
        var material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
        var cube = new THREE.Mesh(geometry, material);
        this.scene.add(cube);
    }

    /* Events */
   private onResize(event: Event) {
        this.canvas.style.width = "100%";
        this.canvas.style.height = "100vh";
        //console.log("onResize: " + this.canvas.clientWidth + ", " + this.canvas.clientHeight);

        this.camera.aspect = this.getAspectRatio();
        this.camera.updateProjectionMatrix();
        this.renderer.setSize(this.canvas.clientWidth, this.canvas.clientHeight);
        this.render();
    }

    /* LIFECYCLE */
   ngAfterViewInit() {
        this.createScene();
        this.createCamera();
        this.loadImage(); // rendering starts here
        this.loadCubeModel();
        this.addControls();
    }
}

我使用 console.log(this.particles.geometry.vertices.length); 的快速示例并获得正确的输出,但它仍然说它不存在。

【问题讨论】:

  • 您能否在每个执行的方法中添加一个 console.log(yourmethodname) 并跟踪执行顺序,我认为执行顺序不好,您的代码很大,很难像那...
  • 我修复了它,但我只是遇到了问题,说当一切正常执行时出现错误。

标签: javascript typescript properties


【解决方案1】:

原因是,当我们使用THREE.Points 时,TypeScript 无法知道我们是否将它们与GeometryBufferGeometry 一起使用。我只是在你的 render() 方法中添加这一行:

const geometry = this.particles.geometry as Geometry

并在以下代码中使用geometry 而不是this.particles.geometry。这基本上会告诉 TypeScript“我知道,它永远是 Geometry,相信我”。

【讨论】:

    【解决方案2】:

    我改变了我的公共粒子 = THREE.Points; -> 公共粒子:any = THREE.Points;

    这为我修复了它,但我没有类型,这很糟糕,但如果你知道你在改变什么,那么你应该没问题。

    固定代码:

    import { Component, AfterViewInit, ElementRef, Input, ViewChild, HostListener} from '@angular/core';
    import { TweenLite } from 'gsap';
    import * as THREE from 'three';
    declare const require: (moduleId: string) => any;
    var OrbitControls = require('three-orbit-controls')(THREE);
    
    @Component({
        selector: 'shared-background-scene',
        templateUrl: './backgroundScene.component.html',
        styleUrls: ['./backgroundScene.component.scss']
    })
    
    export class BackgroundSceneComponent {
    
        public scene: THREE.Scene;
        private renderer: THREE.WebGLRenderer;
        private camera: THREE.PerspectiveCamera;
        private cameraTarget: THREE.Vector3;
        public controls: THREE.OrbitControls;
    
        public fieldOfView: number = 60;
        public nearClippingPane: number = 1;
        public farClippingPane: number = 1100;
    
        @ViewChild('canvas')
        private canvasRef: ElementRef;
    
        public particles:any = THREE.Points;
        public imageData: any;
        public geometry = new THREE.Geometry();
        public material = new THREE.PointsMaterial({
                    size: 3,
                    color: 0x313742,
                    sizeAttenuation: false
        });
        public loadImage() {
            //load texture, which is the image, and then get the imagedata, and draw image.
            var texture = new THREE.TextureLoader().load("assets/img/transparentMap.png", () => { console.log(texture); this.imageData = this.getImageData(texture.image); this.drawImage(); this.startRendering(); })
        }
    
        public getImageData(image: any) {
            console.log(image);
            // Create canvas for the image
            let canvas = document.createElement("canvas");
            canvas.width = image.width;
            canvas.height = image.width;
    
            // Make sure context is 2d
            let context = canvas.getContext("2d");
            context!.drawImage(image, 0, 0);
    
            //return the context to be saved to the imageData.
            return context!.getImageData(0, 0, image.width, image.height);
        }
    
        public drawImage() {
    
            // Create vertices to draw the image.
            for (var y = 0, y2 = this.imageData.height; y < y2; y += 2) {
                for (var x = 0, x2 = this.imageData.width; x < x2; x += 2) {
                    if (this.imageData.data[(x * 4 + y * 4 * this.imageData.width) + 3] > 128) {
    
                        let vertex:any = new THREE.Vector3();
                        vertex.x = Math.random() * 1000 - 500;
                        vertex.y = Math.random() * 1000 - 500;
                        vertex.z = -Math.random() * 500;
    
                        vertex.destination = {
                            x: x - this.imageData.width / 2,
                            y: -y + this.imageData.height / 2,
                            z: 0
                        };
    
                        vertex.speed = Math.random() / 200 + 0.015;
    
                        this.geometry.vertices.push(vertex);
                    }
                }
            }
            this.particles = new THREE.Points(this.geometry, this.material);
            this.scene.add(this.particles);
    
            requestAnimationFrame(this.render);
        }
    
        constructor() {
            this.render = this.render.bind(this);
        }
    
        private get canvas(): HTMLCanvasElement {
            return this.canvasRef.nativeElement;
        }
    
        private createScene() {
            this.scene = new THREE.Scene();
        }
    
        private createCamera() {
            let aspectRatio = this.getAspectRatio();
            this.camera = new THREE.PerspectiveCamera(
                this.fieldOfView,
                aspectRatio,
                this.nearClippingPane,
                this.farClippingPane
            );
    
            // Set position and look at
            this.camera.position.x = 10;
            this.camera.position.y = 10;
            this.camera.position.z = 100;
        }
    
        private getAspectRatio(): number {
            let height = this.canvas.clientHeight;
            if (height === 0) {
                return 0;
            }
            return this.canvas.clientWidth / this.canvas.clientHeight;
        }
    
        private startRendering() {
            this.renderer = new THREE.WebGLRenderer({
                canvas: this.canvas,
                antialias: true
            });
            this.renderer.setPixelRatio(devicePixelRatio);
            this.renderer.setSize(this.canvas.clientWidth, this.canvas.clientHeight);
    
            this.renderer.shadowMap.enabled = true;
            this.renderer.shadowMap.type = THREE.PCFSoftShadowMap;
            this.renderer.setClearColor(0xffffff, 1);
            this.renderer.autoClear = true;
    
            let component: BackgroundSceneComponent = this;
    
            (function render() {
                requestAnimationFrame(render);
                component.render();
            }());
        }
    
        public render() {
            this.renderer.render(this.scene, this.camera);
    
            // Draw image to screen
            for (var i = 0, j = this.particles.geometry.vertices.length; i < j; i++) {
                var particle:any = this.particles.geometry.vertices[i];
                particle.x += (particle.destination.x - particle.x) * particle.speed;
                particle.y += (particle.destination.y - particle.y) * particle.speed;
                particle.z += (particle.destination.z - particle.z) * particle.speed;
            }
            this.particles.geometry.verticesNeedUpdate = true;
        }
    
        public addControls() {
            this.controls = new OrbitControls(this.camera);
            this.controls.rotateSpeed = 1.0;
            this.controls.zoomSpeed = 1.2;
            this.controls.addEventListener('change', this.render);
    
        }
    
        private loadCubeModel() {
            var geometry = new THREE.BoxGeometry(1, 1, 1);
            var material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
            var cube = new THREE.Mesh(geometry, material);
            this.scene.add(cube);
        }
    
        /* Events */
       private onResize(event: Event) {
            this.canvas.style.width = "100%";
            this.canvas.style.height = "100vh";
            //console.log("onResize: " + this.canvas.clientWidth + ", " + this.canvas.clientHeight);
    
            this.camera.aspect = this.getAspectRatio();
            this.camera.updateProjectionMatrix();
            this.renderer.setSize(this.canvas.clientWidth, this.canvas.clientHeight);
            this.render();
        }
    
        /* LIFECYCLE */
       ngAfterViewInit() {
            this.createScene();
            this.createCamera();
            this.loadImage(); // rendering starts here
            this.loadCubeModel();
            this.addControls();
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-02-05
      • 2013-07-06
      • 1970-01-01
      • 2011-07-05
      相关资源
      最近更新 更多