[OHIF-Viewers]医疗数字阅片-医学影像-ViewportDownloadForm.js

ViewportDownloadForm.js

源码还是得一行一行阅读,好多自定义的函数,得找到相应的用法

import React, {
  useRef,
  useCallback,
  useEffect,
  useState,
  createRef,
} from 'react';
import PropTypes from 'prop-types';
import { useTranslation } from 'react-i18next';

import './ViewportDownloadForm.styl';
import { TextInput, Select, Icon } from '@ohif/ui';
import classnames from 'classnames';

const FILE_TYPE_OPTIONS = [
  {
    key: 'jpg',
    value: 'jpg',
  },
  {
    key: 'png',
    value: 'png',
  },
];

const DEFAULT_FILENAME = 'image';
const REFRESH_VIEWPORT_TIMEOUT = 1000;

const ViewportDownloadForm = ({
  activeViewport,
  onClose,
  updateViewportPreview,
  enableViewport,
  disableViewport,
  toggleAnnotations,
  loadImage,
  downloadBlob,
  defaultSize,
  minimumSize,
  maximumSize,
  canvasClass,
}) => {
  const [t] = useTranslation('ViewportDownloadForm');

  const [filename, setFilename] = useState(DEFAULT_FILENAME); //文件名字,初始值image
  const [fileType, setFileType] = useState('jpg'); // 文件类型

  const [dimensions, setDimensions] = useState({ // 尺寸
    width: defaultSize,
    height: defaultSize,
  });

  const [showAnnotations, setShowAnnotations] = useState(true); //是否显示注释

  const [keepAspect, setKeepAspect] = useState(true); // 是否保持比例
  const [aspectMultiplier, setAspectMultiplier] = useState({ // 比例尺寸
    width: 1,
    height: 1,
  });

  const [viewportElement, setViewportElement] = useState(); // 视图元素
  const [viewportElementDimensions, setViewportElementDimensions] = useState({ //视口元素尺寸
    width: defaultSize,
    height: defaultSize,
  });

  const [downloadCanvas, setDownloadCanvas] = useState({ //下载画布
    ref: createRef(), //DOM关于回调 refs
    // ref: null, //DOM关于回调 refs
    width: defaultSize,
    height: defaultSize,

  });
console.log(downloadCanvas.ref);
  const [viewportPreview, setViewportPreview] = useState({ //视图预览
    src: null,
    width: defaultSize,
    height: defaultSize,
  });

  const [error, setError] = useState({ // 错误信息
    width: false,
    height: false,
    filename: false, //文件名
  });

  const hasError = Object.values(error).includes(true); //有错误,判断error里面是否包含true

  /**
   * useRef 返回一个可变的 ref 对象,其 .current 属性被初始化为传入的参数(initialValue)。返回的 ref 对象在组件的整个生命周期内保持不变。
   * @type {React.MutableRefObject}
   */
  const refreshViewport = useRef(null); //刷新视图

  const downloadImage = () => { //下载图片
    downloadBlob(
      filename || DEFAULT_FILENAME,
      fileType,
      viewportElement,
      downloadCanvas.ref.current
    );
  };

  /**
   * @param {object} event - Input change event
   * @param {object}事件-输入更改事件
   * @param {string} dimension - "height" | "width"
   * @param {string}尺寸-“高度” | “宽度”
   */
  // 关于尺寸变化
  const onDimensionsChange = (event, dimension) => {
    const oppositeDimension = dimension === 'height' ? 'width' : 'height';
    const sanitizedTargetValue = event.target.value.replace(/\D/, '');
    const isEmpty = sanitizedTargetValue === ''; //是否为空
    const newDimensions = { ...dimensions };
    const updatedDimension = isEmpty
      ? ''
      : Math.min(sanitizedTargetValue, maximumSize);

    if (updatedDimension === dimensions[dimension]) {
      return;
    }

    newDimensions[dimension] = updatedDimension;

    if (keepAspect && newDimensions[oppositeDimension] !== '') {
      newDimensions[oppositeDimension] = Math.round(
        newDimensions[dimension] * aspectMultiplier[oppositeDimension]
      );
    }

    // In current code, keepAspect is always `true` 在当前代码中,keepAspect始终为true。
    // And we always start w/ a square width/height 我们总是以/一个正方形的宽度/高度开始
    setDimensions(newDimensions); //设定尺寸

    // Only update if value is non-empty //仅在值非空时更新
    if (!isEmpty) {
      setViewportElementDimensions(newDimensions); //设置视口元素尺寸
      setDownloadCanvas(state => ({ //设置下载画布
        ...state,
        ...newDimensions, //新尺寸
      }));
    }
  };

  const error_messages = { // 错误信息
    width: t('minWidthError'),
    height: t('minHeightError'),
    filename: t('emptyFilenameError'),
  };

  const renderErrorHandler = errorType => { // 渲染错误处理程序
    if (!error[errorType]) {
      return null;
    }

    return 
"input-error">{error_messages[errorType]}
; }; const onKeepAspectToggle = () => { //保持纵横切换 const { width, height } = dimensions; const aspectMultiplier = { ...aspectMultiplier }; if (!keepAspect) { const base = Math.min(width, height); aspectMultiplier.width = width / base; aspectMultiplier.height = height / base; setAspectMultiplier(aspectMultiplier); } setKeepAspect(!keepAspect); }; const validSize = value => (value >= minimumSize ? value : minimumSize); // 有效尺寸 const loadAndUpdateViewports = useCallback(async () => { // 加载并更新视口 const { width: scaledWidth, height: scaledHeight } = await loadImage( //载入图片 activeViewport, // 活动视口 viewportElement, // 视口元素 dimensions.width, dimensions.height ); toggleAnnotations(showAnnotations, viewportElement); // 是否显示注释,切换注释 const scaledDimensions = { //比例尺 height: validSize(scaledHeight), //校验是否为有效尺寸 width: validSize(scaledWidth),//校验是否为有效尺寸 }; setViewportElementDimensions(scaledDimensions); // 设置视口元素尺寸 setDownloadCanvas(state => ({ //设置下载画布 ...state, ...scaledDimensions, })); const { dataUrl, //数据地址 width: viewportElementWidth, //视口元素宽度 height: viewportElementHeight, } = await updateViewportPreview( //更新视口预览 viewportElement, //视口元素 downloadCanvas.ref.current, //下载画布,访问 Refs fileType //文件类型 ); setViewportPreview(state => ({ // 设置视口预览 ...state, src: dataUrl, width: validSize(viewportElementWidth), //验证宽度是否有效 height: validSize(viewportElementHeight), })); }, [ //inputs 变化检测 activeViewport,//活动视图 viewportElement,//视口元素 showAnnotations,//显示注释 loadImage,//加载图片 toggleAnnotations,//切换注释 updateViewportPreview,//更新视口预览 fileType,//文件类型 downloadCanvas.ref,//下载画布资源,Ref minimumSize,//最小尺寸 maximumSize,//最大尺寸 viewportElementDimensions,//视口元素尺寸 ]); /** * 通过使用这个 Hook,你可以告诉 React 组件需要在渲染后执行某些操作。React 会保存你传递的函数(我们将它称之为 “effect”),并且在执行 DOM 更新之后调用它。在这个 effect 中,我们设置了 document 的 title 属性,不过我们也可以执行数据获取或调用其他命令式的 API。 */ useEffect(() => { enableViewport(viewportElement);//启用视口 return () => { disableViewport(viewportElement);//禁用视口 useEffect 可以在组件渲染后实现各种不同的副作用。有些副作用可能需要清除,所以需要返回一个函数: }; }, [disableViewport, enableViewport, viewportElement]);//这里是检测 useEffect(() => { if (refreshViewport.current !== null) { clearTimeout(refreshViewport.current); } refreshViewport.current = setTimeout(() => { refreshViewport.current = null; loadAndUpdateViewports(); }, REFRESH_VIEWPORT_TIMEOUT);//刷新视口超时时间 }, [ //检测 activeViewport, viewportElement, showAnnotations, dimensions, loadImage, toggleAnnotations, updateViewportPreview, fileType, downloadCanvas.ref, minimumSize, maximumSize, ]); useEffect(() => { //Effect Hook 可以让你在函数组件中执行副作用操作 const { width, height } = dimensions; // 尺寸 const hasError = { //错误信息 width: width < minimumSize, //小于最小尺寸 height: height < minimumSize, filename: !filename, }; setError({ ...hasError });//设置错误信息 对象的扩展运算符(...)用于取出参数对象的所有可遍历属性,拷贝到当前对象之中。 }, [dimensions, filename, minimumSize]); return ( console.log(viewportPreview.src), console.log(viewportElement), // console.log(activeViewport), // console.log(downloadCanvas.ref),
"ViewportDownloadForm" > <div style={{ height: viewportElementDimensions.height, width: viewportElementDimensions.width, position: 'absolute', left: '9999px', }} ref={ref => setViewportElement(ref)} > <canvas className={canvasClass} //cornerstone-canvas style={{ height: downloadCanvas.height, width: downloadCanvas.width, display: 'block', }} width={downloadCanvas.width} height={downloadCanvas.height} ref={downloadCanvas.ref} >
{viewportPreview.src ? (
"preview" data-cy="image-preview">
"preview-header"> {t('imagePreview')}
<img className="viewport-preview" src={viewportPreview.src} alt={t('imagePreview')} data-cy="image-preview" data-cy="viewport-preview-img" />
) : (
"loading-image"> "circle-notch" className="icon-spin" /> {t('loadingPreview')}
)}
"actions">
"action-save"> <button disabled={hasError} onClick={downloadImage} className="btn btn-primary" data-cy="download-btn" > {t('Buttons:Download')}
); }; ViewportDownloadForm.propTypes = { onClose: PropTypes.func.isRequired, activeViewport: PropTypes.object, updateViewportPreview: PropTypes.func.isRequired, enableViewport: PropTypes.func.isRequired, disableViewport: PropTypes.func.isRequired, toggleAnnotations: PropTypes.func.isRequired, loadImage: PropTypes.func.isRequired, downloadBlob: PropTypes.func.isRequired, /** A default width & height, between the minimum and maximum size */ defaultSize: PropTypes.number.isRequired, minimumSize: PropTypes.number.isRequired, maximumSize: PropTypes.number.isRequired, canvasClass: PropTypes.string.isRequired, }; export default ViewportDownloadForm;

 

 

你可能感兴趣的:([OHIF-Viewers]医疗数字阅片-医学影像-ViewportDownloadForm.js)