text-to-chart.js 55 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747
  1. console.log('text-to-chart');
  2. Chart.register(ChartDataLabels);
  3. var inputField = document.getElementById("keyword_data");
  4. var sendButton = document.getElementById("send_data");
  5. var canvasPng = document.getElementById("textToChart");
  6. var img_box = document.getElementById("img_box");
  7. var sidebar = document.getElementById('style_setting');
  8. var input_text_value;
  9. var chartType = 'line';
  10. var unit = '';
  11. var myChart = null;
  12. var chartColor = '#912B2B';
  13. var chartColorBar = '#'
  14. var displayXaxes = true;
  15. var ctx;
  16. var chartlabels;
  17. var chartdata;
  18. var XfontSizeValue = 18;
  19. var YfontSizeValue = 18;
  20. var TitlefontSizeValue = 32;
  21. var chart_bgimg_url = "url(./img/bg.webp)";
  22. var vocab = [];
  23. var chartDiv = document.getElementById('chartdiv');
  24. document.addEventListener('DOMContentLoaded', function () {
  25. axios.get("https://cmm.ai:8080/vocab")
  26. .then(response => {
  27. // apiHideLoading();
  28. console.log(response);
  29. vocab = response.data;
  30. })
  31. .catch(error => {
  32. console.error('發生錯誤:', error);
  33. });
  34. });
  35. inputField.addEventListener('click', function () {
  36. // 確保輸入框處於焦點狀態
  37. inputField.focus();
  38. // 在控制台中顯示焦點狀態
  39. console.log('Input field focused');
  40. });
  41. document.addEventListener('DOMContentLoaded', function () {
  42. // const input = document.getElementById('stockInput');
  43. const suggestions = document.getElementById('suggestions');
  44. inputField.addEventListener('input', function () {
  45. const query = this.value.trim();
  46. suggestions.innerHTML = ''; // 清空之前的建議
  47. console.log('query', query);
  48. if (query) {
  49. // const filteredVocab = vocab.filter(item => item.toLowerCase().includes(query));
  50. const queryTerms = query.split(/\s+/); // 分割輸入的內容
  51. const lastQueryTerm = queryTerms[queryTerms.length - 1];
  52. const filteredVocab = vocab.filter(item => {
  53. // 對每個分割後的單詞進行匹配,只要其中有一個匹配成功就返回 true
  54. return item.toLowerCase().includes(lastQueryTerm.toLowerCase());
  55. });
  56. if (filteredVocab.length > 0) {
  57. suggestions.style.border = '1px solid #ccc';
  58. suggestions.style.display = 'block'; // 顯示建議容器
  59. } else {
  60. suggestions.style.border = 'none';
  61. suggestions.style.display = 'none'; // 隱藏建議容器
  62. }
  63. console.log(queryTerms[queryTerms.length - 1])
  64. filteredVocab.forEach(item => {
  65. const div = document.createElement('div');
  66. div.classList.add('autocomplete-suggestion');
  67. div.textContent = item;
  68. // div.addEventListener('click', function () {
  69. // inputField.value = item;
  70. // suggestions.innerHTML = ''; // 清空建議
  71. // suggestions.style.border = 'none';
  72. // suggestions.style.display = 'none'; // 隱藏建議容器
  73. // });
  74. console.log('queryTerms', queryTerms);
  75. // console.log('filteredVocab', filteredVocab);
  76. div.addEventListener('click', function () {
  77. queryTerms.forEach((term, index) => {
  78. const regex = new RegExp(term, 'gi');
  79. const match = regex.exec(inputField.value);
  80. // console.log(queryTerms[queryTerms.length - 1]);
  81. // console.log(filteredVocab, queryTerms[queryTerms.length - 1])
  82. if (index === queryTerms.length - 1) {
  83. if (match) {
  84. var start = match.index;
  85. var end = start + match[0].length;
  86. console.log(start, end)
  87. const textBefore = inputField.value.substring(0, start);
  88. const textAfter = inputField.value.substring(end, inputField.value.length);
  89. console.log('start', start, 'end', end, 'textBefore', textBefore, 'textAfter', textAfter);
  90. // 捕獲被選中的部分並替換它
  91. const selectedText = inputField.value.substring(start, end);
  92. console.log('selectedText', selectedText);
  93. const newText = textBefore + item + textAfter.replace(selectedText, '');
  94. console.log('newText', newText);
  95. inputField.value = newText;
  96. // inputField.value = textBefore + item.replace(selectedText, '') + textAfter;
  97. suggestions.innerHTML = ''; // 清空建議
  98. suggestions.style.border = 'none';
  99. }
  100. }
  101. });
  102. // const start = inputField.selectionStart;
  103. // const end = inputField.selectionEnd;
  104. });
  105. suggestions.appendChild(div);
  106. });
  107. } else {
  108. suggestions.style.border = 'none';
  109. suggestions.style.display = 'none'; // 隱藏建議容器
  110. }
  111. });
  112. });
  113. // 監聽輸入框的鍵盤事件
  114. // document.getElementById("keyword_data").addEventListener("keyup", function (event) {
  115. // // 判斷是否按下 Enter 鍵 (key code: 13)
  116. // if (event.keyCode === 13) {
  117. // // 觸發送出按鈕的點擊事件
  118. // document.getElementById("send_data").click();
  119. // }
  120. // });
  121. // 定義按鈕點擊事件處理函數
  122. function sendButtonClickHandler() {
  123. console.log(inputField.value);
  124. var input_text_value = inputField.value;
  125. $('#chartdiv').hide();
  126. sidebar.classList.remove('show');
  127. sidebar.classList.add('hidden');
  128. // 在這裡添加你希望在按下按鈕時執行的其他代碼
  129. get_data(input_text_value);
  130. }
  131. sendButton.addEventListener("click", sendButtonClickHandler);
  132. // sendButton.addEventListener("click", function () {
  133. // console.log(inputField.value);
  134. // input_text_value = inputField.value;
  135. // // if (myChart) {
  136. // // console.log('已存在')
  137. // // data = [];
  138. // // labels = [];
  139. // // myChart.removePlugin(Chart.pluginService.getPlugin('afterDraw'));
  140. // // myChart.destroy();
  141. // // }
  142. // get_data(input_text_value);
  143. // });
  144. var lastKeyPressTime = 0;
  145. var enterCount = 0;
  146. var ENTER_THRESHOLD = 500; // 設定連續按下 Enter 的時間閾值(毫秒)
  147. inputField.addEventListener("keyup", function (event) {
  148. // 判斷是否按下 Enter 鍵 (key code: 13)
  149. if (event.key === "Enter") {
  150. var currentTime = new Date().getTime();
  151. // 計算與上一次按鍵按下時間的差值
  152. var timeDiff = currentTime - lastKeyPressTime;
  153. lastKeyPressTime = currentTime;
  154. // 如果兩次 Enter 鍵按下的時間差小於閾值,則增加計數器
  155. if (timeDiff <= ENTER_THRESHOLD) {
  156. enterCount++;
  157. // 如果計數器為2,則觸發 API 請求並重置計數器
  158. if (enterCount === 2) {
  159. sendButtonClickHandler();
  160. enterCount = 0;
  161. }
  162. } else {
  163. // 如果時間差大於閾值,則重置計數器
  164. enterCount = 0;
  165. }
  166. } else {
  167. // 如果按下的不是 Enter 鍵,則重置計數器
  168. enterCount = 0;
  169. }
  170. });
  171. function number_format(number, decimals, dec_point, thousands_sep) {
  172. // * example: number_format(1234.56, 2, ',', ' ');
  173. // * return: '1 234,56'
  174. number = (number + '').replace(',', '').replace(' ', '');
  175. var n = !isFinite(+number) ? 0 : +number,
  176. prec = !isFinite(+decimals) ? 0 : Math.abs(decimals),
  177. sep = (typeof thousands_sep === 'undefined') ? ',' : thousands_sep,
  178. dec = (typeof dec_point === 'undefined') ? '.' : dec_point,
  179. s = '',
  180. toFixedFix = function (n, prec) {
  181. var k = Math.pow(10, prec);
  182. return '' + Math.round(n * k) / k;
  183. };
  184. // Fix for IE parseFloat(0.55).toFixed(0) = 0;
  185. s = (prec ? toFixedFix(n, prec) : '' + Math.round(n)).split('.');
  186. if (s[0].length > 3) {
  187. s[0] = s[0].replace(/\B(?=(?:\d{3})+(?!\d))/g, sep);
  188. }
  189. if ((s[1] || '').length < prec) {
  190. s[1] = s[1] || '';
  191. s[1] += new Array(prec - s[1].length + 1).join('0');
  192. }
  193. return s.join(dec);
  194. }
  195. var labels = [];
  196. var data = [];
  197. function apiLoading() {
  198. document.getElementById('chartDataLoading').style.display = 'block';
  199. }
  200. function apiHideLoading() {
  201. document.getElementById('chartDataLoading').style.display = 'none';
  202. }
  203. const DISPLAY = true;
  204. const BORDER = true;
  205. const CHART_AREA = true;
  206. const TICKS = true;
  207. var labels = [];
  208. var data = [];
  209. var dataArray;
  210. function generateChart(dataArray) {
  211. // 创建一个空数组来存储 labels 和 data
  212. console.log(dataArray)
  213. // 遍历数据数组
  214. for (var i = 0; i < dataArray.length; i++) {
  215. var item = dataArray[i];
  216. // 遍历当前项的属性
  217. for (var key in item) {
  218. // 如果属性名不在 labels 数组中,并且属性值不是对象,则将属性名添加到 labels 数组中
  219. if (typeof item[key] === 'string') {
  220. labels.push(item[key]);
  221. }
  222. // 如果属性值是数值类型,则将其添加到 data 数组中
  223. if (typeof item[key] === 'number') {
  224. data.push(item[key]);
  225. }
  226. }
  227. }
  228. console.log(data);
  229. if (myChart) {
  230. console.log('已存在')
  231. myChart.destroy();
  232. }
  233. if (chartType === "doughnut") {
  234. // createChartDoughnut(chartType, data, labels);
  235. // createChartDoughnut2(data, labels)
  236. } else {
  237. createChart(chartType, data, labels);
  238. }
  239. // console.log(data);
  240. console.log(labels);
  241. }
  242. var amChartInstance;
  243. function extractAndGenerateChart(dataArray) {
  244. for (var i = 0; i < dataArray.length; i++) {
  245. var item = dataArray[i];
  246. // 遍历当前项的属性
  247. for (var key in item) {
  248. // 如果属性名不在 labels 数组中,并且属性值不是对象,则将属性名添加到 labels 数组中
  249. if (typeof item[key] === 'string') {
  250. labels.push(item[key]);
  251. }
  252. // 如果属性值是数值类型,则将其添加到 data 数组中
  253. if (typeof item[key] === 'number') {
  254. data.push(item[key]);
  255. }
  256. }
  257. }
  258. // console.log('key', key);
  259. generateBarChart(key, dataArray);
  260. }
  261. // 圓餅圖
  262. function generatePieChart(dataArray) {
  263. $('#chartdiv').show();
  264. bgImgelement.style.backgroundImage = chart_bgimg_url;
  265. // chartDiv.style.width = "100%"
  266. chartWhitelement.style.background = "rgba(255,255,255,0.5)"
  267. // Themes begin
  268. am4core.useTheme(am4themes_animated);
  269. // Themes end
  270. // Create chart instance
  271. var chart = am4core.create("chartdiv", am4charts.PieChart);
  272. chart.data = dataArray;
  273. chart.innerRadius = am4core.percent(50);
  274. // Add and configure Series
  275. var pieSeries = chart.series.push(new am4charts.PieSeries());
  276. pieSeries.dataFields.value = "y";
  277. pieSeries.dataFields.category = "x";
  278. pieSeries.slices.template.stroke = am4core.color("#fff");
  279. pieSeries.slices.template.strokeWidth = 2;
  280. pieSeries.slices.template.strokeOpacity = 1;
  281. // Configure labels
  282. pieSeries.labels.template.wrap = true;
  283. pieSeries.labels.template.maxWidth = 100;
  284. pieSeries.labels.template.truncate = false;
  285. pieSeries.labels.template.fontSize = 14;
  286. // Configure label text to wrap and show percentages
  287. pieSeries.labels.template.adapter.add("textOutput", function (text, target) {
  288. if (target.dataItem && target.dataItem.values.value.percent) {
  289. return "[font-size: 14px]" + target.dataItem.category + ": " + target.dataItem.values.value.percent.toFixed(1) + "%";
  290. }
  291. return text;
  292. });
  293. pieSeries.colors.list = [
  294. am4core.color('rgb(171, 51, 49)'),
  295. am4core.color('rgb(34, 83, 149)'),
  296. am4core.color('rgb(79, 148, 65)'),
  297. am4core.color('rgb(217, 195, 105)'),
  298. am4core.color('rgb(142, 124, 180)'),
  299. am4core.color('rgb(211, 183, 144)'),
  300. am4core.color('rgb(83, 84, 84)'),
  301. am4core.color('rgb(229, 147, 152)')
  302. ];
  303. // Ensure labels have background
  304. // pieSeries.labels.template.background.fillOpacity = 1;
  305. console.log(pieSeries.labels.template)
  306. // Set label background color to match corresponding slice color
  307. pieSeries.labels.template.adapter.add("background.fill", function (fill, target) {
  308. return target.dataItem.slice.fill;
  309. });
  310. // This creates initial animation
  311. pieSeries.hiddenState.properties.opacity = 1;
  312. pieSeries.hiddenState.properties.endAngle = -90;
  313. pieSeries.hiddenState.properties.startAngle = -90;
  314. // console.log('調位置')
  315. downloadButton.style.display = "inline-block";
  316. }
  317. // var colorEven='#288D97';
  318. // var colorOdd='#427D7E'
  319. function adjustColorBrightness(color, amount) {
  320. let usePound = false;
  321. if (color[0] == "#") {
  322. color = color.slice(1);
  323. usePound = true;
  324. }
  325. let num = parseInt(color, 16);
  326. let r = (num >> 16) + amount;
  327. let g = ((num >> 8) & 0x00FF) + amount;
  328. let b = (num & 0x0000FF) + amount;
  329. if (r > 255) r = 255;
  330. else if (r < 0) r = 0;
  331. if (g > 255) g = 255;
  332. else if (g < 0) g = 0;
  333. if (b > 255) b = 255;
  334. else if (b < 0) b = 0;
  335. return (usePound ? "#" : "") + (r << 16 | g << 8 | b).toString(16).padStart(6, '0');
  336. }
  337. // 柱狀圖
  338. function generateBarChart(key, dataArray) {
  339. $('#chartdiv').show();
  340. // var colorEven = document.getElementById('colorEven').value;
  341. // var colorOdd = document.getElementById('colorOdd').value;
  342. var baseColor = document.getElementById('borderColorInputBar').value;
  343. var categoryAxisFzValue = document.getElementById('XfontSizeBar').value;
  344. var valueAxisFzValue = document.getElementById('YfontSizeBar').value;
  345. var colorEven = am4core.color(baseColor);
  346. var colorOdd = adjustColorBrightness(baseColor, -20);
  347. chartDiv.style.fontFamily = "Arial, sans-serif";
  348. chartDiv.style.fontWeight = "900";
  349. bgImgelement.style.backgroundImage = chart_bgimg_url;
  350. chartWhitelement.style.background = "rgba(255,255,255,0.5)"
  351. console.log('labelDependent', labelDependent);
  352. // Themes begin
  353. am4core.useTheme(am4themes_animated);
  354. // Themes end
  355. // Create chart instance
  356. var chart = am4core.create("chartdiv", am4charts.XYChart3D);
  357. console.log('判斷資料', dataArray);
  358. chart.data = dataArray;
  359. chart.angle = 30; // 圖表角度
  360. chart.depth = 25; // 圖表深度
  361. let categoryAxis = chart.xAxes.push(new am4charts.CategoryAxis());
  362. categoryAxis.dataFields.category = "x";
  363. categoryAxis.renderer.labels.template.rotation = 0;
  364. categoryAxis.renderer.labels.template.hideOversized = false;
  365. categoryAxis.renderer.minGridDistance = 20; // 間距
  366. // categoryAxis.renderer.labels.template.horizontalCenter = "left";
  367. // categoryAxis.renderer.labels.template.verticalCenter = "middle";
  368. // categoryAxis.tooltip.label.rotation = 90;
  369. // categoryAxis.tooltip.label.horizontalCenter = "right";
  370. // categoryAxis.tooltip.label.verticalCenter = "middle";
  371. // label 換行
  372. let label = categoryAxis.renderer.labels.template;
  373. label.wrap = true;
  374. if (dataArray.length > 5) {
  375. console.log('資料長度5')
  376. label.maxWidth = 50;
  377. } else {
  378. label.maxWidth = 100;
  379. console.log('資料長度<5')
  380. }
  381. // x軸字體大小
  382. categoryAxis.renderer.labels.template.fontSize = categoryAxisFzValue;
  383. categoryAxis.renderer.cellEndLocation = 0.5; // 減少值可以增加間距
  384. let valueAxis = chart.yAxes.push(new am4charts.ValueAxis());
  385. valueAxis.title.text = labelDependent; // Y軸
  386. valueAxis.title.fontWeight = "bold";
  387. // y軸字體大小
  388. valueAxis.renderer.labels.template.fontSize = valueAxisFzValue;
  389. // Create series
  390. var series = chart.series.push(new am4charts.ColumnSeries3D());
  391. series.dataFields.valueY = 'y';
  392. series.dataFields.categoryX = "x";
  393. series.name = "y";
  394. series.tooltipText = "{categoryX}: [bold]{valueY}[/]";
  395. series.columns.template.fillOpacity = .8;
  396. let columnTemplate = series.columns.template;
  397. columnTemplate.strokeWidth = 2;
  398. columnTemplate.strokeOpacity = 1;
  399. columnTemplate.stroke = am4core.color("#FFFFFF");
  400. // columnTemplate.adapter.add("fill", function (fill, target) {
  401. // return chart.colors.getIndex(target.dataItem.index);
  402. // })
  403. // 設置基數和偶數顏色
  404. columnTemplate.adapter.add("fill", function (fill, target) {
  405. return target.dataItem.index % 2 === 0 ? am4core.color(colorEven) : am4core.color(colorOdd);
  406. });
  407. columnTemplate.adapter.add("stroke", function (stroke, target) {
  408. return chart.colors.getIndex(target.dataItem.index);
  409. })
  410. // // 加上白色線條
  411. // series.columns.template.events.on("validated", function (event) {
  412. // let column = event.target;
  413. // let whiteLine = column.createChild(am4core.Line);
  414. // whiteLine.stroke = am4core.color("#ffffff");
  415. // whiteLine.strokeWidth = 1.3; // 線條寬度
  416. // whiteLine.strokeOpacity = 0.5;// 透明度
  417. // whiteLine.x1 = column.pixelWidth / 1;
  418. // whiteLine.y1 = 0;
  419. // whiteLine.x2 = column.pixelWidth / 1;
  420. // whiteLine.y2 = column.pixelHeight;
  421. // });
  422. chart.cursor = new am4charts.XYCursor();
  423. chart.cursor.lineX.strokeOpacity = 0;
  424. chart.cursor.lineY.strokeOpacity = 0;
  425. categoryAxis.renderer.grid.template.strokeOpacity = 0; // 隱藏 X 軸
  426. // valueAxis.renderer.grid.template.strokeOpacity = 0; // 隱藏 Y 軸
  427. // valueAxis.renderer.line.strokeOpacity = 0;
  428. // LineSeries 底部線條
  429. var lineSeries = chart.series.push(new am4charts.LineSeries());
  430. lineSeries.dataFields.valueY = "bottom";
  431. lineSeries.dataFields.categoryX = "0";
  432. lineSeries.stroke = am4core.color("#FFFFFF")
  433. lineSeries.strokeWidth = 2;
  434. lineSeries.strokeOpacity = 1
  435. var bottomData = [];
  436. for (var i = 0; i < dataArray.length; i++) {
  437. bottomData.push({ "x": dataArray[i].x, "bottom": 0 });
  438. }
  439. lineSeries.data = bottomData;
  440. downloadButton.style.display = "inline-block";
  441. // 底部線條
  442. // let rectElements = document.querySelectorAll("rect");
  443. // // let widthValue = 0;
  444. // let fifthRectElement = rectElements[3];
  445. // // fifthRectElement.style.position = "relative";
  446. // setTimeout(() => {
  447. // let width = fifthRectElement.getAttribute("width");
  448. // // widthValue = parseFloat(width);
  449. // console.log('rectElements', rectElements);
  450. // console.log('fifthRectElement', fifthRectElement);
  451. // console.log('width', width);
  452. // let line = document.createElement("div");
  453. // line.style.position = "absolute";
  454. // line.style.bottom = "162px";
  455. // line.style.right = "40px";
  456. // line.style.width = `${parseFloat(width)}px`;
  457. // line.style.height = "2px";
  458. // line.style.backgroundColor = "#000000";
  459. // document.getElementById("chartdiv").appendChild(line);
  460. // }, 10)
  461. // end am4core.ready()
  462. }
  463. var downloadButton = document.getElementById("downloadButton");
  464. // downloadButton.style.display = 'none';
  465. // 添加點擊事件監聽器
  466. downloadButton.addEventListener('click', function () {
  467. setTimeout(function () {
  468. html2canvas(document.getElementById('data_chart_box')).then(function (canvas) {
  469. // // 獲取圖片資料 URL
  470. // var imageData = canvasPng.toDataURL("image/png");
  471. // // 創建下載連結
  472. // var link = document.createElement('a');
  473. // link.download = 'chart.png'; // 下載的檔案名稱
  474. // link.href = imageData; // 圖片資料 URL
  475. // // 模擬點擊下載連結
  476. // link.click();
  477. // 創建一個&lt;a&gt;元素
  478. const link = document.createElement('a');
  479. // 將 Canvas 轉換為 Data URL
  480. link.href = canvas.toDataURL('image/png');
  481. // 設置下載文件名
  482. link.download = 'chart.png';
  483. // 模擬點擊下載
  484. link.click();
  485. });
  486. }, 1000); // 等待 1 秒钟
  487. });
  488. var pieChartColors = [
  489. 'rgb(171, 51, 49)',
  490. 'rgb(34, 83, 149)',
  491. 'rgb(79, 148, 65)',
  492. 'rgb(217, 195, 105)',
  493. 'rgb(142, 124, 180)',
  494. 'rgb(211, 183, 144)',
  495. 'rgb(83, 84, 84)',
  496. 'rgb(229, 147, 152)'
  497. ];
  498. function createChartDoughnut2(data, labels) {
  499. const chartData = {
  500. type: 'outlabeledPie',
  501. data: {
  502. labels: labels,
  503. datasets: [
  504. {
  505. data: data,
  506. borderWidth: borderWidthValue,
  507. fill: false,
  508. backgroundColor: pieChartColors,
  509. },
  510. ],
  511. },
  512. options: {
  513. plugins: {
  514. legend: false,
  515. outlabels: {
  516. text: '%l %p',
  517. color: 'white',
  518. stretch: 35,
  519. font: {
  520. resizable: true,
  521. family: 'Arial',
  522. size: 48,
  523. weight: 'bold',
  524. style: 'italic',
  525. },
  526. },
  527. },
  528. },
  529. };
  530. const devicePixelRatio = 4;
  531. var chartUrl = `https://quickchart.io/chart?c=${encodeURIComponent(JSON.stringify(chartData))}&devicePixelRatio=${devicePixelRatio}&f=png&fontsize=20`;
  532. // 获取目标 div 元素
  533. const targetDiv = document.getElementById('data_chartJs_box');
  534. // 创建一个 img 元素来显示图表
  535. const chartImg = document.createElement('img');
  536. chartImg.src = chartUrl;
  537. chartImg.classList.add('outlabeled_img');
  538. // 清空目标 div 元素
  539. targetDiv.innerHTML = '';
  540. // 将图表 img 元素插入到目标 div 中
  541. targetDiv.appendChild(chartImg);
  542. console.log(chart_bgimg_url);
  543. bgImgelement.style.backgroundImage = chart_bgimg_url;
  544. chartWhitelement.style.background = "rgba(255,255,255,0.5)"
  545. }
  546. // 版型二源餅圖
  547. // // 创建 Chart.js 图表
  548. function createChartDoughnut(chartType, data, labels) {
  549. $('#textToChart').show();
  550. canvasPng.style.maxWidth = '450px';
  551. canvasPng.style.maxHeight = '450px';
  552. var windowWidth = window.innerWidth || document.documentElement.clientWidth;
  553. var canvasWidth = Math.min(500, windowWidth); // 限制最大宽度为 500px
  554. canvasPng.style.width = canvasWidth + 'px'; // 设置 canvas 宽度
  555. canvasPng.style.marginLeft = 'auto'; // 左外边距自动计算
  556. canvasPng.style.marginRight = 'auto'; // 右外边距自动计算
  557. var ctx = document.getElementById("textToChart").getContext('2d');
  558. myChart = new Chart(ctx, {
  559. type: chartType,
  560. data: {
  561. labels: labels,
  562. datasets: [{
  563. strokeColor: "rgba(220,220,220,1)",
  564. StrokeWidth: 5,
  565. data: data,
  566. borderWidth: borderWidthValue,
  567. pointRadius: 0,
  568. pointBorderColor: '#fff',
  569. pointBorderWidth: 3,
  570. pointHoverRadius: 0,
  571. fill: false,
  572. backgroundColor: pieChartColors,
  573. // barPercentage: 0.5,
  574. // categoryPercentage: 0.5
  575. }]
  576. },
  577. options: {
  578. // responsive: true, // 啟用響應式
  579. maintainAspectRatio: true,
  580. responsive: true,
  581. aspectRatio: 1,
  582. plugins: {
  583. legend: {
  584. display: false,
  585. },
  586. datalabels: {
  587. color: '#fff', // 数据标签的颜色
  588. anchor: 'end', // 数据标签的位置
  589. align: 'start', // 数据标签的对齐方式
  590. font: {
  591. size: 14, // 数据标签的字体大小
  592. },
  593. }
  594. },
  595. scales: {
  596. x: {
  597. display: false, // 显示 x 轴
  598. grid: {
  599. display: false,
  600. lineWidth: 5,
  601. color: '#584B3D'
  602. },
  603. ticks: {
  604. textStrokeColor: '#fff',
  605. textStrokeWidth: 5,
  606. font: {
  607. display: false,
  608. family: 'Arial', // 设置字体
  609. size: XfontSizeValue, // 设置字体大小
  610. weight: 'bold', // 设置字体粗细
  611. fontColor: 'rgba(255,255,255,0.8)', // X-axis font color
  612. shadowColor: 'rgba(0, 0, 0, 0.5)', // Shadow color
  613. shadowBlur: 10, // Shadow blur level
  614. shadowOffsetX: 5, // Horizontal shadow offset
  615. shadowOffsetY: 5
  616. },
  617. },
  618. },
  619. y: {
  620. display: false,
  621. beginAtZero: false,
  622. grid: {
  623. display: false,
  624. lineWidth: 5,
  625. color: '#584B3D'
  626. },
  627. ticks: {
  628. textStrokeColor: '#fff',
  629. textStrokeWidth: 5,
  630. font: {
  631. family: 'Arial', // 設置字體
  632. size: XfontSizeValue, // 設置字體大小
  633. weight: 'bold', // 設置字體粗細
  634. color: 'rgba(255,255,255,0.8)', // Y-axis 字體顏色
  635. shadowColor: 'rgba(0, 0, 0, 0.5)', // 陰影顏色
  636. shadowBlur: 10, // 陰影模糊級別
  637. shadowOffsetX: 5, // 水平陰影偏移
  638. shadowOffsetY: 5 // 垂直陰影偏移
  639. },
  640. }
  641. }
  642. },
  643. layout: {
  644. padding: {
  645. left: 50, // 调整图表左边距
  646. right: 50, // 调整图表右边距
  647. top: 10,
  648. bottom: 10,
  649. }
  650. },
  651. },
  652. });
  653. console.log(chart_bgimg_url);
  654. bgImgelement.style.backgroundImage = chart_bgimg_url;
  655. chartWhitelement.style.background = "rgba(255,255,255,0.5)"
  656. }
  657. var chartJsBox = document.getElementById('data_chartJs_box');
  658. function createTable(dataArray, unit, Label_dependent_variable, Label_independent_variable,) {
  659. $('#chartdiv').hide();
  660. $('#textToChart').hide();
  661. var table = document.createElement('table');
  662. table.classList.add('table', 'table_template', 'dynamic-table'); // 添加 Bootstrap 的 table 样式,如果你在使用 Bootstrap
  663. // 创建表头
  664. var thead = table.createTHead();
  665. var headerRow = thead.insertRow();
  666. // Object.keys(dataArray[0]).forEach(function (key) {
  667. // var header = headerRow.insertCell();
  668. // header.textContent = key;
  669. // });
  670. var yearHeader = headerRow.insertCell();
  671. yearHeader.textContent = Label_independent_variable;
  672. var avgPriceHeader = headerRow.insertCell();
  673. avgPriceHeader.textContent = Label_dependent_variable;
  674. // 创建表格主体
  675. var tbody = table.createTBody();
  676. dataArray.forEach(function (item) {
  677. console.log(item)
  678. var row = tbody.insertRow();
  679. // var cell1 = row.insertCell();
  680. // cell1.textContent = item.year;
  681. // cell1.classList.add('year-class'); // 为年份单元格添加类
  682. // var cell2 = row.insertCell();
  683. Object.keys(item).forEach(function (key, index) {
  684. var cell = row.insertCell();
  685. if (index === 0) { // If it's the first cell, add 'year-class'
  686. cell.textContent = item[key];
  687. cell.classList.add('year-class');
  688. } else { // Otherwise, add 'average-class'
  689. if (key === 'Average_Close') {
  690. cell.textContent = item[key].toFixed(2) + unit;
  691. } else {
  692. // cell.textContent = item[key];
  693. cell.textContent = item[key].toFixed(2) + unit;
  694. }
  695. cell.classList.add('average-class');
  696. }
  697. });
  698. // console.log(item.avg_price.toFixed(2))
  699. // cell.textContent = item[key].toFixed(2) + unit;
  700. // cell2.classList.add('average-class'); // 为年份单元格添加类
  701. });
  702. // 获取包含表格的 div 元素
  703. bgImgelement.style.backgroundImage = chart_bgimg_url;
  704. img_box.style.bottom = '60px';
  705. img_box.style.right = '5px';
  706. document.getElementById('img_box_url').style.width = "180px";
  707. // chartWhitelement.style.background = "rgba(255,255,255,0.5)"
  708. // 将表格添加到指定的 div 元素中
  709. chartJsBox.appendChild(table);
  710. }
  711. // 版型一折線圖
  712. // // 创建 Chart.js 图表
  713. function createChart(chartType, data, labels) {
  714. $('#textToChart').show();
  715. canvasPng.style.maxWidth = '';
  716. canvasPng.style.maxHeight = '';
  717. ctx = document.getElementById("textToChart");
  718. myChart = new Chart(ctx, {
  719. type: chartType,
  720. data: {
  721. labels: labels,
  722. datasets: [{
  723. strokeColor: "rgba(220,220,220,1)",
  724. StrokeWidth: 5,
  725. data: data,
  726. borderWidth: borderWidthValue,
  727. pointRadius: 0,
  728. pointBorderColor: '#fff',
  729. pointBorderWidth: 3,
  730. pointHoverRadius: 0,
  731. fill: false,
  732. backgroundColor: chartColor,
  733. borderColor: chartColor,
  734. // barPercentage: 0.5,
  735. // categoryPercentage: 0.5
  736. }]
  737. },
  738. options: {
  739. // responsive: true, // 啟用響應式
  740. maintainAspectRatio: false,
  741. plugins: {
  742. chart3d: {
  743. enabled: true, // 啟用 3D 插件
  744. alpha: 25, // 圖表繞 x 軸的旋轉角度
  745. beta: 25, // 圖表繞 y 軸的旋轉角度
  746. depth: 15 // 圖表的深度
  747. },
  748. // datalabels: {
  749. // formatter: function (value, context) {
  750. // // 添加单位
  751. // return value + ' ' + unit;
  752. // },
  753. // textStrokeColor: '#fff',
  754. // textStrokeWidth: 5,
  755. // color: '#584B3D',
  756. // font: {
  757. // size: YfontSizeValue,
  758. // },
  759. // anchor: 'end',
  760. // align: 'end',
  761. // },
  762. datalabels: null,
  763. // datalabels: data.length <= 10 ? {
  764. // formatter: function (value, context) {
  765. // // 添加单位
  766. // return value + ' ' + unit;
  767. // },
  768. // textStrokeColor: '#fff',
  769. // textStrokeWidth: 5,
  770. // color: '#584B3D',
  771. // font: {
  772. // size: YfontSizeValue,
  773. // },
  774. // anchor: 'end',
  775. // align: 'end',
  776. // } : null,
  777. customLabels: null,
  778. legend: {
  779. display: false,
  780. },
  781. // subtitle: {
  782. // display: true,
  783. // align: 'left',
  784. // position: 'top',
  785. // text: 'Custom Chart Subtitle'
  786. // },
  787. // afterDatasetsDraw(chart) {
  788. // var ctx = chart.ctx;
  789. // var xAxis = chart.scales.x;
  790. // var yAxis = chart.scales.y;
  791. // var dataj = myChart.data.datasets[0].data;
  792. // console.log('after', dataj)
  793. // ctx.save();
  794. // ctx.strokeStyle = '#000'; // 虚线颜色
  795. // ctx.lineWidth = 1; // 虚线宽度
  796. // ctx.setLineDash([5, 5]); // 设置虚线样式,[虚线段长度, 间隔长度]
  797. // dataj.forEach(function (value, index) {
  798. // var xPos = xAxis.getPixelForValue(labels[index]); // 获取 x 轴位置
  799. // var yPos = yAxis.getPixelForValue(value); // 获取 y 轴位置
  800. // // console.log(xPos)
  801. // // 绘制虚线
  802. // // ctx.beginPath();
  803. // // ctx.moveTo(xPos, yPos);
  804. // // ctx.lineTo(xPos, xAxis.bottom);
  805. // // ctx.stroke();
  806. // var xLineEnd = Math.min(yPos, yAxis.bottom);
  807. // // console.log('第' + index + '條線', xPos, yPos, 'xLineEnd', xLineEnd, 'yAxis.getPixelForValue(value)', yAxis.getPixelForValue(value));
  808. // // console.log('yAxis.getPixelForValue(value)', yAxis.getPixelForValue(value))
  809. // // 绘制虚线
  810. // ctx.beginPath();
  811. // ctx.moveTo(xPos, yAxis.getPixelForValue(value));
  812. // ctx.lineTo(xPos, xAxis.top);
  813. // ctx.stroke();
  814. // // 添加日期标签
  815. // ctx.fillStyle = '#000'; // 文字颜色
  816. // ctx.textAlign = 'center';
  817. // // ctx.fillText(labels[index], xPos, yAxis.bottom + 20); // 将日期标签绘制在虚线下方
  818. // });
  819. // ctx.restore();
  820. // }
  821. },
  822. scales: {
  823. x: {
  824. display: displayXaxes, // 显示 x 轴
  825. grid: {
  826. display: false,
  827. lineWidth: 5,
  828. color: '#584B3D'
  829. },
  830. ticks: {
  831. textStrokeColor: '#fff',
  832. textStrokeWidth: 5,
  833. font: {
  834. display: false,
  835. family: 'Arial', // 设置字体
  836. size: XfontSizeValue, // 设置字体大小
  837. weight: 'bold', // 设置字体粗细
  838. fontColor: 'rgba(255,255,255,0.8)', // X-axis font color
  839. shadowColor: 'rgba(0, 0, 0, 0.5)', // Shadow color
  840. shadowBlur: 10, // Shadow blur level
  841. shadowOffsetX: 5, // Horizontal shadow offset
  842. shadowOffsetY: 5
  843. },
  844. },
  845. },
  846. y: {
  847. display: true,
  848. beginAtZero: false,
  849. grid: {
  850. grid: {
  851. display: true, // 显示 y 轴网格线
  852. lineWidth: 1, // 网格线宽度
  853. color: '#C0C5CC' // 网格线颜色
  854. },
  855. },
  856. ticks: {
  857. textStrokeColor: '#fff',
  858. textStrokeWidth: 5,
  859. font: {
  860. family: 'Arial', // 設置字體
  861. size: XfontSizeValue, // 設置字體大小
  862. weight: 'bold', // 設置字體粗細
  863. color: 'rgba(255,255,255,0.8)', // Y-axis 字體顏色
  864. shadowColor: 'rgba(0, 0, 0, 0.5)', // 陰影顏色
  865. shadowBlur: 10, // 陰影模糊級別
  866. shadowOffsetX: 5, // 水平陰影偏移
  867. shadowOffsetY: 5 // 垂直陰影偏移
  868. },
  869. }
  870. }
  871. },
  872. layout: {
  873. padding: {
  874. left: 50, // 调整图表左边距
  875. right: 50, // 调整图表右边距
  876. top: 40,
  877. bottom: 10,
  878. }
  879. },
  880. },
  881. });
  882. // 注册 afterDraw 事件
  883. // Chart.register({
  884. // id: 'afterDraw',
  885. // afterDraw: function (chart) {
  886. // // console.log('處發', chart)
  887. // // 在这里添加你的绘制代码
  888. // var ctx = chart.ctx;
  889. // var xAxis = chart.scales.x;
  890. // var yAxis = chart.scales.y;
  891. // var dataj = myChart.data.datasets[0].data;
  892. // console.log('after', dataj)
  893. // ctx.save();
  894. // ctx.strokeStyle = '#000'; // 虚线颜色
  895. // ctx.lineWidth = 1; // 虚线宽度
  896. // ctx.setLineDash([5, 5]); // 设置虚线样式,[虚线段长度, 间隔长度]
  897. // dataj.forEach(function (value, index) {
  898. // var xPos = xAxis.getPixelForValue(labels[index]); // 获取 x 轴位置
  899. // var yPos = yAxis.getPixelForValue(value); // 获取 y 轴位置
  900. // // console.log(xPos)
  901. // // 绘制虚线
  902. // // ctx.beginPath();
  903. // // ctx.moveTo(xPos, yPos);
  904. // // ctx.lineTo(xPos, xAxis.bottom);
  905. // // ctx.stroke();
  906. // var xLineEnd = Math.min(yPos, yAxis.bottom);
  907. // // console.log('第' + index + '條線', xPos, yPos, 'xLineEnd', xLineEnd, 'yAxis.getPixelForValue(value)', yAxis.getPixelForValue(value));
  908. // // console.log('yAxis.getPixelForValue(value)', yAxis.getPixelForValue(value))
  909. // // 绘制虚线
  910. // ctx.beginPath();
  911. // ctx.moveTo(xPos, yAxis.getPixelForValue(value));
  912. // ctx.lineTo(xPos, xAxis.top);
  913. // ctx.stroke();
  914. // // 添加日期标签
  915. // ctx.fillStyle = '#000'; // 文字颜色
  916. // ctx.textAlign = 'center';
  917. // // ctx.fillText(labels[index], xPos, yAxis.bottom + 20); // 将日期标签绘制在虚线下方
  918. // });
  919. // ctx.restore();
  920. // }
  921. // });
  922. console.log(chart_bgimg_url);
  923. bgImgelement.style.backgroundImage = chart_bgimg_url;
  924. chartWhitelement.style.background = "rgba(255,255,255,0.5)";
  925. downloadButton.style.display = "inline-block";
  926. }
  927. // createChart(chartType);
  928. // createChart(chartType)
  929. const ChartOptions = document.querySelectorAll('input[name="ChartOptions"]');
  930. ChartOptions.forEach(button => {
  931. button.addEventListener('click', function () {
  932. // console.log(this.value);
  933. chartType = this.value;
  934. console.log(chartType);
  935. if (myChart !== null) {
  936. myChart.destroy();
  937. data = [];
  938. labels = [];
  939. }
  940. if (chartType === 'line') {
  941. $('#chartdiv').hide();
  942. generateChart(dataArray);
  943. } else {
  944. $('#textToChart').hide();
  945. extractAndGenerateChart(dataArray);
  946. }
  947. // createChart(chartType, data, labels);
  948. });
  949. });
  950. // 表格字體
  951. var fontSizeInput = document.getElementById('table_fontSize');
  952. // 添加事件监听器
  953. fontSizeInput.addEventListener('input', function () {
  954. // 获取输入框的值
  955. var fontSize = fontSizeInput.value;
  956. // 获取动态创建的表格元素
  957. var dynamicTable = document.querySelector('.dynamic-table');
  958. // 如果表格存在,则调整其字体大小
  959. if (dynamicTable) {
  960. dynamicTable.style.fontSize = fontSize + 'px';
  961. }
  962. });
  963. // 是否顯示point
  964. var togglePoints = document.getElementById('togglePoints');
  965. togglePoints.addEventListener('change', function () {
  966. console.log('checked')
  967. if (this.checked) {
  968. myChart.data.datasets[0].pointRadius = 5;
  969. myChart.data.datasets[0].pointHoverRadius = 8;
  970. } else {
  971. myChart.data.datasets[0].pointRadius = 0;
  972. myChart.data.datasets[0].pointHoverRadius = 0;
  973. }
  974. myChart.update();
  975. });
  976. // 單位標題
  977. // =========================
  978. var unitInput = document.getElementById('unit_data');
  979. unitInput.addEventListener('input', function () {
  980. unit = unitInput.value;
  981. // 重新渲染图表
  982. myChart.update();
  983. });
  984. // ==========================
  985. // y軸字體大小-折線圖
  986. // ==========================
  987. var YfontSize = document.getElementById('YfontSize');
  988. YfontSize.addEventListener('input', function () {
  989. YfontSizeValue = YfontSize.value;
  990. if (myChart) {
  991. myChart.destroy();
  992. }
  993. createChart(chartType, data, labels);
  994. });
  995. // ==========================
  996. // x軸字體大小-折線圖
  997. // ==========================
  998. var XfontSize = document.getElementById('XfontSize');
  999. XfontSize.addEventListener('input', function () {
  1000. XfontSizeValue = XfontSize.value;
  1001. console.log(XfontSizeValue)
  1002. if (myChart) {
  1003. myChart.destroy();
  1004. }
  1005. createChart(chartType, data, labels);
  1006. });
  1007. // ==========================
  1008. // x軸字體大小-柱狀圖
  1009. // ==========================
  1010. var XfontSizeBar = document.getElementById('XfontSizeBar');
  1011. XfontSizeBar.addEventListener('input', function () {
  1012. extractAndGenerateChart(dataArray);
  1013. });
  1014. // ==========================
  1015. // y軸字體大小-柱狀圖
  1016. // ==========================
  1017. var YfontSizeBar = document.getElementById('YfontSizeBar');
  1018. YfontSizeBar.addEventListener('input', function () {
  1019. extractAndGenerateChart(dataArray);
  1020. });
  1021. // ==========================
  1022. // 線條顏色-柱狀圖
  1023. // =========================
  1024. const colorInputBar = document.getElementById('borderColorInputBar');
  1025. // 添加事件监听器,当颜色选择发生变化时触发
  1026. colorInputBar.addEventListener('input', function () {
  1027. extractAndGenerateChart(dataArray);
  1028. });
  1029. // =========================
  1030. // 線條粗細
  1031. // =========================
  1032. var rangeInput = document.getElementById('borderWidthRange');
  1033. var rangeInputSpan = document.getElementById('borderWidthRangeValue');
  1034. var borderWidthValue;
  1035. rangeInputSpan.textContent = rangeInput.value;
  1036. // 添加事件监听器,当滑动条的值发生改变时更新显示的值
  1037. rangeInput.addEventListener('input', function () {
  1038. // 获取滑动条的当前值
  1039. borderWidthValue = rangeInput.value;
  1040. console.log(borderWidthValue);
  1041. rangeInputSpan.textContent = borderWidthValue;
  1042. if (myChart) {
  1043. myChart.destroy();
  1044. }
  1045. createChart(chartType, data, labels);
  1046. // myChart.data.datasets[0].borderWidth = borderWidthValue;
  1047. });
  1048. // =========================
  1049. // 線條顏色-折線圖
  1050. // =========================
  1051. const colorInput = document.getElementById('borderColorInput');
  1052. // 添加事件监听器,当颜色选择发生变化时触发
  1053. colorInput.addEventListener('input', function () {
  1054. // 获取当前选择的颜色值
  1055. chartColor = colorInput.value;
  1056. if (myChart) {
  1057. myChart.destroy();
  1058. }
  1059. console.log(chartColor);
  1060. createChart(chartType, data, labels);
  1061. });
  1062. // =========================
  1063. // 模板樣式
  1064. // =========================
  1065. // JavaScript
  1066. document.addEventListener("DOMContentLoaded", function () {
  1067. // 獲取所有帶有 templateImg class 的圖像元素
  1068. var templateImgs = document.querySelectorAll('.templateImg');
  1069. // 為每個圖像元素添加點擊事件監聽器
  1070. templateImgs.forEach(function (img) {
  1071. img.addEventListener('click', function () {
  1072. // 在點擊時印出圖像元素的 value 屬性值
  1073. console.log(this.getAttribute('value'));
  1074. });
  1075. });
  1076. });
  1077. // =========================
  1078. var bgImgelement = document.getElementById('data_chart_box');
  1079. var chartWhitelement = document.getElementById('data_chartJs_box');
  1080. // 背景樣式
  1081. // =========================
  1082. // JavaScript
  1083. document.addEventListener("DOMContentLoaded", function () {
  1084. // 獲取所有帶有 templateImg class 的圖像元素
  1085. var bgImgs = document.querySelectorAll('.bgImg');
  1086. // 為每個圖像元素添加點擊事件監聽器
  1087. bgImgs.forEach(function (img) {
  1088. img.addEventListener('click', function () {
  1089. // 在點擊時印出圖像元素的 value 屬性值
  1090. console.log(this.getAttribute('value'));
  1091. var bgImgUrl = this.getAttribute('value');
  1092. chart_bgimg_url = 'url(' + bgImgUrl + ')';
  1093. bgImgelement.style.backgroundImage = chart_bgimg_url;
  1094. // bgImgelement.style.backgroundSize = 'cover'; // 調整背景圖片大小
  1095. // bgImgelement.style.backgroundPosition = 'center'; // 調整背景圖片位置
  1096. // bgImgelement.style.backgroundRepeat = 'no-repeat'; // 調整背景圖片重複
  1097. });
  1098. });
  1099. });
  1100. // =========================
  1101. const radioButtons = document.querySelectorAll('input[name="inlineRadioOptions"]');
  1102. var chartTitle = document.querySelector('.chart_title');
  1103. radioButtons.forEach(button => {
  1104. button.addEventListener('click', function () {
  1105. if (this.value === '0') {
  1106. chartTitle.style.textAlign = 'left';
  1107. } else if (this.value === '1') {
  1108. chartTitle.style.textAlign = 'center';
  1109. } else if (this.value === '2') {
  1110. chartTitle.style.textAlign = 'right';
  1111. }
  1112. });
  1113. });
  1114. var keywordInput = document.getElementById('title_data');
  1115. // 初始时将输入框的值设置为标题的文本内容
  1116. keywordInput.value = chartTitle.textContent;
  1117. // 监听输入框的输入事件,实现内容同步更新
  1118. keywordInput.addEventListener('input', function () {
  1119. chartTitle.textContent = this.value;
  1120. });
  1121. // 標題字體大小
  1122. // ==========================
  1123. var TitlefontSize = document.getElementById('TitlefontSize');
  1124. TitlefontSize.addEventListener('input', function () {
  1125. var TitlefontSizeValue = TitlefontSize.value;
  1126. chartTitle.style.fontSize = TitlefontSizeValue + 'px';;
  1127. });
  1128. // ==========================
  1129. let labelDependent = ""; // 圖表左側 Label
  1130. function get_data(input_text_value) {
  1131. inputField.value = "";
  1132. apiLoading();
  1133. var existingTable = chartJsBox.querySelector('table');
  1134. downloadButton.style.display = "none";
  1135. if (chartDiv.childElementCount != 0) {
  1136. data = [];
  1137. labels = [];
  1138. console.log('已存在')
  1139. chartTitle.textContent = "";
  1140. bgImgelement.style.backgroundImage = "";
  1141. chartWhitelement.style.background = "";
  1142. document.getElementById('img_box_url').src = "";
  1143. }
  1144. if (existingTable) {
  1145. chartJsBox.removeChild(existingTable);
  1146. chartTitle.textContent = "";
  1147. bgImgelement.style.backgroundImage = "";
  1148. chartWhitelement.style.background = "";
  1149. document.getElementById('img_box_url').src = "";
  1150. }
  1151. if (myChart) {
  1152. data = [];
  1153. labels = [];
  1154. chartTitle.textContent = "";
  1155. bgImgelement.style.backgroundImage = "";
  1156. chartWhitelement.style.background = "";
  1157. myChart.destroy();
  1158. document.getElementById('img_box_url').src = "";
  1159. }
  1160. axios.get('https://cmm.ai:8080/answer?question=' + input_text_value)
  1161. .then(response => {
  1162. apiHideLoading();
  1163. // 在這裡處理成功獲取 JSON 的情況
  1164. console.log(response);
  1165. var chart_info = response.data.chart_info.Title;
  1166. chartType = response.data.chart_info.Chart_type;
  1167. var finance_img_url = response.data.imageUrl_info.imageUrl;
  1168. if (response.data.imageUrl_info != null) {
  1169. console.log(finance_img_url);
  1170. document.getElementById('img_box_url').src = finance_img_url;
  1171. }
  1172. // switch (chartType) {
  1173. // case "line":
  1174. // document.getElementById("inlineRadio4").checked = true; // 折线图
  1175. // break;
  1176. // case "bar":
  1177. // document.getElementById("inlineRadio5").checked = true; // 柱状图
  1178. // labelDependent = response.data.chart_info.Label_dependent_variable;
  1179. // break;
  1180. // case "pie":
  1181. // document.getElementById("inlineRadio6").checked = true; // 圆饼图
  1182. // break;
  1183. // case "table":
  1184. // document.getElementById("inlineRadio7").checked = true; // 表格
  1185. // break;
  1186. // default:
  1187. // // 默认情况
  1188. // }
  1189. keywordInput.value = chart_info;
  1190. chartTitle.textContent = chart_info;
  1191. unit = response.data.chart_info.Unit_of_dependent_variable;
  1192. var Label_dependent_variable = response.data.chart_info.Label_dependent_variable;
  1193. var Label_independent_variable = response.data.chart_info.Label_independent_variable;
  1194. unit_data.value = response.data.chart_info.Unit_of_dependent_variable;
  1195. dataArray = response.data.data;
  1196. if (chartType === "table") {
  1197. createTable(dataArray, unit, Label_dependent_variable, Label_independent_variable);
  1198. // document.getElementById('img_box_url').src = "";
  1199. } else if (chartType === "bar") {
  1200. console.log('圖表類型bar')
  1201. $('#textToChart').hide();
  1202. extractAndGenerateChart(dataArray);
  1203. } else if (chartType === "doughnut") {
  1204. $('#textToChart').hide();
  1205. generatePieChart(dataArray)
  1206. } else {
  1207. $('#chartdiv').hide();
  1208. generateChart(dataArray);
  1209. }
  1210. // generateChart(dataArray);
  1211. })
  1212. .catch(error => {
  1213. apiHideLoading();
  1214. // 在這裡處理請求失敗的情況
  1215. console.error('發生錯誤:', error);
  1216. });
  1217. }
  1218. $(document).ready(function () {
  1219. $('#dataTable').DataTable();
  1220. });
  1221. function resizeChart() {
  1222. if (myChart) {
  1223. myChart.resize();
  1224. }
  1225. }
  1226. document.addEventListener('visibilitychange', function () {
  1227. console.log('Visibility changed:', document.visibilityState);
  1228. if (document.visibilityState === 'visible') {
  1229. resizeChart();
  1230. }
  1231. });
  1232. // 监听窗口resize事件
  1233. window.addEventListener('resize', resizeChart);
  1234. var setting_button = document.getElementById('chart_seeting_button');
  1235. var closeButton = document.getElementById('style_setting_close');
  1236. var closeButton_table = document.getElementById('style_setting_close_table');
  1237. // var borderSetting = document.getElementById('borderSetting');
  1238. var lineChartSetting = document.getElementById('lineChartSetting');
  1239. var barChartSetting = document.getElementById('barChartSetting');
  1240. var table_setting = document.getElementById('table_setting');
  1241. var chart_category = document.getElementById('chart_category');
  1242. // 获取 chartDiv 元素
  1243. setting_button.addEventListener('click', () => {
  1244. console.log('setting_button')
  1245. if (myChart === null && !chartJsBox.querySelector('table') && chartDiv.childElementCount === 0) {
  1246. alert('請先生成圖表');
  1247. return
  1248. }
  1249. if (chartType === 'table') {
  1250. console.log('表格');
  1251. sidebar.classList.toggle('show');
  1252. sidebar.classList.toggle('hidden');
  1253. barChartSetting.style.display = 'none';
  1254. lineChartSetting.style.display = 'none';
  1255. table_setting.style.display = 'block';
  1256. chart_category.style.display = 'none';
  1257. } else if (chartType === "bar") {
  1258. console.log('柱狀圖')
  1259. sidebar.classList.toggle('show');
  1260. sidebar.classList.toggle('hidden');
  1261. barChartSetting.style.display = 'block';
  1262. lineChartSetting.style.display = 'none';
  1263. table_setting.style.display = 'none';
  1264. } else if (chartType === "doughnut") {
  1265. console.log('快捷功能圓餅圖')
  1266. sidebar.classList.toggle('show');
  1267. sidebar.classList.toggle('hidden');
  1268. barChartSetting.style.display = 'none';
  1269. lineChartSetting.style.display = 'none';
  1270. table_setting.style.display = 'none';
  1271. chart_category.style.display = 'none';
  1272. } else {
  1273. sidebar.classList.toggle('show');
  1274. sidebar.classList.toggle('hidden');
  1275. table_setting.style.display = 'none';
  1276. barChartSetting.style.display = 'none';
  1277. lineChartSetting.style.display = 'block';
  1278. }
  1279. });
  1280. closeButton.addEventListener('click', () => {
  1281. sidebar.classList.remove('show');
  1282. sidebar.classList.add('hidden');
  1283. });
  1284. const finance_options = [
  1285. { name: "原油油桶", imageUrl: "./img/finance/01.webp" },
  1286. { name: "黃金", imageUrl: "./img/finance/02.webp" },
  1287. { name: "房屋", imageUrl: "./img/finance/03.webp" },
  1288. { name: "車", imageUrl: "./img/finance/04.webp" },
  1289. { name: "股市", imageUrl: "./img/finance/05.webp" },
  1290. { name: "晶圓", imageUrl: "./img/finance/06.webp" },
  1291. { name: "TSMC 台積電", imageUrl: "./img/finance/07.webp" },
  1292. { name: "台幣", imageUrl: "./img/finance/08.webp" },
  1293. { name: "美金", imageUrl: "./img/finance/09.webp" },
  1294. { name: "購物車", imageUrl: "./img/finance/10.webp" },
  1295. { name: "美中貿易", imageUrl: "./img/finance/11.webp" },
  1296. { name: "世界地圖", imageUrl: "./img/finance/12.webp" },
  1297. { name: "小麥", imageUrl: "./img/finance/13.webp" },
  1298. { name: "玉米", imageUrl: "./img/finance/14.webp" },
  1299. { name: "智慧產線", imageUrl: "./img/finance/15.webp" }
  1300. ];
  1301. const selectOptions = document.getElementById('finance_options');
  1302. const selectOptions_table = document.getElementById('finance_options_table');
  1303. finance_options.forEach((option, index) => {
  1304. const optionElement = document.createElement('option');
  1305. optionElement.value = index + 1; // 值从 1 开始
  1306. optionElement.textContent = option.name;
  1307. optionElement.setAttribute('data-image-url', option.imageUrl); // 存储图片 URL
  1308. selectOptions.appendChild(optionElement);
  1309. });
  1310. selectOptions.addEventListener('change', function () {
  1311. const selectedOption = selectOptions.options[selectOptions.selectedIndex];
  1312. const imageUrl = selectedOption.getAttribute('data-image-url');
  1313. document.getElementById('img_box_url').src = imageUrl;
  1314. });
  1315. // finance_options.forEach((option, index) => {
  1316. // const optionElement = document.createElement('option');
  1317. // optionElement.value = index + 1; // 值从 1 开始
  1318. // optionElement.textContent = option.name;
  1319. // optionElement.setAttribute('data-image-url', option.imageUrl); // 存储图片 URL
  1320. // selectOptions_table.appendChild(optionElement);
  1321. // });
  1322. // selectOptions_table.addEventListener('change', function () {
  1323. // const selectedOption = selectOptions_table.options[selectOptions_table.selectedIndex];
  1324. // const imageUrl = selectedOption.getAttribute('data-image-url');
  1325. // document.getElementById('img_box_url').src = imageUrl;
  1326. // });
  1327. document.querySelectorAll('input[name="ChartOptions"]').forEach(function (radio) {
  1328. radio.addEventListener('change', function () {
  1329. // 檢查哪個單選按鈕被選中
  1330. if (this.value === 'line') {
  1331. // 如果選擇了折線圖,執行相應的操作
  1332. console.log("選擇了折線圖");
  1333. // 在這裡執行顯示折線圖的相關代碼
  1334. } else if (this.value === 'doughnut') {
  1335. // 如果選擇了柱狀圖,執行相應的操作
  1336. console.log("選擇了柱狀圖");
  1337. // 在這裡執行顯示柱狀圖的相關代碼
  1338. }
  1339. });
  1340. });