nodeの環境の下でecharts図表に文案を加えます.
10721 ワード
開発環境:node開発言語:javascript開発に依存するパッケージ: node-charts canvas グラフの幅は1000です.最後に出す効果を下の図を見てください.
チャートに追加のテキストブロックを追加すると、1つの属性
コードは以下の通りです
問題は二つありますは一行だけで、後ろの文字は全部切断されました. は、凡例の文字をカバーしており、間隔がない .
第2の問題はよく解決しています.echartsの配置を熟知すれば、gridのbottom、legendのbottomに値を設定します.しかし、この値はダイナミックで、文案の行数と関係があります.まず基本値を決めます.一行だけあれば、gridのbottomは90、legendのbottomは35です.
改行しましたが、一行の文字が違っていて、行間がないので、窮屈です.行ごとの長さを計算する方法を説明します.中国語と英語の幅が違っています.各文字の幅を知る必要があります.そして、graphicはimageをサポートしているのではないですか?考えを変えて、文字を画像に変えましょう.canvasに関連してgoogleがcanvas文字を改行した後、このcanvasテキストを見つけて自動的に改行、字間、縦列などを描きます.また、このアムウェイの下で、彼の書いたブログは全部干物だらけで、canvasの中に有用なAPIがあります.
そしてgraphicを修正します
行間の問題は解決されていませんでした.graphicは配列である以上、行ごとに分解して個々の対象として、bottomの値が違います.
最終ソースコード転送ゲート:github
締め括りをつける
echart座標系を理解してecharts基本構成を熟知しています.canvas基本APIは数学を熟知しています.数字に対して敏感にして、書かないでください.
多く捜索して、多く試みて、多く考えてやっと融通がききます.
チャートに追加のテキストブロックを追加すると、1つの属性
graphic【ˈgrafik】
だけが実装できるようになります.これは、元のパターン要素コンポーネントを指しています.image, text, circle, sector, ring, polygon, polyline, ...
などの様々なタイプから構成されてもいいです.すぐやりますコードは以下の通りです
var node_echarts = require("node-echarts");
var Path = require("path");
const text = ' 4G , idea , 30 >80% , OOM!Chrome ! , idea chrome , 40% 。 , , (16G macbook pro), , 4G , ! , , , 。 , , JetBrains 。';
const config = {
legend: { bottom: 0, show: true, data: [" ", " "] },
xAxis: [
{
type: "category",
data: [
"201701",
"201702",
"201703",
"201704",
"201705",
"201706",
"201707",
"201708",
"201709",
"201710",
"201711",
"201712",
"201801"
],
axisLabel: { interval: 0 },
axisPointer: { type: "shadow" },
splitLine:{show: false}
}
],
yAxis: [
{ type: "value", axisLabel: { formatter: null } },
{ type: "value", axisLabel: { formatter: "{value}%" }}
],
series: [
{
type: "bar",
name: " ",
data: [
23620000,
21060000,
26420000,
30180000,
31430000,
34100000,
33740000,
40170000,
39910000,
38420000,
49300000,
50710000,
46550000
],
yAxisIndex: 0
},
{
type: "line",
name: " ",
data: [
-23,
-12.13,
20.26,
12.46,
4,
7.82,
-1.09,
16.02,
-0.65,
-3.88,
22.05,
2.79,
-8.95
],
yAxisIndex: 1
}
],
color: ["#4498f6", "#d9e96c"],
graphic: [
{
type: 'text',
left: '10%',
bottom: 'bottom',
style: {
fill: '#333',
text: text,
font: '14px Microsoft YaHei'
}
}
],
};
node_echarts({
width: 1000,
height: 400,
option: config,
path: Path.join(__dirname, "./charts.png")
});
process.exit();
効果は下図のようです問題は二つあります
第2の問題はよく解決しています.echartsの配置を熟知すれば、gridのbottom、legendのbottomに値を設定します.しかし、この値はダイナミックで、文案の行数と関係があります.まず基本値を決めます.一行だけあれば、gridのbottomは90、legendのbottomは35です.
const config = {
legend: { bottom: 3 * 15 + 35, show: true, data: [" ", " "] },
grid: {bottom: 3 * 15 + 90}
...
具体的な行数を得るには、1つ目の問題を解決するために、最も核心的な問題は限られた幅の中でどのように1つの文字の行数を計算しますか?まず次の行にどれぐらいの文字を入れるかを計算してください.中国語は全部中国語で計算します.これで63,行数=Math.ceeir(文字の総長さ/63).行数を得ると、各行の文字が分かります.つまり、改行はこうなります....
graphic: [
{
type: 'text',
left: '10%',
bottom: 'bottom',
style: {
fill: '#333',
text: ['text','text2', 'text3'].join('
'),
font: '14px Microsoft YaHei'
}
}
],
...
長い間考えましたが、コードが出ました....
const buildText = (result=text) => {
const graphicY = 15;
let texts = [];
let gridBottom = 90;
let legendBottom = 35;
const rlen = 63; //
const len = result.length; //
//
if (len > rlen) {
const temp = Math.ceil(len / rlen); //
const arr = result.split(""); //
const newArrs = {};
//
for (let k = 0; k < temp; k++) {
newArrs[k] = []; //
for (let i = rlen * k; i < rlen * (k + 1); i++) {
if(arr[i] != undefined)
newArrs[k].push(arr[i]);
}
}
for(let j in newArrs){
texts.push(newArrs[j].join(''));
}
const lastLen = texts.length-1;
gridBottom = lastLen * graphicY + gridBottom;
legendBottom = lastLen * graphicY + legendBottom;
} else {
texts = [result];
}
// console.log(texts);
return {
graphic: [
{
type: "text",
left: "10%",
bottom: "bottom",
style: {
fill: "#333",
text: texts.join("
"),
font: "14px Microsoft YaHei"
}
}
],
gridBottom: gridBottom,
legendBottom: legendBottom
};
}
const texts = buildText();
const config = {
...
legend: { bottom: texts.legendBottom, show: true, data: [" ", " "] },
grid:{ bottom: texts.gridBottom},
...
}
config.graphic = texts.graphic;
効果は以下の通りです.改行しましたが、一行の文字が違っていて、行間がないので、窮屈です.行ごとの長さを計算する方法を説明します.中国語と英語の幅が違っています.各文字の幅を知る必要があります.そして、graphicはimageをサポートしているのではないですか?考えを変えて、文字を画像に変えましょう.canvasに関連してgoogleがcanvas文字を改行した後、このcanvasテキストを見つけて自動的に改行、字間、縦列などを描きます.また、このアムウェイの下で、彼の書いたブログは全部干物だらけで、canvasの中に有用なAPIがあります.
measureText
、文字の幅を計算します.文字を画像のコードに変えます.var fs = require('fs')
var path = require('path')
var Canvas = require('canvas')
const maxWidth = 1000;
let height = 20;
const text = ' 4G , idea , 30 >80% , OOM!Chrome ! , idea chrome , 40% 。 , , (16G macbook pro), , 4G , ! , , , 。 , , JetBrains 。';
const rlen = 63; //
const len = text.length; //
const temp = Math.ceil(len / rlen); //
var canvas = Canvas.createCanvas(maxWidth, temp * height)
var ctx = canvas.getContext('2d')
ctx.globalAlpha = 1
ctx.font = '14px Microsoft Yahei'
ctx.lineWidth = 1
ctx.fillStyle = '#000'
const arrText = text.split('');
let line = '';
let y = 20;
const lineHeight = 25;
// , , , Y
for (var n = 0; n < arrText.length; n++) {
var testLine = line + arrText[n];
var metrics = ctx.measureText(testLine);
var testWidth = metrics.width;
if (testWidth > maxWidth && n > 0) {
ctx.fillText(line, 0, y);
line = arrText[n];
y += lineHeight;
} else {
line = testLine;
}
// console.log(line)
}
console.log(line)
ctx.fillText(line, 0, y);
canvas.createPNGStream().pipe(fs.createWriteStream(path.join(__dirname, 'text.png')))
もらった写真は以下の通りです.そしてgraphicを修正します
...
graphic:[{
type: 'image',
left: '10%',
bottom: 'bottom',
style: {
image: path.join(__dirname, 'text.png')
width: 1000,
height: 200
}
}],
...
しかし、画像は生成されておらず、上のコードは機能していません.ソースコードを調べましたが、原因が見つからないので、issueを提出するしかありません.これはまた起点に戻りますが、文字の長さを計算する方法は上記のようになります.const buildText = (text=text) => {
const graphicY = 15;
let gridBottom = 90;
let legendBottom = 35;
const maxWidth = 900;
const canvas = createCanvas(maxWidth,100);
const ctx = canvas.getContext("2d");
ctx.font = "normal 14px SongTi";
const arrText = text.split('');
let line = '';
const newArrs = [];
for (var n = 0; n < arrText.length; n++) {
var testLine = line + arrText[n];
var metrics = ctx.measureText(testLine);
var testWidth = metrics.width;
if (testWidth > maxWidth & n>0) {
line = arrText[n];
newArrs.push(testLine.substr(0, testLine.length-1));
} else {
line = testLine;
}
}
newArrs.push(line);
//console.log(newArrs);
const row = newArrs.length;
if (row > 1) {
gridBottom = row * graphicY + gridBottom;
legendBottom = row * graphicY + legendBottom;
}
return {
graphic:[
{
type: "text",
left: "10%",
bottom: "bottom",
style: {
fill: "#333",
text: newArrs.join("
"),
font: "14px Songti"
}
}
],
gridBottom: gridBottom,
legendBottom: legendBottom
};
}
得られた効果は以下の通りです.行間の問題は解決されていませんでした.graphicは配列である以上、行ごとに分解して個々の対象として、bottomの値が違います.
const buildText = (text=text) =>{
const graphicY = 15;
const lineY = 20; // bottom
let gridBottom = 90;
let legendBottom = 35;
const maxWidth = 900;
const canvas = createCanvas(maxWidth,100);
const ctx = canvas.getContext("2d");
ctx.font = "normal 14px SongTi";
const arrText = text.split('');
let line = '';
const newArrs = [];
for (var n = 0; n < arrText.length; n++) {
var testLine = line + arrText[n];
var metrics = ctx.measureText(testLine);
var testWidth = metrics.width;
if (testWidth > maxWidth & n>0) {
line = arrText[n];
newArrs.push(testLine.substr(0, testLine.length-1));
} else {
line = testLine;
}
}
newArrs.push(line);
//console.log(newArrs);
const row = newArrs.length; //
if (row > 1) {
gridBottom = row * graphicY + gridBottom;
legendBottom = row * graphicY + legendBottom;
}
let graphics = [];
//
for (let k=0; k < row; k++){
const temp = {
type: "text",
left: "5%",
bottom: (row-1-k) * lineY, // ,
style: {
fill: "#333",
text: [`${newArrs[k]}`].join("
"),
font: "14px SongTi"
}
}
graphics.push(temp);
}
// console.log(graphics);
return {
graphic: graphics,
gridBottom: gridBottom,
legendBottom: legendBottom
};
これで問題はすべて解決された.最終ソースコード転送ゲート:github
締め括りをつける
echart座標系を理解してecharts基本構成を熟知しています.canvas基本APIは数学を熟知しています.数字に対して敏感にして、書かないでください.
多く捜索して、多く試みて、多く考えてやっと融通がききます.