【问题标题】:fabric.js - React.js - canvas - Printing multiple fabric canvases that contain images (w/ react-to-print)fabric.js - React.js - canvas - 打印多个包含图像的织物画布(w/ react-to-print)
【发布时间】:2022-10-24 18:38:25
【问题描述】:

所以我正在尝试记录打印多个织物图像。以下是准备过程。我看到一个空白窗口。我可以根据要求提供更多信息。我可能错过了某种异步逻辑?

1-我从每个画布对象初始化画布(循环画布数组 - 每个画布对象都有一个图像,可能还有多个文本框对象)

2-然后我使用 toDataURL() 并为每个创建图像元素,将 src 附加到 img

3-我遍历图像并将它们附加到 printWindow。

   const handleCustomPrint = () => {

    const div = document.querySelector('.print-content');

    for (let i = 0; i < canvasArrayToBePrinted.length; i++) {
      const canvas = new fabric.Canvas(`${i}`)
      canvas.loadFromJSON(canvasArrayToBePrinted[i], () => {
        const img = canvas.toDataURL({
          format: 'jpeg',
          quality: 0.75
        });
        const singleImg = `<img src=${img} class='image-content' />`
        div.innerHTML += singleImg;
      });
    }

    console.log(div);

    var windowUrl = 'about:blank';
    var uniqueName = new Date();
    var windowName = 'Print' + uniqueName.getTime();
    var printWindow = window.open(windowUrl, windowName, 'left=50000,top=50000,width=1000000,height=10000');
    printWindow.document.write(div.innerHTML);

    printWindow.document.close();

    printWindow.onload = function() {
      printWindow.focus();
      printWindow.print();
      printWindow.close();
    }
    return true;

  };

编辑:好的。我想我已经接近了。但还是什么都看不到。

这是 console.log(div) 的输出

<div class="print-content">
<img src="data:image/jpeg;base64,/9j/4AAQSkZJ..." class="img-content"/>
<img src="data:image/jpeg;base64,/9j/4AAQSkZJ..." class="img-content"/>
</div>

这是用于定位打印样式的 CSS

@media all {
  .img-content {
    display: none !important;
  }
  .print-content {
    display: none !important;
  }
}
@media print {

  .print-content {
    display: block !important;
  }

  .img-print {
    display: block !important;
  }
}

【问题讨论】:

  • 请问是不是图片的问题。如果您只包含文本框,它是否有效?
  • @JohnM您的意思是省略toDataURL()。并从画布中删除图像对象?
  • 我的意思是从画布上删除任何图像对象
  • @JohnM 我在 react-to-print 的帮助下用不同的方法解决了这个问题(它允许我打印反应组件) - 图像转换结果是无用的。我在画布数组上循环,为循环中的每个数据创建画布,然后触发 document.print

标签: javascript reactjs canvas printing fabricjs


【解决方案1】:

准备画布(loadFromJSON 回调是指示画布是否已初始化并附有其所有对象(图像/文本框)的指示器...)

const PrintContent = React.forwardRef((props, ref) => {

  const { canvasData, setIsPrintReady, shouldExcludeImage } = props;

  const [preparedCanvases, setPreparedCanvases] = React.useState({ prepared: 0, total: canvasData.length });

  const incrementPrepared = () => setPreparedCanvases(prev => ({ ...prev, prepared: prev.prepared + 1 }));

  const imageToBePrinted = canvasData && canvasData.length && canvasData[0].objects.find(o => o.type === 'image');

  const { width, height } = imageToBePrinted;

  React.useEffect(() => {
    if (preparedCanvases.prepared === preparedCanvases.total) {
      setIsPrintReady(true);
    }
  }, [preparedCanvases, setIsPrintReady])

  return (
    <div className="content-to-be-printed" ref={ref}>
      {
        props.canvasData && props.canvasData.length && props.canvasData.map((singleCanvas, idx) => {
          return <SingleCanvasData
            key={`${idx}--canvas`}
            singleCanvas={singleCanvas}
            index={idx}
            incrementPrepared={incrementPrepared}
            imgWidth={width}
            imgHeight={height}
            shouldExcludeImage={shouldExcludeImage}
            />
        })
      }
    </div>
  )
});
const SingleCanvasData = ({ singleCanvas, index, incrementPrepared, imgWidth, imgHeight, shouldExcludeImage }) => {

  const [canvas, setCanvas] = React.useState("");
  const [once, setOnce] = React.useState(true);

  React.useEffect(() => {
    const initCanvas = () =>
      new fabric.Canvas(`${index}`, {
        height: imgHeight,
        width: imgWidth,
        preserveObjectStacking: true
      });
    setCanvas(initCanvas());
  }, [index, imgHeight, imgWidth]);

  React.useEffect(() => {
    if (once && canvas) {

      let canvasWithoutImage;
      if(!shouldExcludeImage) {
        canvasWithoutImage = {...singleCanvas, objects: singleCanvas.objects.filter(o => o.type !== 'image')};
      }

      canvas.loadFromJSON(canvasWithoutImage || singleCanvas, () => {
        incrementPrepared();
      });
      setOnce(false);
    }

  }, [canvas, incrementPrepared, once, singleCanvas, shouldExcludeImage]);

  return (
    <canvas
      style={{ width: 'auto', height: 'auto' }}
      className="single-canvas"
      id={index}
      key={`canvas-${index}`}>

    </canvas>
  )
}

export default PrintContent

家长

      {
        canPrint && (
          <PrintContent
            canvasData={canvasArrayToBePrinted}
            setIsPrintReady={setIsPrintReady}
            ref={componentRef}
            shouldExcludeImage={shouldExcludeImage} />
        )
      }

useReactToPrint 挂钩(将 ref 附加到要打印的组件(在我的情况下是 forwardRef,因为我将 ref 传递给组件)-您还可以通过 props 声明打印样式-超级漂亮),允许您打印反应组件(反应打印)

  const handlePrint = useReactToPrint({
    pageStyle: `
    @page { size: ${pageSize.widthPX}px ${pageSize.heightPX}px; margin: 0mm; }
    `,
    content: () => componentRef.current,
    onAfterPrint: () => handleResetPrintModal()
  });

打印就绪时启用打印按钮

            <button disabled={!isPrintReady || !pageSize.widthPX}
              onClick={handlePrint}
              className='btn-primary btn-success'>
              Print
            </button>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-04-23
    • 2017-02-24
    • 2015-03-14
    • 2019-09-19
    • 2018-12-25
    • 2021-07-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多