首页 > 编程语言 >node服务 图片合并echarts图表,绘制方框

node服务 图片合并echarts图表,绘制方框

时间:2023-06-26 11:36:26浏览次数:55  
标签:node index resultData bgCanvas 方框 item res var echarts

效果图:
image

环境及依赖配置

node版本参考:v14.18.3
npm版本参考:6.14.15

环境安装

Mac系统 需要先将Homebrew升级到与系统匹配的版本

系统 命令
Mac OS X brew install pkg-config cairo pango libpng jpeg giflib librsvg pixman
Ubuntu sudo apt-get install build-essential libcairo2-dev libpango1.0-dev libjpeg-dev libgif-dev librsvg2-dev
Fedora sudo yum install gcc-c++ cairo-devel pango-devel libjpeg-turbo-devel giflib-devel
Solaris pkgin install cairo pango pkg-config xproto renderproto kbproto xextproto
OpenBSD doas pkg_add cairo pango png jpeg giflib
Windows And Others wiki

Mac OS X v10.11+:如果系统版本Mac OS X v10.11+并且在编译时遇到问题,请运行以下命令:xcode-select--install

node-canvas安装

1.这里推荐使用yarn,npm可能会遇到权限问题,可使用 npm --build-from-source --unsafe-perm install 尝试(百度只搜到这个方法,亲测无效)
2.为防止node-gyp这个大坑的一系列报错和问题
先全局安装node-gyp

npm -g node-gyp 

3.安装canvas的时候需要从源代码去构建,否则会安装失败或报错,需要在安装是添加一些选项,根据对应的的包管理工具,使用对应的命令

npm: npm install canvas --build-from-source
yarn: npm_config_build_from_source=true yarn add canvas
pnpm: npm_config_build_from_source=true pnpm add canvas

node-canvas源码地址

安装过程中还可能遇到很多告警,如不影响编译安装,可不理会

echarts服务端渲染

代码:
echarts图表配置line.js


var echartLine = (data) => {
    var xData = [], yData = [];
    for (let index = 0; index < data.length; index++) {
        const item = data[index];
        xData.push(item.name)
        yData.push(item.value)
    }
    var option = {
        backgroundColor: "rgba(255,255,255,0.8)",
        grid: {
            left: "10%",
            right: "10%",
            top: "10%",
            bottom: "10%",
            containLabel: true,
            show: true,
            borderColor: "rgba(0,0,0,0)",
        },
        xAxis: {
            type: "category",
            boundaryGap: false,
            offset: 5,
            axisLabel: {
                // color: "rgba(198, 211, 236, 1)",
                fontSize: 12,
                fontFamily: "PingFangSC-Regular, PingFang SC",
                showMaxLabel: false,
            },
            axisLine: {
                show: false,
            },
            axisTick: {
                show: false,
            },
            splitLine: {
                show: false,
                lineStyle: {
                    color: "rgba(64, 72, 106, 1)",
                },
            },
            data: xData,
        },
        yAxis: {
            type: "value",
            offset: 3,
            splitLine: {
                show: true,
                lineStyle: {
                    color: "rgba(64, 72, 106, 1)",
                },
            },
            axisLine: {
                show: false,
            },
            axisTick: {
                show: false,
            },
            axisLabel: {
                // color: "rgba(198, 211, 236, 1)",
                fontSize: 12,
                fontFamily: "PingFangSC-Regular, PingFang SC",
            },
        },
        series: [
            {
                type: "line",
                smooth: true,
                // color: "rgba(98, 208, 255, 1)",
                data: yData,
            },
        ],
    }
    return option
}
module.exports = echartLine;

路由文件index.js

var express = require('express');
var router = express.Router();

//生成echart图片模块
const echarts = require('echarts');
const path = require("path");
const fs = require("fs");

const ECHARTS_LINE = require("../echarts/line");
const { createCanvas, Image } = require('canvas');

var resultData = {
    status: 0,
    data: null,
    msg: ""
}

/* GET home page. */
router.get('/', function (req, res, next) {
    res.render('index', { title: 'Express' });
});

router.get('/testApi', function (req, res, next) {
    res.send({
        code: 1,
        data: "success"
    });
});


var echartsColor = [
    "#74D690",
    "#ff0000",
    "#1AA7E8",
    "#BDE5F8",
    "#5273E0",
    "#32CEDC"
]

router.post('/mergeImage', function (req, res, next) {
    var data = req.body;
    var { imgUrl, imgCoor, chartData } = data
    if (imgUrl && imgCoor && chartData) {
        var coor = []
        for (let index = 0; index < imgCoor.length; index++) {
            const item = imgCoor[index];
            if (item.origin && item.origin.includes(",") && item.target && item.target.includes(",")) {
                var origin = item.origin.split(",")
                var target = item.target.split(",")
                coor.push([+origin[0], +origin[1], target[0] - origin[0], target[1] - origin[1]])
            }
        }
        var bgImg = new Image();
        bgImg.onload = function () {
            const bgCanvas = createCanvas(bgImg.width, bgImg.height);
            var bgCtx = bgCanvas.getContext('2d');
            // bgCtx.rect(0, 0, bgCanvas.width, bgCanvas.height);
            // bgCtx.fillStyle = "#fff";
            // bgCtx.fill();
            bgCtx.drawImage(bgImg, 0, 0, bgImg.width, bgImg.height);

            for (let index = 0; index < coor.length; index++) {
                const item = coor[index];
                bgCtx.strokeStyle = echartsColor[index]
                bgCtx.lineWidth = 4;
                bgCtx.strokeRect(...item);
            }
            // echarts宽高,可以根据bgCanvas动态计算宽高,这里先固定写
            var lineChartWidth = 100
            var lineChartHeight = 100

            var lineChartXY = [bgImg.width - lineChartWidth, 0]

            // 生成echarts折线图
            var option = ECHARTS_LINE(chartData);
            const chartCanvas = createCanvas(lineChartWidth, lineChartHeight);
            var chartCtx = chartCanvas.getContext('2d');
            // chartCtx.rect(0, 0, chartCanvas.width, chartCanvas.height);
            // chartCtx.fillStyle = "#fff";
            // chartCtx.fill();
            const chart = echarts.init(chartCanvas);
            chart.setOption(option);

            chartCanvas.toBuffer(function (err, buf) {
                if (err) {
                    return res.send({ msg: "Diagram generation failed" })
                } else {
                    var chartImg = new Image()
                    chartImg.onload = function () {
                        // 1492 826 1092 526
                        // console.log(bgCanvas.width, bgCanvas.height, "bgCanvas")
                        // console.log(chartCanvas.width, chartCanvas.height, "chartCanvas")
                        // console.log(bgCanvas.width - chartCanvas.width, bgCanvas.height - chartCanvas.height, "xy")

                        // res.writeHead(200, {
                        //     'Content-Type': 'image/png'
                        // })
                        bgCtx.drawImage(chartImg, ...lineChartXY, lineChartWidth, lineChartHeight)
                        // res.write(bgCanvas.toBuffer('image/png'))
                        // console.log(bgCanvas.toDataURL())
                        // bgCanvas.toBuffer('image/png')
                        resultData.status = 200
                        resultData.data = bgCanvas.toDataURL()
                        resultData.msg = "success"

                        return res.send(resultData)


                    }
                    chartImg.onerror = function () {
                        resultData.status = 500;
                        resultData.msg = "Diagram loading failed";

                        return res.send(resultData);
                    }
                    chartImg.src = buf
                }
            })
        }
        bgImg.onerror = function () {
            resultData.status = 500;
            resultData.msg = "Image loading failed";
            return res.send(resultData);

        }
        bgImg.src = imgUrl
    } else {
        resultData.data = "";
        resultData.status = 400;
        resultData.msg = "必传字段不可为空";
        res.send(resultData);
        res.end();
    }
});

module.exports = router;

测试接口

let params = {
//图片地址
  imgUrl: "http://localhost:4060/images/shujia.jpg",
  //画框对角线坐标
  imgCoor: [
    { origin: "100,100", target: "150,130" },
    { origin: "180,150", target: "210,190" },
  ],
  //折线图数据
  chartData: [
    { name: "2023-06-10", value: "15" },
    { name: "2023-06-12", value: "30" },
    { name: "2023-06-13", value: "40" },
    { name: "2023-06-14", value: "20" },
    { name: "2023-06-15", value: "22" },
    { name: "2023-06-16", value: "15" },
    { name: "2023-06-17", value: "20" },
  ],
};

mergeImage(params).then((res) => {
 console.log(res)
});

标签:node,index,resultData,bgCanvas,方框,item,res,var,echarts
From: https://www.cnblogs.com/FormerWhite/p/17505183.html

相关文章

  • python数据可视化神器--pyecharts 快速入门
    大家好,我是一名来自广东的邓棋文,目前正在学习Python的开发技能。在开发过程中,数据可视化是一个非常重要的环节,帮助我们理解数据,从而作出正确的决策。今天,我将介绍一个强大的Python数据可视化库——pyecharts。pyecharts是一个用于生成ECharts图表的类库。ECharts是百度开源的一个......
  • node框架介绍sails
     Sails: 官方网站:http://sailsjs.org/#/ MVCfornode auto-generateRESTAPIs EasyWebSocketSupport         ......
  • 11.2.0.1 Grid Infrastructure Installation Failed at Second Nodes While Running r
     11.2.0.1GridInfrastructureInstallationFailedatSecondNodesWhileRunningroot.shDueToASMCrashCausedbylmonTimeout[ID1239123.1]--------------------------------------------------------------------------------  修改时间06-JAN-2011    ......
  • electron中调用node.js API
    主进程在node.js环境中运行,等同于它拥有调用require模块和使用所有node.jsAPI的能力。但是在渲染器进程中,渲染器是无法直接访问require和其他node.jsAPI的,想要访问有以下两种方法:Preload脚本预加载脚本运行在渲染器环境中,可以在BrowserWindow构造方法中的webPreferences选项里被......
  • 11gR2 OneNode Convert RAC
                  11gR2OneNodeConvertRAC 一、查看状态[oracle@ora11grac1~]$srvctlconfigdatabase-dwooDatabaseuniquename:wooDatabasename:wooOraclehome:/DBSoft/oracle/product/11.2.0/dbhome_1Oracleuser:oracleSpfile:+D......
  • 用node-webkit把web应用打包成桌面应用
    1.下载node-webkit:https://github.com/nwjs/nw.js=>下载完成后是个压缩包。解压即可。=>看到nw.exe文件,双击运行一下,看是否正常=>exe文件的图标可以用ResourceHacker,nw-builder和node-winresourcer之类的工具替换。 2.项目新建package.json:{  "name":"zqz",//这里......
  • 使用Echarts时报 Implementation of registerMap doesn't exists 错误解决办法
    最新的echarts在使用时,如果使用按需加载的方式引入依赖。在使用registerMap函数时会报错如果出现这两个错误:ImplementationofregisterMapdoesn'texists.或者Mapxxxnotexists.TheGeoJSONofthemapmustbeprovided.那么大概率是因为echarts升级后导致的不兼容问题。......
  • create-react-app 除了NODE_ENV如何区分环境变量
    比如webpack打包的时候,可能要打包到测试环境或者生产环境,但是这时候NODE_ENV的值都是production,这个时候如何区分呢。答案是:cross-env和webpack.DefinePlugin1.定义环境变量到编译环境:测试环境: cross-envNODE_STAGE=testnpmrunbuild预上线: cross-envNODE_STAGE=s......
  • 解决echarts鼠标选择错位的问题
    在写echarts时遇到的问题,鼠标选择总是和图形错位,同事提供的解决方法,在这里记录一下。1.增加以下代码exportdefaultfunctionresizeEcharts(ele){letrate=1920/window.innerWidth;if(ele.style){ele.style.zoom=1*rate;ele.style.transform=`......
  • Elasticsearch专题精讲—— REST APIs —— Cluster APIs —— Node specification
     RESTAPIs——ClusterAPIs—— Nodespecification(节点过滤)https://www.elastic.co/guide/en/elasticsearch/reference/8.8/cluster.html#cluster-nodes Somecluster-levelAPIsmayoperateonasubsetofthenodeswhichcanbespecifiedw......