Widget:Grafico: differenze tra le versioni

Da WikiLectio.
m test
Etichette: Ripristino manuale Annullato
m downgrade
Etichetta: Ripristino manuale
 
(38 versioni intermedie di uno stesso utente non sono mostrate)
Riga 1: Riga 1:
<!-- Widget:Grafico — Grafici domanda/offerta con Chart.js, fino a 4 serie + punto equilibrio opzionale -->
<includeonly>
<div id="chart_{{{id}}}" style="width:{{{width|600}}}px;height:{{{height|380}}}px;">
<div id="chartwrap_<!--{$id}-->"
   <canvas id="canvas_{{{id}}}" width="{{{width|600}}}" height="{{{height|380}}}"></canvas>
    style="width:<!--{$width|default:600}-->px;height:<!--{$height|default:380}-->px;">
</div>
   <canvas id="canvas_<!--{$id}-->"
          width="<!--{$width|default:600}-->"
          height="<!--{$height|default:380}-->"></canvas>


<!-- Chart.js (CDN) -->
  <!-- Config INI dentro <pre hidden> -->
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
  <pre id="cfg_<!--{$id}-->" hidden>
id=<!--{$id}-->
title=<!--{$title}-->
xTitle=<!--{$xTitle}-->
yTitle=<!--{$yTitle}-->
labels=<!--{$labels}-->


<script>
series1title=<!--{$series1title}-->
/* ===== Helpers ===== */
series1data=<!--{$series1data}-->
function parseCSVNumbers(str){
series1type=<!--{$series1type}-->
  if(!str) return [];
series1color=<!--{$series1color}-->
  return str.split(',').map(s=>{
    const n = Number(s.trim());
    return isNaN(n) ? null : n;
  });
}
function parseCSVStrings(str){
  if(!str) return [];
  return str.split(',').map(s=>s.trim());
}
function colorOrNull(s){ return (s && s.trim()) ? s.trim() : null; }
function numOrUndef(x){ var n = Number(x); return isNaN(n) ? undefined : n; }


/* ===== Costruzione grafico ===== */
series2title=<!--{$series2title}-->
(function(){
series2data=<!--{$series2data}-->
  var id = "{{{id}}}";
series2type=<!--{$series2type}-->
  var canvas = document.getElementById("canvas_{{{id}}}");
series2color=<!--{$series2color}-->
  if(!canvas){ return; }
  var ctx = canvas.getContext("2d");


  // Parametri base
series3title=<!--{$series3title}-->
  var labels = parseCSVStrings("{{{labels|0,2,4,6,8,10}}}");
series3data=<!--{$series3data}-->
  var chartTitle = "{{{title|}}}";
series3type=<!--{$series3type}-->
  var xTitle = "{{{xTitle|Quantità di appartamenti}}}";
series3color=<!--{$series3color}-->
  var yTitle = "{{{yTitle|Prezzo dell'affitto}}}";
  var showLegend = "{{{showLegend|true}}}".toLowerCase() !== "false";
  var responsive = "{{{responsive|true}}}".toLowerCase() !== "false";


  // Limiti assi opzionali
series4title=<!--{$series4title}-->
  var yMin = numOrUndef("{{{yMin|}}}");
series4data=<!--{$series4data}-->
  var yMax = numOrUndef("{{{yMax|}}}");
series4type=<!--{$series4type}-->
  var xMin = numOrUndef("{{{xMin|}}}");
series4color=<!--{$series4color}-->
  var xMax = numOrUndef("{{{xMax|}}}");


  // Serie 1..4
eqX=<!--{$eqX}-->
  var series = [
eqY=<!--{$eqY}-->
    {t:"{{{series1title|}}}", d:"{{{series1data|}}}", ty:"{{{series1type|line}}}", c:"{{{series1color|}}}"},
showLegend=<!--{$showLegend}-->
    {t:"{{{series2title|}}}", d:"{{{series2data|}}}", ty:"{{{series2type|line}}}", c:"{{{series2color|}}}"},
responsive=<!--{$responsive}-->
    {t:"{{{series3title|}}}", d:"{{{series3data|}}}", ty:"{{{series3type|line}}}", c:"{{{series3color|}}}"},
xMin=<!--{$xMin}-->
    {t:"{{{series4title|}}}", d:"{{{series4data|}}}", ty:"{{{series4type|line}}}", c:"{{{series4color|}}}"}
xMax=<!--{$xMax}-->
   ];
yMin=<!--{$yMin}-->
yMax=<!--{$yMax}-->
   </pre>


   var datasets = [];
   <!-- opzionale: area debug tenuta nascosta -->
  series.forEach(function(s){
   <pre id="debug_<!--{$id}-->" hidden></pre>
    if(!s.t || !s.d) return;
</div>
    var dataArr = parseCSVNumbers(s.d);
    datasets.push({
      label: s.t,
      data: dataArr,
      type: (s.ty && s.ty.trim()) || 'line',
      fill: false,
      borderColor: colorOrNull(s.c),
      backgroundColor: colorOrNull(s.c),
      tension: 0,
      pointRadius: 2
    });
   });
 
  // Punto di equilibrio opzionale (eqX, eqY)
  var eqX = numOrUndef("{{{eqX|}}}");
  var eqY = numOrUndef("{{{eqY|}}}");
  if(eqX !== undefined && eqY !== undefined){
    datasets.push({
      label: "Equilibrio",
      type: "scatter",
      data: [{x:eqX, y:eqY}],
      showLine: false,
      pointRadius: 5,
      pointHoverRadius: 6,
      borderColor: "#000000",
      backgroundColor: "#000000"
    });
  }
 
  // Se le labels sono numeriche, usa asse X lineare
  var numericLabels = labels.every(function(l){ return !isNaN(Number(l)); });
  var dataConfig = { labels: labels, datasets: datasets };
 
  new Chart(ctx, {
    type: 'line',
    data: dataConfig,
    options: {
      responsive: responsive,
      maintainAspectRatio: false,
      plugins: {
        title: { display: !!chartTitle, text: chartTitle },
        legend: { display: showLegend },
        tooltip: { enabled: true }
      },
      elements: { line: { borderWidth: 2 } },
      scales: {
        x: numericLabels ? {
          type: 'linear',
          title: { display: true, text: xTitle },
          min: xMin, max: xMax
        } : {
          type: 'category',
          title: { display: true, text: xTitle }
        },
        y: {
          title: { display: true, text: yTitle },
          min: yMin, max: yMax,
          beginAtZero: false
        }
      }
    }
  });
})();
</script>
 
<!--
Documentazione rapida parametri:
 
Obbligatorio: id
Opzionali: width, height, title, xTitle, yTitle, showLegend, responsive, xMin, xMax, yMin, yMax
labels = CSV (es. 0,2,4,6,8,10)
 
Fino a 4 serie:
seriesNtitle, seriesNdata (CSV), seriesNtype (line|bar), seriesNcolor (es. #d62728)
 
Punto equilibrio opzionale:
eqX=numero, eqY=numero


Esempio minimo:
<script src="/resources/chart.umd.js" defer></script>
{{#widget:Grafico
<script src="/resources/widget-grafico.js" defer></script>
| id=test
</includeonly>
| labels=0,2,4,6
| series1title=Domanda
| series1data=10,7,4,1
| series2title=Offerta
| series2data=0,3,6,9
}}
-->

Versione attuale delle 22:36, 23 set 2025