【问题标题】:Plot multiple graphs (Chart.js) from php loop for reading multiple files从 php 循环中绘制多个图表(Chart.js)以读取多个文件
【发布时间】: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...

【问题讨论】:

    标签: javascript php html chart.js laravel-blade


    【解决方案1】:

    好吧,事实证明我想出了解决问题的方法,当然,这得益于 stackoverflow 和 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 的。喜欢它!

    我必须解决它的主要帮助来源:

    一切都是正确的,经过一些调整,我已经开始运行了。所以,我要感谢开放代码社区!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-06-30
      • 1970-01-01
      • 1970-01-01
      • 2014-01-28
      • 1970-01-01
      相关资源
      最近更新 更多