Quantcast
Channel: CNode:Node.js专业中文社区
Viewing all articles
Browse latest Browse all 14821

使用node生成柱状图

$
0
0

先看一下效果: untitled1.png以下是源代码: /**

  • Created by zhoulanhong on 12/29/16. */

var barImage = { width: 600, height: 400, bgcolor: {red: 255, green: 255, blue: 255}, header: 30, bottom: 30, title: “Vote Result”, barcolor: {red: 230, green: 230, blue: 230}, bars: [{ text: “天朝”, amout: 1, color: {red: 0, green: 100, blue: 200}, }, { text: “日本”, amout: 2, color: {red: 0, green: 100, blue: 200}, }, { text: “美帝”, amout: 1, color: {red: 0, green: 100, blue: 200}, } , { text: “新西兰”, amout: 6, color: {red: 0, green: 100, blue: 200}, } ], output: “output.jpg” }

const fs = require(‘fs’); const img = require(‘images’); const TextToSVG = require(‘text-to-svg’); const textToSVG = TextToSVG.loadSync(‘hanyikaiti.ttf’); const svg2png = require(“svg2png”); function createBar(options) { var svgsPromises = []; var svgsLocs = []; var contentHeight = options.height - (options.header + options.bottom);

if (contentHeight <= 0) {
    throw new Error("height need small than header plus bottom");
}
//先处理数据
var imgBars = options.bars;
//单个bar会占的宽度
var signleBarWidth = options.width / imgBars.length;
var bottomTexts = "";
var total = 0;
for (var i in imgBars) {
    //bottomTexts += imgBars[i].text + "(" + imgBars[i].amout + ")" + "     ";
    //统计一共有多少选项需要生成图片,用于显示刻度
    total += imgBars[i].amout;

    //把每一项显示出来,放到底部
    var curBottom = imgBars[i].text + "(" + imgBars[i].amout + ")";
    svgsPromises.push(svg2png(textToSVG.getSVG(curBottom, {
        x: 0,
        y: 0,
        fontSize: 16,
        anchor: 'top',
    })));
    svgsLocs.push({
        width: (i * signleBarWidth) + (signleBarWidth - curBottom.length * 11) / 2,
        height: options.height - options.bottom
    });
}

//渲染背景
var mainImg = img(options.width, options.height);
mainImg.fill(options.bgcolor.red, options.bgcolor.green, options.bgcolor.blue);

//渲染内容区域
var contentImg = img(options.width, contentHeight);
contentImg.fill(options.barcolor.red, options.barcolor.green, options.barcolor.blue);
mainImg.draw(contentImg, 0, options.header);

//渲染刻度
for (var i = 0; i < 5; i++) {
    var contentImg = img(options.width, 1);
    contentImg.fill(0, 0, 0);
    mainImg.draw(contentImg, 30, contentHeight / 5 * (i + 1) - options.bottom - (5 - i));
    var curnbr = ((total / 5) * (5 - i)).toFixed(2) + "";
    svgsPromises.push(svg2png(textToSVG.getSVG(curnbr, {
        x: 0,
        y: 0,
        fontSize: 16,
        anchor: 'top',
    })));
    svgsLocs.push({
        width: 0,
        height: contentHeight / 5 * (i + 1) - curnbr.length - options.bottom - 3
    });
}

//生成柱状图区域
if (imgBars.length > 0) {
    var barWidth = options.width / imgBars.length * 0.1;
    //生成具体的柱状图
    for (var i in imgBars) {
        var curHeight = contentHeight * imgBars[i].amout / total;
        var curBarImg = img(barWidth, curHeight);
        curBarImg.fill(imgBars[i].color.red, imgBars[i].color.green, imgBars[i].color.blue);
        mainImg.draw(curBarImg, (signleBarWidth - barWidth) / 2 + (i * signleBarWidth), (options.header + contentHeight - curHeight));
    }
}

svgsPromises.push(svg2png(textToSVG.getSVG(options.title, {
    x: 10,
    y: 0,
    fontSize: 24,
    anchor: 'top',
})));
svgsLocs.push({
    width: 10,
    height: 2
});

Promise.all(svgsPromises).then(function (buffer) {
    for (var i in buffer) {
        var curImg = img(buffer[i]);
        mainImg.draw(curImg, svgsLocs[i].width, svgsLocs[i].height);
    }

    mainImg.save("output.jpg");
}).catch(function (hello) {
    console.log(hello)
});

} createBar(barImage);


Viewing all articles
Browse latest Browse all 14821

Trending Articles