nglviewer / ngl

WebGL protein viewer
http://nglviewer.org/ngl/
MIT License
657 stars 168 forks source link

Saving state and displaying several selected atoms in molecule #1007

Closed hellhorse123 closed 5 months ago

hellhorse123 commented 6 months ago

I continue to transfer ngl functionality to react. I can’t figure out how to show selected atoms on a 3D model. I found this function, but problem with displaying of selected atom is stayed.

    stage.signals.clicked.add((pickingProxy) => {
      if (pickingProxy && (pickingProxy.atom || pickingProxy.bond)) {
        const atom = pickingProxy.atom || pickingProxy.closestBondAtom;
        updateSelectedResnos(atom.resno); // Update selected residues
      }
    });

How can i modifying my current code?

import { useEffect, useRef } from "react";
import * as NGL from "ngl";
// eslint-disable-next-line react/prop-types
const MoleculeViewer = ({ pdbId = "4hhb" }) => {
  const ref = useRef();
  const representation = useRef(null);

  useEffect(() => {
    const stage = new NGL.Stage(ref.current);
    stage
      .loadFile(`rcsb://${pdbId}`)
      .then(function (o) {
        console.log("Loaded object:", o); // For debugging
        const rep = o.addRepresentation("cartoon", {
          defaultRepresentation: true,
        });
        representation.current = rep;
        o.autoView();
      })
      .catch((error) => {
        console.error("Error loading the molecule:", error);
      });

    return () => {
      if (stage) {
        stage.viewer.wrapper.remove(); // div wrapper generated by NGL. Hides the subsequent stages if not removed
        stage.viewer.renderer.forceContextLoss();
        stage.dispose();
      }
    };
  }, [pdbId]);

  const handleChangeColor = () => {
    representation.current?.setParameters({ color: "green" });
  };

  return (
    <div>
      <div ref={ref} style={{ width: "500px", height: "500px" }} />
      <button onClick={handleChangeColor}>Change Color to Green</button>
    </div>
  );
};

export default MoleculeViewer;
ppillot commented 5 months ago

The event listener should be attached to the stage at the place where the stage is declared.

For the rest of the code that you need to add it depends what you want to do. For example, you can bind it to a react state variable (like adding to an array of all the selected atoms) and have a useEffect depend on this list of selected atoms to update a representation selection.

This is not trivial, because there are design issues related to React and functionality from NGL. This takes a long time to explain the details and I'm afraid I cannot do more while also maintaining the NGL library.