mistic100 / Photo-Sphere-Viewer

A JavaScript library to display 360° sphere panoramas.
https://photo-sphere-viewer.js.org
MIT License
1.89k stars 681 forks source link

Viewer.setPanorama -> Cannot add property transition, object is not extensible #1291

Closed rohitCodeBuddy closed 5 months ago

rohitCodeBuddy commented 5 months ago

Describe the bug

viewer crashes if manually changing scene using viewer ?.setPanorama(IMAGES[nextStep], { zoom: 0, position: { yaw: 1, pitch: 1, }, transition: true, }) .then(() => setStep(nextStep));

Online demo URL

DEMO URL

Photo Sphere Viewer version

5.7.2

Plugins loaded

None

OS & browser

Mac OS, Chrome

Additional context

No response

mistic100 commented 5 months ago

This seems to be a problem with React Photo Sphere. There is a binding to the "src" property here https://github.com/Elius94/react-photo-sphere-viewer/blob/main/src/index.tsx#L484-L488

In your case "setPanorama" is called twice (once by your code and once by the react wrapper). Additionally the react wrapper calls it with the initial "options" which seems frozen (it anyway it should not be the case : "setPanorama" options ara absolutely not related to the global options), so it crash.

I suggest you ask the wrapper author how to disable this binding in order to manually change the scenes.

rohitCodeBuddy commented 5 months ago

Thanks !! for the help 👍

bakermanbrian commented 2 months ago

@rohitCodeBuddy how did you work around this issue on your end?

Elius94 commented 2 months ago

Hi, fixed in release 6.0.0 (react-photo-sphere-viewer)

Edit sleepy-williamson-x7s9nv

mistic100 commented 2 months ago

FYI your sandbox uses version 5.0.2-psv5.7.1 and thus still have the error. Switching to 6.0.0 indeed fix the issue.

However I noticed there a second loader briefly displayed because the component thinks the url changed when calling setStep. PSV core does not check if the panorama is different when calling setPanorama (and it could be a legitimiate usage...).

Elius94 commented 2 months ago

Ops, Thank you for notice me! I've used the old link.

Edit gifted-dewdney-4646l2

This is the real sandbox

Please, remember that you can change panorama source by react prop and also using setPanorama Method. If you bind "src" to a state that changes when you call "setPanorama" it will load the same panorama twice! So, in this particular case, you can follow this pattern:

import { Viewer } from "@photo-sphere-viewer/core";
import * as React from "react";
import { render } from "react-dom";
import { ReactPhotoSphereViewer } from "react-photo-sphere-viewer";

const baseUrl = "https://photo-sphere-viewer-data.netlify.app/assets/";
const IMAGES = {
  a: `${baseUrl}/artist-workshop.jpg`,
  b: `${baseUrl}/sphere.jpg`,
};
const INITIAL_IMG = Object.keys(IMAGES)[0];

import "./styles.css";

function App() {
  const [step, setStep] = React.useState(INITIAL_IMG);
  const [viewer, setViewer] = React.useState<Viewer | undefined>();

  React.useEffect(() => {
    if (viewer) {
      // When step changes, you call "setPanorama()"
      viewer?.setPanorama(IMAGES[step], {
        zoom: 0,
        position: {
          yaw: 1,
          pitch: 1,
        },
        transition: true,
      });
    }
  }, [viewer, step]);

  const toggle = () => {
    const nextStep = step === "a" ? "b" : "a";
    console.log(nextStep, IMAGES[nextStep]);
    setStep(nextStep); // you change the step on the state
  };

  return (
    <div className="App">
      <button onClick={toggle} className="btn">
        change scene
      </button>
      <ReactPhotoSphereViewer
        src={IMAGES[INITIAL_IMG]} // src is binded to a constant that can't change
        defaultYaw={0}
        defaultPitch={0}
        defaultZoomLvl={0}
        height={"100vh"}
        width={"100%"}
        onReady={setViewer}
      ></ReactPhotoSphereViewer>
    </div>
  );
}

const rootElement = document.getElementById("root");
render(<App />, rootElement);