leaferjs / ui

一款好用的 Canvas 渲染引擎,革新的体验。高效绘图 、UI 交互(小游戏、互动应用、组态)、图形编辑。
https://www.leaferjs.com
MIT License
2.32k stars 81 forks source link

请教一个问题 #176

Open rojer95 opened 1 month ago

rojer95 commented 1 month ago

就是我用@leafer-draw/node在服务端进行渲染一些动态的海报 因为是需要生成打印物料。尺寸比较大 有的尺寸类似 8504 * 5669 但是现在渲染导出一张图片内存会飚到1-2个G的情况, 这种应该如何优化呢

leaferjs commented 1 month ago
  1. 需要提供个JSON数据结构,能复现才能看得出原因。

  2. node导出图片会另外再创建一张画布,所以初始化的画布可以宽高设置的小一些(不影响导出,可以节省内存)。

rojer95 commented 1 month ago

你好,这个是完整的DEMO代码:

const { Leafer, UI, useCanvas } = require("@leafer-ui/node");
const napi = require("@napi-rs/canvas");
const http = require("http");

useCanvas("napi", napi); // must

setInterval(() => {
  const memoryUsage = process.memoryUsage();
  console.log(
    [
      `RSS: ${(memoryUsage.rss / 1024 / 1024).toFixed(2)} MB`,
      `Heap total: ${(memoryUsage.heapTotal / 1024 / 1024).toFixed(2)} MB`,
      `Heap used: ${(memoryUsage.heapUsed / 1024 / 1024).toFixed(2)} MB`,
      `External: ${(memoryUsage.external / 1024 / 1024).toFixed(2)} MB`,
    ].join("/")
  );
}, 500);

http
  .createServer(function (req, res) {
    // console.log('data ----> ', JSON.stringify(data, null, 2));
    console.log("start render .....");
    const data = {
      x: 0,
      y: 0,
      id: "stage",
      tag: "Frame",
      data: { pixelRatio: 15, defaultFontSize: 14 },
      fill: [
        { type: "solid", color: "#FFFFFF" },
        {
          url: "http://cdn.eqistu.cn/huizhan_test/m0/20240726/143e1d4e73234612b03205e0c32cb6b4.jpeg",
          type: "image",
        },
      ],
      width: 500,
      height: 333,
      scaleX: 1,
      scaleY: 1,
      shadow: { x: 0, y: 0, blur: 6, color: "#dcdcdc" },
      children: [
        {
          x: 88.29568295836316,
          y: 9.900325705003596,
          id: "9ae65926-4871-4e32-a772-dd01e9e9cf52",
          tag: "Text",
          fill: [{ type: "solid", color: "#000000" }],
          text: "Entry Permit Number: {{uid}}\n\nEntry Permit\n{{exhiName}}\n{{exhiTime}}\n{{name}}\n{{company}}",
          skewX: 0,
          skewY: 0,
          width: 374.62646560925873,
          height: 375.6441570748247,
          stroke: [{ type: "solid", color: "#e3e3e3" }],
          editable: true,
          fontSize: 12,
          rotation: 0,
          textAlign: "center",
          fontFamily: "alibaba-puhui",
          fontWeight: "normal",
          lineHeight: { type: "percent", value: 1.5 },
          strokeWidth: 0,
          letterSpacing: { type: "px", value: 0 },
          textDecoration: "none",
        },
        {
          x: 291.11491990092554,
          y: 133.72768276811547,
          id: "7f19ab68-b670-4d08-90c6-98cdca4171dc",
          tag: "Rect",
          fill: {
            url: "data:image/png;base64,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",
            mode: "fit",
            type: "image",
          },
          text: "文字",
          skewX: 0,
          skewY: 0,
          width: 155.32713731176898,
          height: 148.74114435585363,
          margin: 1,
          editable: true,
          rotation: 0,
          colorDark: "#000000ff",
          colorLight: "#ffffff00",
          errorCorrectionLevel: "H",
        },
      ],
      overflow: "hide",
      hitChildren: true,
    };
    const leafer = new Leafer({
      width: data.width,
      height: data.height,
    });

    leafer.add(UI.one(data));

    leafer
      .export("webp", {
        screenshot: {
          x: data.x,
          y: data.y,
          width: data.width,
          height: data.height,
        },
        pixelRatio: data?.data?.pixelRatio || 1,
      })
      .then(function (result) {
        leafer.clear();
        leafer.destroy(true);
        res.writeHead(200, { "Content-Type": "text/html" });
        res.write(`<img src="${result.data}" />`);
        res.end();
        console.log("start end .....");
      });
  })
  .listen(3100, function () {
    console.log(
      "\x1B[36m%s\x1B[0m",
      "server is running at http://localhost:3100"
    );
  });

image