摘要:開發環境開發語言開發依賴的包圖表的寬度是先把最終要呈現的效果貼出來,見下圖查看配置項及實例,給圖表增加額外的文本塊,只有一個屬性似乎可以實現,它指的是原生圖形元素組件,可以由多種類型組成,如,結合給的實例,看起來很不錯,馬上開干。
開發環境:node
開發語言:javascript
開發依賴的包:node-charts
canvas
圖表的寬度是1000
先把最終要呈現的效果貼出來,見下圖:
查看charts配置項及實例,給圖表增加額外的文本塊,只有一個屬性graphic【?grafik】似乎可以實現,它指的是原生圖形元素組件,可以由多種類型組成,如image, text, circle, sector, ring, polygon, polyline, ...,結合給的實例,看起來很不錯,so easy!馬上開干。
代碼如下:
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,每多一行,就多加15,偽代碼如下:
const config = { legend: { bottom: 3 * 15 + 35, show: true, data: ["身份證數量", "環比增長率"] }, grid: {bottom: 3 * 15 + 90} ...
要得到具體的行數,其實是解決第1個問題,所以最核心的問題是在限定的寬度里怎么計算一段文字的行數?
先算下一行能放多少個字符,中英文都算一個字符,以都是中文來算,這樣算下得到結果是63,行數 = Math.ceil(字符總長度/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
總結了解echarts坐標系
熟悉echarts基本配置
熟悉echarts graphic配置
了解canvas基本API
熟悉數學
對于數字要保持敏感,不要寫死了
多搜索,多嘗試,多思考才會變通
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/93630.html
摘要:瀏覽器兼容性事件綁定一框架使用的是什么如何避免樣式污染,以及改變其樣式引入插件的方式如何按需引入安裝二的生命周期的使用生命周期鉤子函數包含的組件緩存與排除的組件不緩存,優先級大于的作用中一般處理什么問題三如何封裝組件組件封裝過么如何 瀏覽器兼容性(ie)1.事件綁定 vue一. UI框架使用的是什么? 1.1 如何避免樣式污染,以及改變其樣式;1.2 vue-cli 引入插件的方式? ...
摘要:每周前端開源推薦第六期從名字就可以很容易的看出該項目的作用,解壓縮。同時支持瀏覽器和。是任務調度的項目。初始化定義人物每三分鐘觸發一次觸發一個交互式學習的方式。強烈建議大家先去體驗一下的介紹是由百度團隊開發的一款開源圖表項目。 每周前端開源推薦第六期 43081j / rar.js Pure-JavaScript RAR reader using AJAX, File API...
摘要:每周前端開源推薦第六期從名字就可以很容易的看出該項目的作用,解壓縮。同時支持瀏覽器和。是任務調度的項目。初始化定義人物每三分鐘觸發一次觸發一個交互式學習的方式。強烈建議大家先去體驗一下的介紹是由百度團隊開發的一款開源圖表項目。 每周前端開源推薦第六期 43081j / rar.js Pure-JavaScript RAR reader using AJAX, File API...
摘要:每周前端開源推薦第六期從名字就可以很容易的看出該項目的作用,解壓縮。同時支持瀏覽器和。是任務調度的項目。初始化定義人物每三分鐘觸發一次觸發一個交互式學習的方式。強烈建議大家先去體驗一下的介紹是由百度團隊開發的一款開源圖表項目。 每周前端開源推薦第六期 43081j / rar.js Pure-JavaScript RAR reader using AJAX, File API...
摘要:今天我就來介紹下在中如何使用來顯示各種圖表。首先需要在我們的項目中安裝組件,該組件是兼容和安卓雙平臺的。組件主要有三個屬性圖表的相關配置和數據。圖表的高度,默認值是。解決方法將中的代碼修改為同時將文件拷貝到安卓項目下面的文件夾中。 本文原創首發于公眾號:ReactNative開發圈 Echarts是百度推出的免費開源的圖表組件,功能豐富,涵蓋各行業圖表。相信很多同學在網頁端都使用過。今...
閱讀 3557·2021-08-02 13:41
閱讀 2391·2019-08-30 15:56
閱讀 1520·2019-08-30 11:17
閱讀 1174·2019-08-29 15:18
閱讀 580·2019-08-29 11:10
閱讀 2671·2019-08-26 13:52
閱讀 508·2019-08-26 13:22
閱讀 2949·2019-08-23 15:41