先看一下效果: 以下是源代码: /**
- 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);