aframevr / aframe

:a: Web framework for building virtual reality experiences.
https://aframe.io/
MIT License
16.67k stars 3.97k forks source link

I have to resize the brower to see the embedded aframe #3353

Open Cnsdesign opened 6 years ago

Cnsdesign commented 6 years ago

Description: I have an embedded aframe with a 360 image, and the image only appears when i resize the browser windows. I dont know what could be. Im not a programmer but i know a thing or two. I haven't see this problem in the issues so thats why im writing this. please help me.

dmarcos commented 6 years ago

Can you share a link to your example? What browser / OS?

florentpeyrard commented 6 years ago

Hi, I've encountered a similar behavior when I activate embedded component in my vue/vue-router/quasar/webpack app (a-frame 0.8.0):

florentpeyrard commented 6 years ago

Erratum : "canvas width and height".

florentpeyrard commented 6 years ago

In my case, I finally found out that the problem had something to do with quasar modal : if modal shows up before the scene is initialized, the scene is rendered correctly.

darkl1ght commented 4 years ago

Hi, I am facing similar issue. When I try to load the entity with src attribute of image id populated after being selected by a dropdown, the canvas appears, but the image does not appear. And as soon as you resize the window(hit F11(fullscreen) or F12(open dev tools of chrome)), the image appears. I debugged the HTML code of the page and turns out, the canvas element has height and width as 0.

<canvas class="a-canvas a-grab-cursor" data-aframe-canvas="true" width="0" height="0" style=""></canvas>

and when resized, it becomes this

<canvas class="a-canvas a-grab-cursor" data-aframe-canvas="true" width="300" height="200" style=""></canvas>

I am using angular 10 with AFRAME 1.0.0 .

      <div id="myEmbeddedScene">
        <a-scene id="ascene" background-color="#000000" embedded="true" load-scene>
          <a-assets id="aassets" load-asset>
          </a-assets>
          <!-- <a-sky id="skybox" src=""></a-sky> -->
        </a-scene>
      </div>

CSS

#myEmbeddedScene {
  height: 200px;
  width: 300px;
}

#ascene {
  height: 200px;
  width: 300px;
  display: block !important;
}

#asky {
  display: block !important;
}

I load the asky tag when the image is selected from a dropdown using below code.

 let skyboxEl: HTMLElement;
    @if (!document.getElementById('skybox')) {
      const selectedImageId = this.ddSelectedImageId;
      skyboxEl = document.createElement('a-sky');
      skyboxEl.setAttribute('asky', '');
      skyboxEl.setAttribute('id', 'skybox');
      skyboxEl.setAttribute('src', `#${selectedImageId}`);
      sceneEl.appendChild(skyboxEl);
    } else {
      skyboxEl = document.getElementById('skybox');
      skyboxEl.setAttribute('src', `#${this.ddSelectedImageId}`);
    }

@dmarcos I got reference from this https://stackoverflow.com/questions/49322305/hiding-an-embedded-aframe-scene

Initial snip without selecting the image from dropdown image

snip when image is selected from dropdown, but image is not loaded image

snip when F12 is hit to open dev tools and image is loaded, based on this.resize event(reference from here) image

ThangD commented 3 years ago

@darkl1ght Did you have a solution for this issue?

darkl1ght commented 3 years ago

Hi @ThangD ,

My approach was Angular based.

I created a separate component for loading the a-frame component on the page. And once the dropdown was opened and an item was selected, I would take the id of that item from the dropdown and used a *ngIf to show the component. Also, I passed an image list for all the images that are present in the dropdown so that I can load those images in this aframe-component's assets. I also passed the id of the selected image from the dropdown, so that when the aframe-component loads, it shows the selected image in the aframe-component. main_file.html :

<primary-img-aframe *ngIf="id" [id]="id" [images]="images">
</primary-img-aframe>

images being the array containing all the image ids and the url for those assets.

In the aframe-component:

In the ts file you input those parameters like below

@Component({
  selector: 'primary-img-aframe',
  templateUrl: './primary-img-aframe.component.html',
  styleUrls: ['./primary-img-aframe.component.scss']
})
export class PrimaryImgAframeComponent implements OnInit {
 @Input() id: string;
 @Input() images: any;
  ngOnInit(): void {
  }
  // You have to use ngOnChanges to detect changes
  // because anytime a user selects a different image from the dropdown, that id is sent here and loaded from the assets.
  ngOnChanges() {
    const camera = document.getElementById('camera1');
    camera.setAttribute('position', '0 0 0');
    // This lets you load all the assets in the aframe-component
    const aAssets = document.getElementById('aassets');
    while (aAssets.lastChild) {  // removes all previously attached assets, required to prevent duplicate assets being added
      aAssets.removeChild(aAssets.firstChild);
    }
    for (let image of this.images) { // loads each image's url and id into assets
      const img = document.createElement('img');
      img.setAttribute('id', image.id);
      img.setAttribute('src', image.url);
      img.setAttribute('crossorigin','anonymous'); // this is mandatory otherwise it gives error
      aAssets.appendChild(img);
    }
  }
}

my html file:

<div id="myEmbeddedScene">
  <a-scene id="ascene" background-color="#ECECEC" embedded>
    <a-assets id="aassets">
    </a-assets>
    <a-camera id="camera1" rotation="0 0 0">
    </a-camera>
    <a-sky id="skybox" [attr.src]="id"></a-sky>
  </a-scene>
</div>

my css(scss) file:

#myEmbeddedScene {
  height: 350px;
  width: 500px;
}

.a-canvas {
  width: 500px !important;
  height: 350px !important;
}

I hope this helps.