/* * @Author: your name * @Date: 2025-04-14 16:09:13 * @LastEditTime: 2025-04-30 13:47:08 * @LastEditors: bogon * @Description: In User Settings Edit * @FilePath: /downLoadServer/src/server/utils/chartsCom/3DDrawingChart.js */ import puppeteer from "puppeteer"; import fs from "fs-extra"; import path from "path"; import FormData from "form-data"; import { colorSchemes } from "../colors.js"; export const generate3DDrawingChart = async (data) => { try { console.log("开始生成热力图..."); console.log("数据:", data); const colorSchemesItem = colorSchemes[0].colors; // 创建临时目录 const tempDir = path.join(process.cwd(), "images"); await fs.ensureDir(tempDir); const tempFilePath = path.join( tempDir, `temp_heatmap_chart_${Date.now()}.png` ); // 获取 plotly.js 的绝对路径 const plotlyPath = path.join( process.cwd(), "src", "public", "js", "plotly-3.0.1.min.js" ); const plotlyContent = await fs.readFile(plotlyPath, "utf-8"); // 创建浏览器实例 const browser = await puppeteer.launch({ headless: "new", args: ["--no-sandbox", "--disable-setuid-sandbox"], }); try { const page = await browser.newPage(); // 准备图表数据 const chartDataset = data.data[0]; // 修改为 data.chartData const uniqueColors = [...new Set(chartDataset.color)]; const traces = uniqueColors.map((color, idx) => { const colorData = chartDataset.color.map((c) => (c === color ? 1 : 0)); return { x: chartDataset.xData.filter((_, i) => colorData[i] === 1), y: chartDataset.yData.filter((_, i) => colorData[i] === 1), z: chartDataset.zData.filter((_, i) => colorData[i] === 1), mode: "markers", // 根据需要设置模式 type: "scatter3d", marker: { size: 1, // 使用动态点大小 color: colorSchemesItem[idx], // 使用配色方案 colorscale: "YlGnBu", }, name: ` ${color}`, // hovertemplate: `${data.xaixs}: %{x}
${data.yaixs}: %{y}
${data.zaixs}: %{z} `, }; }); // 准备布局配置 const layout = { title: { text: chartDataset.title, font: { size: 16, weight: "bold", }, }, scene: { xaxis: { gridcolor: "rgb(255,255,255)", tickcolor: "rgb(255,255,255)", backgroundcolor: "#CFD4DC", showbackground: true, linecolor: "black", // 轴线颜色 ticks: "outside", // 设置刻度线在轴线外 fixedrange: true, // 防止缩放 tickcolor: "black", tickangle: -10, title: { text: data.xaixs, }, }, yaxis: { type: "category", categoryorder: "array", // 自定义顺序,确保间隔均匀 categoryarray: [...new Set(chartDataset.yData)], gridcolor: "rgb(255,255,255)", linecolor: "black", ticks: "outside", gridcolor: "rgb(255,255,255)", tickcolor: "rgb(255,255,255)", backgroundcolor: "#CFD4DC", showbackground: true, tickcolor: "black", tickangle: 25, title: { text: data.yaixs, }, }, zaxis: { gridcolor: "rgb(255,255,255)", tickcolor: "rgb(255,255,255)", backgroundcolor: "#CFD4DC", showbackground: true, fixedrange: true, // 防止缩放 linecolor: "black", // 轴线颜色 ticks: "outside", // 设置刻度线在轴线外 tickcolor: "black", tickangle: -90, title: { text: data.zaixs, }, }, aspectratio: { x: 2.2, y: 1.7, z: 1, }, plot_bgcolor: "#e5ecf6", gridcolor: "#fff", bgcolor: "#e5ecf6", // 设置背景颜色 camera: { up: { x: 0.200292643688136, y: 0.2488259353493132, z: 0.947612004346693, }, center: { x: -0.052807476121180814, y: 0.02451796399554085, z: -0.022911006648570736, }, eye: { x: -2.126379643342493, y: -2.551422475965373, z: 1.0917667684145647, }, projection: { type: "orthographic", }, }, }, margin: { t: 50, b: 50, l: 50, r: 50 }, staticPlot: false, showlegend: true, legend: { marker: { size: 10, // 图例中点的大小 }, }, }; // 准备 HTML 内容 const htmlContent = ` 热力图
`; // ... existing code ... // 设置页面内容 await page.setContent(htmlContent, { waitUntil: "networkidle0", }); // 等待图表渲染完成,延长超时时间 await page.waitForFunction(() => window.chartRendered === true, { timeout: 150000, // 延长到 120 秒 }); // 截图并保存到临时文件 const chartElement = await page.$("#chart"); await chartElement.screenshot({ path: tempFilePath, type: "png", }); // 上传图片到服务器 const formData = new FormData(); formData.append("file", fs.createReadStream(tempFilePath)); // 发送上传请求 const response = await axios.post( `${process.env.API_BASE_URL}/examples/upload`, { filePath: tempFilePath } ); // return formData; } catch (error) { console.error("生成3D图失败:", error); throw error; } finally { await browser.close(); } } catch (error) { console.error("生成3D图失败:", error); throw error; } };