ieskudero / three-dxf-viewer

DXF viewer using ThreeJS
https://www.npmjs.com/package/three-dxf-viewer
MIT License
70 stars 24 forks source link

DXFViewer not working in react - Getting JSON error on file load #12

Closed faizan-malik closed 4 months ago

faizan-malik commented 4 months ago

I have react component and getting this error when I choose a file.

Uncaught (in promise) SyntaxError: Unexpected token '<', "<!doctype "... is not valid JSON at JSON.parse (<anonymous>) at Object.onLoad (three-dxf-viewer.js?v=4a151fb9:4303:36) at three-dxf-viewer.js?v=4a151fb9:4141:29

Whereas given is my react component

import { useRef, useEffect, useState } from 'react';
import {
  Scene,
  WebGLRenderer,
  OrthographicCamera,
  Box3,
  MOUSE,
  LinearToneMapping,
  SRGBColorSpace,
  Color,
} from 'three';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';
// @ts-ignore
import { DXFViewer } from 'three-dxf-viewer';

const DxfViewer = ({ url }: { url: string }) => {
  console.log('url', url);
  const canvasRef = useRef(null);
  const [dxfData, setDxfData] = useState(null);
  const [scene] = useState(new Scene());

  useEffect(() => {
    // renderer
    const renderer = new WebGLRenderer({
      canvas: canvasRef?.current || undefined,
    });
    renderer.setSize(window.innerWidth, window.innerHeight);
    renderer.outputColorSpace = SRGBColorSpace;
    renderer.toneMapping = LinearToneMapping;
    renderer.toneMappingExposure = 3;

    // scene
    scene.background = new Color(0x212830);

    // camera
    const size = 10000;
    const aspect = canvasRef.current
      ? canvasRef.current.offsetWidth / canvasRef.current.offsetHeight
      : 0;
    const camera = new OrthographicCamera(
      -size * aspect,
      size * aspect,
      size,
      -size,
      -size / 2,
      size,
    );

    //controls
    const controls = new OrbitControls(camera, renderer.domElement);
    controls.zoomSpeed = 2;
    controls.enableRotate = false;
    controls.mouseButtons = {
      LEFT: MOUSE.PAN,
      MIDDLE: MOUSE.DOLLY,
      RIGHT: MOUSE.PAN,
    };

    // Animation loop
    function animate() {
      requestAnimationFrame(animate);
      controls.update();
      renderer.render(scene, camera);
    }

    function centerCamera() {
      const box = new Box3().setFromObject(scene);

      const bigAxis = box.max.x - box.min.x > box.max.y - box.min.y ? 'x' : 'y';
      const size =
        bigAxis === 'x' ? box.max.x - box.min.x : box.max.y - box.min.y;
      const sizeFrustum =
        bigAxis === 'x'
          ? camera.right - camera.left
          : camera.top - camera.bottom;

      const lateralMargin = 0.9; //percentage of screento leave on the sides. 1 means no margin
      if (size < sizeFrustum) {
        camera.zoom = lateralMargin * (sizeFrustum / size);
        camera.updateProjectionMatrix();
      } else camera.zoom = 1;

      const center = box.min.add(box.max.sub(box.min).divideScalar(2));

      camera.position.set(center.x, center.y, center.z + 100);
      controls.target.set(camera.position.x, camera.position.y, center.z);

      camera.updateProjectionMatrix();
    }

    if (dxfData) centerCamera();
    animate();

    return () => {
      // Cleanup on unmount
      renderer.dispose();
    };
  }, [dxfData]);

  const handleFileChange = async (event) => {
    const file = event.target.files[0];
    // const font = 'fonts/helvetiker_regular.typeface.json'; // Adjust font path if needed

    try {
      const dxf = await new DXFViewer().getFromFile(file);

      // Add the DXF geometry to the scene
      scene.add(dxf);

      setDxfData(dxf);
    } catch (error) {
      console.error('Error loading DXF file:', error);
    }
  };

  return (
    <div>
      <input type="file" id="file" onChange={handleFileChange} />
      <canvas ref={canvasRef} style={{ width: '100%', height: '100%' }} />
    </div>
  );
};

export default DxfViewer;
ieskudero commented 4 months ago

Same error as #8, looks like the FontLoader is getting an Html parsed string, instead of a Json parsed string. Closing the issue since it looks duplicated.