Cornerstone Tools in ReactJS - not working on first load bit works afterwards

Viewed 1287

I'm trying to load the latest cornerstone tools in ReactJS, but I can't get it to work. I can load cornerstoneJS, and then display the image, but the will not be activated. I have seen examples working using older versions of cornerstonejs react, here and here, but once updated they stop working too.

Here is my code:

index.js

import React from "react";
import { render } from "react-dom";
import CornerstoneElement from "./cornerstoneElement";

const App = () => (
  <div>
    <h2>Cornerstone React Component Example</h2>
    <CornerstoneElement imageId="https://www.fnordware.com/superpng/pnggrad16rgb.png" />
  </div>
);

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

CornerstoneElement.js

import React from "react";
import * as cornerstone from "cornerstone-core";
import * as cornerstoneMath from "cornerstone-math";
import * as cornerstoneTools from "cornerstone-tools";
import Hammer from "hammerjs";
import * as cornerstoneWebImageLoader from "cornerstone-web-image-loader";
import { withStyles } from "@material-ui/core/styles";
import PropTypes from "prop-types";

const defaultTools = {
  Pan: 2,
  ZoomMouseWheel: 0,
  Wwwc: 1
};

cornerstoneTools.external.cornerstone = cornerstone;
cornerstoneTools.external.cornerstoneMath = cornerstoneMath;
cornerstoneTools.external.Hammer = Hammer;
cornerstoneWebImageLoader.external.cornerstone = cornerstone;

const styles = theme => ({
  root: {
    width: "100%",
    height: "100%",
    color: "black",
    position: "relative"
  },
  bottomLeftStyle: {
    bottom: "0.5rem",
    left: "0.5rem",
    position: "absolute",
    color: "white"
  },
  bottomRightStyle: {
    bottom: "0.5rem",
    right: "0.5rem",
    position: "absolute",
    color: "white"
  }
});

class CornerstoneElement extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      viewport: cornerstone.getDefaultViewport(null, undefined)
    };
    this.toolBox = {};

    this.onImageRendered = this.onImageRendered.bind(this);
    this.onNewImage = this.onNewImage.bind(this);
    this.onWindowResize = this.onWindowResize.bind(this);
  }

  render() {
    const { classes } = this.props;
    return (
      <div
        className={[classes.root, "viewportElement"].join(" ")}
        ref={input => {
          this.element = input;
        }}
      >
        <canvas className="cornerstone-canvas" />
        <div className={classes.bottomLeftStyle}>
          Zoom: {this.state.viewport.scale}
        </div>
        <div className={classes.bottomRightStyle}>
          WW/WC: {this.state.viewport.voi.windowWidth} /{" "}
          {this.state.viewport.voi.windowCenter}
        </div>
      </div>
    );
  }

  onWindowResize() {
    cornerstone.resize(this.element);
  }

  onImageRendered() {
    const viewport = cornerstone.getViewport(this.element);

    this.setState({
      viewport
    });
  }

  onNewImage() {
    const enabledElement = cornerstone.getEnabledElement(this.element);

    this.setState({
      imageId: enabledElement.image.imageId
    });
  }

  componentDidMount() {
    const element = this.element;
    this.loadDefaultCanvas(element);

    this.element.addEventListener(
      "cornerstoneimagerendered",
      this.onImageRendered
    );
    this.element.addEventListener("cornerstonenewimage", this.onNewImage);

    window.addEventListener("resize", this.onWindowResize);
  }

  componentWillUnmount() {
    const element = this.element;
    element.removeEventListener(
      "cornerstoneimagerendered",
      this.onImageRendered
    );

    element.removeEventListener("cornerstonenewimage", this.onNewImage);

    window.removeEventListener("resize", this.onWindowResize);

    cornerstone.disable(element);
  }

  loadDefaultCanvas(element) {
    //enable element
    cornerstone.enable(element);
    this.loadImageToGivenPath().then(() => {
      cornerstoneTools.init();
      console.log(cornerstoneTools);
      this.loadDefaultTools(element);
    });
  }

  async loadImageToGivenPath() {
    let image = await cornerstone.loadAndCacheImage(this.props.imageId);
    return cornerstone.displayImage(this.element, image);
  }

  loadDefaultTools(element) {
    for (const defaultTool of Object.keys(defaultTools)) {
      this.loadCsTool(
        String(defaultTool),
        defaultTools[defaultTool],
        true,
        element
      );
    }
  }

  loadCsTool(toolName, toolMouseMask = 0, activate = false, element) {
    const tool = cornerstoneTools[toolName + "Tool"];
    cornerstoneTools.addToolForElement(element, tool);
    //keep toolbox status
    this.toolBox[toolName + "Tool"] = {
      isEnabled: false
    };
    if (activate) {
      this.activateCsTool(toolName, toolMouseMask, element);
    }
  }

  activateCsTool(toolName, toolMouseMask = 0, element) {
    cornerstoneTools.setToolActiveForElement(element, toolName, {
      mouseButtonMask: toolMouseMask
    });

    this.toolBox[toolName + "Tool"].isEnabled = true;
  }
}

CornerstoneElement.propTypes = {
  classes: PropTypes.object.isRequired
};

export default withStyles(styles)(CornerstoneElement);

However, I just noticed that when I put the code in a fiddle, it works fine after breaking the code at some point, and fixing it immediately. However it does, not work on page load, which is the expected outcome.

The image link is passed as props to the cornerstoneElement. Any help would be greatly appreciated.

UPDATE: fiddle now works with external image, issue persists. There is no error or warning in the console.

1 Answers
Related