Widget:Grafico: differenze tra le versioni

Da WikiLectio.
creazione pagina
 
m test
Etichette: Sostituito Annullato
Riga 1: Riga 1:
<!-- Widget:Grafico — Grafici domanda/offerta con Chart.js, fino a 4 serie + punto equilibrio opzionale -->
<div style="padding:8px;border:1px solid #ccc;">
<div id="chart_{{{id}}}" style="width:{{{width|600}}}px;height:{{{height|380}}}px;">
   Widget attivo: {{{id}}}
   <canvas id="canvas_{{{id}}}" width="{{{width|600}}}" height="{{{height|380}}}"></canvas>
</div>
</div>
<!-- Chart.js (CDN) -->
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script>
/* ===== Helpers ===== */
function parseCSVNumbers(str){
  if(!str) return [];
  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 ===== */
(function(){
  var id = "{{{id}}}";
  var canvas = document.getElementById("canvas_{{{id}}}");
  if(!canvas){ return; }
  var ctx = canvas.getContext("2d");
  // Parametri base
  var labels = parseCSVStrings("{{{labels|0,2,4,6,8,10}}}");
  var chartTitle = "{{{title|}}}";
  var xTitle = "{{{xTitle|Quantità di appartamenti}}}";
  var yTitle = "{{{yTitle|Prezzo dell'affitto}}}";
  var showLegend = "{{{showLegend|true}}}".toLowerCase() !== "false";
  var responsive = "{{{responsive|true}}}".toLowerCase() !== "false";
  // Limiti assi opzionali
  var yMin = numOrUndef("{{{yMin|}}}");
  var yMax = numOrUndef("{{{yMax|}}}");
  var xMin = numOrUndef("{{{xMin|}}}");
  var xMax = numOrUndef("{{{xMax|}}}");
  // Serie 1..4
  var series = [
    {t:"{{{series1title|}}}", d:"{{{series1data|}}}", ty:"{{{series1type|line}}}", c:"{{{series1color|}}}"},
    {t:"{{{series2title|}}}", d:"{{{series2data|}}}", ty:"{{{series2type|line}}}", c:"{{{series2color|}}}"},
    {t:"{{{series3title|}}}", d:"{{{series3data|}}}", ty:"{{{series3type|line}}}", c:"{{{series3color|}}}"},
    {t:"{{{series4title|}}}", d:"{{{series4data|}}}", ty:"{{{series4type|line}}}", c:"{{{series4color|}}}"}
  ];
  var datasets = [];
  series.forEach(function(s){
    if(!s.t || !s.d) return;
    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:
{{#widget:Grafico
| id=test
| labels=0,2,4,6
| series1title=Domanda
| series1data=10,7,4,1
| series2title=Offerta
| series2data=0,3,6,9
}}
-->

Versione delle 15:04, 19 set 2025

 Widget attivo: {{{id}}}