从 php 循环中绘制多个图表(Chart.js)以读取多个文件
Posted
技术标签:
【中文标题】从 php 循环中绘制多个图表(Chart.js)以读取多个文件【英文标题】:Plot multiple graphs (Chart.js) from php loop for reading multiple files 【发布时间】:2022-01-06 04:21:32 【问题描述】:我一直在尝试使用来自 php 循环的 Chart.js 绘制多个图表。事实证明,Chart.js 只会将数据聚集在一个画布(第一个)中~其他的最终都是空白的。我觉得我很接近了,但还没有完全到那里......请有人帮助我吗?提前致谢!这是我的代码:
PS:画布空间出现在其他 div 中,虽然是空白的......所以这已经被清除了。
GraphPage.blade.php
@foreach ($items as $item)
<div class="table">
<div class="table-row">
$item->id
</div>
<div class="table-row">
$item->name
</div>
<div class="table-row">
<canvas class="bar-chart"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.4/Chart.min.js"></script>
<script type="text/javascript">
<?php
$i = 0;
$files = fopen("storage/" . $item->file, "r");
while(!feof($files))
$content = fgets($files);
$carray = explode(",", $content);
list($axisX, $axisY) = $carray;
$x[] = $axisX;
$y[] = $axisY;
$i++;
fclose($files);
$x_to_json = json_encode((array)$x);
$y_to_json = json_encode((array)$y);
?>
var x = <?php echo $x_to_json ?>;
var y = <?php echo $y_to_json ?>;
var ctx = document.getElementsByClassName('bar-chart');
var chartGraph = new Chart(ctx,
type: 'bar',
data:
labels: x,
datasets: [
label: "Bar Plot",
data: y,
]
);
</script>
</div>
</div>
@endforeach
这就是现在的结果...
All data aglomerated together in the first plot and nothing in the second...
【问题讨论】:
【参考方案1】:好吧,事实证明我想出了解决问题的方法,当然,这得益于 *** 和 YouTube 代码朋友的大力帮助。它的作用是,根据公共存储 url 中的逗号分隔值文件的数量(两列,没有标题 ~ 都可以调整),它会读取每个文件并为每个文件动态构建 Chart.js 图表其中。无论如何......如果它对任何人有任何帮助,这是我的代码和我使用的帮助来源:
在 view Blade 文件 (created-project.blade.php) 中,我在 foreach 循环中插入了来自 Chart.js 的画布和函数,在为了通过每个带有数据的文件运行它:
编辑 1: 在这里,来自 x 轴 的数据将被视为连续(线性)。但请确保已将 Chart.js 对应的脚本行添加到至少 3.0.0-beta.7。在早期版本中,这将不起作用...
@foreach ($mols as $mol)
<div class="flex flex-wrap m-1 w-5/6 lg:w-3/6">
<script>
var cont;
for(cont = 0; cont < !! $spectraCount !!; cont++)
window.addEventListener('load', setup);
async function setup()
const ctx = document.getElementById('myChart').insertAdjacenthtml("afterend","<canvas id='canvas"+cont+"' height='230'></canvas>");
const can_id="canvas"+cont;
const ctx2 = document.getElementById(can_id).getContext('2d');
const spectra = await getData();
window.can_id = new Chart(ctx2,
type: 'bar',
data:
datasets: [
label: "!! $mol->nome_molecula !!",
backgroundColor: "#0070bf",
data: spectra.xy,
barThickness: 3,
]
,
options:
scales:
x:
type: 'linear',
offset: false,
gridLines:
offsetGridLines: false,
);
window.can_id.update();
async function getData()
const response = await fetch('spectra/!! $mol->espectro !!');
const data = await response.text();
const xy = [];
const table = data.split('\n');
table.forEach(row =>
const columns = row.split(',');
xy.push('x': parseFloat(columns[0]), 'y': parseFloat(columns[1]));
);
return xy ;
var cont = cont + !! $spectraCount !!;
</script>
<canvas id="myChart" class="w-2 h-2"></canvas>
</div>
@endforeach
PS:var cont = cont + !! for JavaScript 循环结束时的 $spectraCount !! 是为了匹配计数的文件数,并完成 for 循环,该循环将再次重新启动每次通过刀片代码中的 foreach 循环。没有添加,它会导致页面中的图表数量增加一倍。
数据来自livewire 组件 (CreatedProject.php),包含以下代码:
<?php
namespace App\Http\Livewire;
use Livewire\Component;
use App\Models\Spectra;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Http;
class CreatedProject extends Component
public function render()
$metadados = DB::table('new_projects')->where('user_id', '=', auth()->user()->id)->orderBy('id_projeto', 'DESC')->first();
$mols = DB::table('new_molecules')->where('nome_projeto', '=', $metadados->nome_projeto)->get();
$spectra = DB::table('spectras')->where('nome_projeto', '=', $metadados->nome_projeto)->get();
$collection = collect($spectra);
$spectraCount = collect($spectra)->count();
return view('livewire.created-project', [
'metadados' => $metadados,
'mols' => $mols,
'collection' => $collection,
'spectraCount' => $spectraCount,
]);
进入数据库的文件已经在 livewire 组件 (NewProject.php) 中的 save() 函数中处理,代码如下:
public function save()
foreach ($this->espectro as $key => $value)
$mol_localpath = $this->espectro[$key]->storeAs('spectra', $mol_path);
$a = 0;
$files = fopen("spectra/" . $this->espectro[$key]->hashName(), "r");
while(!feof($files))
$content = fgets($files);
$carray = explode(",", $content);
list($mz1, $int1) = $carray;
$mz[] = $mz1;
$int[] = $int1;
$a++;
fclose($files);
Spectra::create([
'user_id' => auth()->user()->id,
'nome_projeto' => $this->nome_projeto,
'espectro' => $this->espectro[$key]->hashName(),
'mz' => $mz,
'int' => $int,
]);
$mz = [];
$int = [];
return redirect()->route('created-project');
当然,您不应该忘记将 Chart.js 主 CDN 脚本添加到视图文件中 HTML 的 head 标记中,或者按照您认为最好的方式安装它。
来自两个不同文本文件的示例结果:
PS2:我的 CSS 是基于 Tailwind 的。喜欢它!
我必须解决它的主要帮助来源:
这个系列来自 YouTube 上的 The Coding Train:https://youtu.be/RfMkdvN-23o
这篇来自***的帖子:Multiple dynamic line charts with chart.js | Js and html
这个人制作的视频(不是英文,但很好理解):https://youtu.be/sjF7A_uMbgc
Chart.js Github 中@etimberg 的问题答案:https://github.com/chartjs/Chart.js/issues/8233
他解释的小提琴:https://jsfiddle.net/ob0xc5u7/
一切都是正确的,经过一些调整,我已经开始运行了。所以,我要感谢开放代码社区!
【讨论】:
以上是关于从 php 循环中绘制多个图表(Chart.js)以读取多个文件的主要内容,如果未能解决你的问题,请参考以下文章
在 Django 模板中使用 for 循环显示多个 chart.js 图表
在Django模板中使用for循环显示多个chart.js图表
Chart.js 数据数组使用 PHP、MySQL。如何从 JSON 数组定义数据源?
使用 Chart.js 绘制图表,其中填充了每个 JsonRPC 获取的数据