ソースを参照

feat: 添加水印图片

liaojiaxing 6 ヶ月 前
コミット
237ec8cdf1

ファイルの差分が大きいため隠しています
+ 6 - 0
apps/designer/src/assets/watermark/wm1.svg


ファイルの差分が大きいため隠しています
+ 8 - 0
apps/designer/src/assets/watermark/wm2.svg


ファイルの差分が大きいため隠しています
+ 9 - 0
apps/designer/src/assets/watermark/wm3.svg


ファイルの差分が大きいため隠しています
+ 5 - 0
apps/designer/src/assets/watermark/wm4.svg


ファイルの差分が大きいため隠しています
+ 5 - 0
apps/designer/src/assets/watermark/wm5.svg


+ 159 - 69
apps/designer/src/components/ExportImage.tsx

@@ -1,10 +1,20 @@
-import { Graph, Node } from "@antv/x6"
+import { Graph, Node } from "@antv/x6";
 import { Button, Form, Input, Modal, Radio } from "antd";
 import { CheckCard } from "@ant-design/pro-components";
-import insertCss from 'insert-css';
+import insertCss from "insert-css";
 import { useEffect, useRef, useState } from "react";
+import { Export } from "@antv/x6-plugin-export";
+import { Scroller } from "@antv/x6-plugin-scroller";
 
-const ExportComponent = ({graph, getModal, type}: { graph: Graph, getModal?: () => { destroy: () => void}, type?: 'svg' | 'png' | 'jpg'},) => {
+const ExportComponent = ({
+  graph,
+  getModal,
+  type,
+}: {
+  graph: Graph;
+  getModal?: () => { destroy: () => void };
+  type?: "svg" | "png" | "jpg";
+}) => {
   insertCss(`
     .ant-pro-checkcard-content {
       padding-block: 8px;
@@ -14,11 +24,17 @@ const ExportComponent = ({graph, getModal, type}: { graph: Graph, getModal?: ()
   const graphRef = useRef<HTMLDivElement>(null);
   const printGraph = useRef<Graph>();
   const data = graph.toJSON();
-  console.log('graph data', data);
+  data.cells = data.cells.filter((cell) => !cell?.data?.isPage);
+  data.cells.forEach((cell) => {
+    if(cell.data) {
+      cell.data.lock = true;
+    }
+  });
+  console.log("graph data", data);
 
   useEffect(() => {
-    if(!graphRef.current) return;
-    
+    if (!graphRef.current) return;
+
     printGraph.current = new Graph({
       container: graphRef.current,
       autoResize: true,
@@ -42,95 +58,169 @@ const ExportComponent = ({graph, getModal, type}: { graph: Graph, getModal?: ()
         stopDelegateOnDragging: true,
         toolsAddable: false,
       },
-    });
+    })
+    .use(new Export())
+    .use(new Scroller({
+      enabled: true,
+      pannable: true,
+      autoResize: true,
+    }));
     printGraph.current.fromJSON(data);
+    printGraph.current.centerContent();
   }, []);
 
   const [formModel, setFormModel] = useState({
-    type: type || 'png',
+    type: type || "png",
     quality: 1,
     watermark: "严禁复制",
-    watermarkStyle: 1
+    watermarkStyle: 1,
   });
 
   const handleExport = () => {
-    switch(formModel.type) {
-      case 'png':
-        graph.exportPNG('', {
-          quality: formModel.quality === 1 ? 1 : 0.6
+    switch (formModel.type) {
+      case "png":
+        printGraph.current?.exportPNG("", {
+          quality: formModel.quality === 1 ? 1 : 0.6,
+          // copyStyles: false,
         });
         break;
-      case 'jpg': 
-        graph.exportJPEG('', {
-          quality: formModel.quality === 1 ? 1 : 0.6
+      case "jpg":
+        printGraph.current?.exportJPEG("", {
+          quality: formModel.quality === 1 ? 1 : 0.6,
+          // copyStyles: false,
         });
         break;
-      default: 
-        graph.exportSVG('', {
-
+      default:
+        printGraph.current?.exportSVG("", {
+          // copyStyles: false,
         });
     }
-  }
+  };
 
   const handleSetFormValue = (key: string, value: any) => {
-    setFormModel(state => ({...state, [key]: value}))
-  }
+    setFormModel((state) => ({ ...state, [key]: value }));
+  };
 
   const modal = getModal?.();
 
-  return <div className="flex">
-  <div className="h-500px flex-1 bg-#f3f5f9 rounded-4px">
-    <div className="graph-container" ref={graphRef}></div>
-  </div>
-  <div className="flex-1 p-10px">
-    <div className="flex flex-col">
-      <div className="flex-1">
-        <Form layout="vertical" size="small">
-          <Form.Item label="图片格式">
-            <CheckCard.Group className="flex" value={formModel.type} onChange={(value) => handleSetFormValue("type", value)}>
-              <CheckCard className="w-100px h-40px" title="PNG" value={'png'}></CheckCard>
-              <CheckCard className="w-100px h-40px" title="JPG" value={'jpg'}></CheckCard>
-              <CheckCard className="w-100px h-40px" title="SVG" value={'svg'}></CheckCard>
-            </CheckCard.Group>
-          </Form.Item>
-          {
-            formModel.type !== 'svg' && <Form.Item label="图片质量">
-            <Radio.Group value={formModel.quality} onChange={(e) => handleSetFormValue("quality", e.target.value)}>
-              <Radio.Button value={1}>高清</Radio.Button>
-              <Radio.Button value={2}>普通</Radio.Button>
-            </Radio.Group>
-          </Form.Item>
-          }
-          <Form.Item label="水印设置">
-            <Input placeholder="请输入水印内容" value={formModel.watermark} onChange={(e) => handleSetFormValue("watermark", e.target.value)} />
-          </Form.Item>
-          <Form.Item label="水印样式">
-            <CheckCard.Group className="flex flex-wrap" value={formModel.watermarkStyle} onChange={(value) => handleSetFormValue("watermarkStyle", value)} >
-              <CheckCard className="w-96px h-50px" title="文字水印" value={1}></CheckCard>
-              <CheckCard className="w-96px h-50px" title="图片水印" value={2}></CheckCard>
-              <CheckCard className="w-96px h-50px" title="图片水印" value={3}></CheckCard>
-              <CheckCard className="w-96px h-50px" title="图片水印" value={4}></CheckCard>
-              <CheckCard className="w-96px h-50px" title="图片水印" value={5}></CheckCard>
-              <CheckCard className="w-96px h-50px" title="图片水印" value={6}></CheckCard>
-            </CheckCard.Group>
-          </Form.Item>
-        </Form>
+  return (
+    <div className="flex">
+      <div className="h-500px flex-1 bg-#f3f5f9 rounded-4px">
+        <div className="graph-container" ref={graphRef}></div>
       </div>
-      <div className="flex justify-end gap-8px">
-        <Button size="small" onClick={() => modal?.destroy()}>取消</Button>
-        <Button size="small" type="primary" onClick={handleExport}>开始导出</Button>
+      <div className="flex-1 p-10px">
+        <div className="flex flex-col">
+          <div className="flex-1">
+            <Form layout="vertical" size="small">
+              <Form.Item label="图片格式">
+                <CheckCard.Group
+                  className="flex"
+                  value={formModel.type}
+                  onChange={(value) => handleSetFormValue("type", value)}
+                >
+                  <CheckCard
+                    className="w-100px h-40px"
+                    title="PNG"
+                    value={"png"}
+                  ></CheckCard>
+                  <CheckCard
+                    className="w-100px h-40px"
+                    title="JPG"
+                    value={"jpg"}
+                  ></CheckCard>
+                  <CheckCard
+                    className="w-100px h-40px"
+                    title="SVG"
+                    value={"svg"}
+                  ></CheckCard>
+                </CheckCard.Group>
+              </Form.Item>
+              {formModel.type !== "svg" && (
+                <Form.Item label="图片质量">
+                  <Radio.Group
+                    value={formModel.quality}
+                    onChange={(e) =>
+                      handleSetFormValue("quality", e.target.value)
+                    }
+                  >
+                    <Radio.Button value={1}>高清</Radio.Button>
+                    <Radio.Button value={2}>普通</Radio.Button>
+                  </Radio.Group>
+                </Form.Item>
+              )}
+              <Form.Item label="水印设置">
+                <Input
+                  placeholder="请输入水印内容"
+                  value={formModel.watermark}
+                  onChange={(e) =>
+                    handleSetFormValue("watermark", e.target.value)
+                  }
+                />
+              </Form.Item>
+              <Form.Item label="水印样式">
+                <CheckCard.Group
+                  className="flex flex-wrap"
+                  value={formModel.watermarkStyle}
+                  onChange={(value) =>
+                    handleSetFormValue("watermarkStyle", value)
+                  }
+                >
+                  <CheckCard
+                    className="w-96px h-50px"
+                    title="文字水印"
+                    value={1}
+                  ></CheckCard>
+                  <CheckCard
+                    className="w-96px h-50px"
+                    title="图片水印"
+                    value={2}
+                  ></CheckCard>
+                  <CheckCard
+                    className="w-96px h-50px"
+                    title="图片水印"
+                    value={3}
+                  ></CheckCard>
+                  <CheckCard
+                    className="w-96px h-50px"
+                    title="图片水印"
+                    value={4}
+                  ></CheckCard>
+                  <CheckCard
+                    className="w-96px h-50px"
+                    title="图片水印"
+                    value={5}
+                  ></CheckCard>
+                  <CheckCard
+                    className="w-96px h-50px"
+                    title="图片水印"
+                    value={6}
+                  ></CheckCard>
+                </CheckCard.Group>
+              </Form.Item>
+            </Form>
+          </div>
+          <div className="flex justify-end gap-8px">
+            <Button size="small" onClick={() => modal?.destroy()}>
+              取消
+            </Button>
+            <Button size="small" type="primary" onClick={handleExport}>
+              开始导出
+            </Button>
+          </div>
+        </div>
       </div>
     </div>
-  </div>
-</div>
-}
-export const exportImage = (graph: Graph, type?: 'svg' | 'png' | 'jpg') => {
+  );
+};
+export const exportImage = (graph: Graph, type?: "svg" | "png" | "jpg") => {
   const modal = Modal.info({
     title: "下载预览",
     icon: <></>,
     width: 800,
     closable: true,
     footer: <></>,
-    content: <ExportComponent graph={graph} getModal={() => modal} type={type} />,
-  })
-}
+    content: (
+      <ExportComponent graph={graph} getModal={() => modal} type={type} />
+    ),
+  });
+};

+ 11 - 5
apps/designer/src/utils/hander.tsx

@@ -715,6 +715,8 @@ export const handleGroup = (graph: Graph, cells: Cell[]) => {
     },
   });
   cells?.forEach((cell) => parent.addChild(cell));
+  graph.select(parent);
+  graph.createTransformWidget(parent);
 };
 
 /**
@@ -725,11 +727,15 @@ export const handleUnGroup = (graph: Graph, cells?: Cell[]) => {
   // const cells = graph.getSelectedCells();
   cells = cells || graph.getSelectedCells();
   cells?.forEach((cell) => {
-    const children = cell.getChildren();
-    children?.forEach((child) => {
-      child.setParent(null);
-      graph.addCell(child);
-    });
+    if (cell.data?.isGroup) {
+      const children = cell.getChildren();
+      cell.setChildren(null);
+      children?.forEach((child) => {
+        child.setParent(null);
+        graph.addCell(child);
+      });
+      graph.removeCell(cell.id);
+    }
   });
 };