html - pie - ¿Cómo puedo controlar la ubicación de la leyenda de mi gráfico circular Chart.JS, así como su apariencia?
chart js pie percentage (3)
Puedo crear un gráfico circular usando Chart.JS con este código:
HTML
<div>
<canvas id="top10ItemsChart" style="padding-left:20px" width="320" height="320"></canvas>
<div id="top10Legend" class="chart-legend"></div>
</div>
jQuery
var data = [{
value: 2755,
color: "#FFE135",
label: "Bananas"
}, {
value: 2256,
color: "#3B5323",
label: "Lettuce, Romaine"
}, {
value: 1637,
color: "#fc6c85",
label: "Melons, Watermelon"
}, {
value: 1608,
color: "#ffec89",
label: "Pineapple"
}, {
value: 1603,
color: "#021c3d",
label: "Berries"
}, {
value: 1433,
color: "#3B5323",
label: "Lettuce, Spring Mix"
}, {
value: 1207,
color: "#046b00",
label: "Broccoli"
}, {
value: 1076,
color: "#cef45a",
label: "Melons, Honeydew"
}, {
value: 1056,
color: "#421C52",
label: "Grapes"
}, {
value: 1048,
color: "#FEA620",
label: "Melons, Cantaloupe"
}];
var optionsPie = {
legend: {
display: true,
position: ''right'',
labels: {
fontColor: ''rgb(255, 99, 132)''
}
}
}
var ctx = $("#top10ItemsChart").get(0).getContext("2d");
var top10PieChart = new Chart(ctx).Pie(data, optionsPie);
document.getElementById(''top10Legend'').innerHTML = top10PieChart.generateLegend();
El problema es que coloca la leyenda en la parte inferior de la tarta, e incluso se derrama y sangra fuera de los límites de la división a la que quiero que la tarta se limite:
También presenta la leyenda como una simple lista desordenada. Lo que quiero hacer es controlar el color de los diversos elementos de la leyenda ("Banana" debe ser del mismo color (# FFE135) que el trozo de pastel de banana (por así decirlo), etc.)
¿Cómo puedo hacer que los elementos individuales coincidan con el color de su punto de datos respectivo?
ACTUALIZAR
El tema "Configuración de la etiqueta de leyenda" en los documentos oficiales here indica que puede establecer el color de fuente de las leyendas, pero esto es para todo el shebang; Lo que quiero saber es, ¿cómo es posible controlar el color de cada elemento?
ACTUALIZACIÓN 2
En un intento de al menos obtener la leyenda que se muestra en el lugar deseado, agregué esto a la jQuery:
var optionsPie = {
legend: {
display: true,
position: ''right'',
labels: {
fontColor: ''rgb(255, 99, 132)''
}
}
}
. . .
var myPieChart = new Chart(ctx).Pie(data, optionsPie);
document.getElementById("legendDiv").innerHTML = myPieChart.generateLegend();
... pero no hace ninguna diferencia: la leyenda aún está colgada en la parte inferior del gráfico circular y su fuente sigue siendo el negro predeterminado.
ACTUALIZACIÓN 3
Utilicé algunos códigos sugeridos, pero la leyenda sigue siendo alimentada por gravedad en lugar de colgarse a la derecha:
Por lo tanto, la leyenda incide en el cuadro que se encuentra debajo, en lugar de limitarse a su propio vecindario.
Además, no quiero que las viñetas infesten la leyenda: los cuadrados de colores (y la palabrería, pero también los valores) son todo lo que necesito. ¿Cómo puedo empujar la leyenda desde el sur del pastel hacia el este del pastel?
ACTUALIZACIÓN 4
He refactorizado el código basado en this y se ve mejor (también agregué más datos al valor de "etiqueta" de la matriz de datos):
Sin embargo, como puedes ver, la leyenda está infringiendo el cuadrante debajo de él. Sin embargo, hay una "tonelada" de espacio vacío / desperdiciado alrededor del pastel: quiero mover el pastel a la izquierda y la leyenda a la derecha del pastel. Eso también permitiría más espacio vertical para que el pastel crezca en estatura.
¿Cómo puedo hacer eso? Aquí está el código que estoy usando ahora:
HTML
<div>
<canvas id="top10ItemsChart" class="pie" style="padding-left:20px"></canvas>
<div id="top10Legend"></div>
</div>
CSS
.pie-legend {
list-style: none;
margin: 0;
padding: 0;
}
.pie-legend span {
display: inline-block;
width: 14px;
height: 14px;
border-radius: 100%;
margin-right: 16px;
margin-bottom: -2px;
}
.pie-legend li {
margin-bottom: 10px;
display: inline-block;
margin-right: 10px;
}
JQUERY
var data = [{
value: 2755,
color: "#FFE135",
label: "Bananas: 2,755 (18%)"
}, {
. . .
}, {
value: 1048,
color: "#FEA620",
label: "Melons, Cantaloupe: 1,048 (7%)"
}];
var optionsPie = {
responsive: true,
scaleBeginAtZero: true,
legendTemplate: "<ul class=/"<%=name.toLowerCase()%>-legend/"><% for (var i=0; i<segments.length; i++){%><li><span style=/"background-color:<%=segments[i].fillColor%>/"></span><%if(segments[i].label){%><%=segments[i].label%><%}%></li><%}%></ul>"
}
var ctx = $("#top10ItemsChart").get(0).getContext("2d");
var top10PieChart = new Chart(ctx).Pie(data, optionsPie);
$("#top10Legend").html(top10PieChart.generateLegend());
NOTA : Agregando esto a optionsPie:
legend: {
display: true,
position: ''right''
},
... no hace nada: la leyenda permanece cargada en el suelo como una rana llena hasta la barbilla con un disparo de codorniz.
Actualización 5
He jugado un poco con el ejemplo de Teo, tratando de que funcione correctamente pero, aunque es mejor, el pastel es muy insignificante, y la leyenda debería ser más amplia, pero no puedo imaginar cómo estirar la leyenda horizontalmente. El pastel en todas direcciones. Así es como se ve ahora:
Este es el código ahora (JQUERY es el mismo):
HTML
<div class="col-md-6">
<div class="topleft">
<h2 class="sectiontext">Top 10 Items</h2>
<br />
<div class="legendTable">
<div class="legendCell">
<canvas id="top10ItemsChart" class="pie" style="padding-left:20px"></canvas>
</div>
<div class="legendCell" id="top10Legend">
</div>
</div>
</div>
</div>
CSS
.topleft {
margin-top: -4px;
margin-left: 16px;
margin-bottom: 16px;
padding: 16px;
border: 1px solid black;
}
canvas {
width: 100% !important;
height: auto !important;
}
.legendTable {
border: 1px solid forestgreen;
display: table;
width: 100%;
table-layout: fixed;
}
.legendCell {
display: table-cell;
vertical-align: middle;
}
.pie-legend ul {
list-style: none;
margin: 0;
padding: 0;
width: 300px;
}
.pie-legend span {
display: inline-block;
width: 14px;
height: 12px;
border-radius: 100%;
margin-right: 4px;
margin-bottom: -2px;
}
.pie-legend li {
margin-bottom: 4px;
display: inline-block;
margin-right: 4px;
}
Algo está aplastando el pastel y juntando los bordes exteriores de la leyenda.
Actualización 6
Ochi, et al: Esto es lo que veo después de la Ochificación de mi código:
Este es mi código, incluso ordené el jQuery de la manera que lo tienes, aunque dudo que sea realmente necesario:
HTML
<div class="row" id="top10Items">
<div class="col-md-6">
<div class="topleft">
<h2 class="sectiontext">Top 10 Items</h2>
<br />
@*<div class="legendTable">
<div class="legendCell">
<canvas id="top10ItemsChart" class="pie" style="padding-left:20px"></canvas>
</div>
<div class="legendCell" id="top10Legend">
</div>
</div>*@
<div class="chart">
<canvas id="top10ItemsChart" class="pie"></canvas>
<div id="pie_legend"></div>
</div>
</div>
</div>
. . .
</div>
CSS
.pie-legend {
list-style: none;
margin: 0;
padding: 0;
}
.pie-legend span {
display: inline-block;
width: 14px;
height: 14px;
border-radius: 100%;
margin-right: 16px;
margin-bottom: -2px;
}
.pie-legend li {
margin-bottom: 10px;
display: block;
margin-right: 10px;
}
.chart,
#priceComplianceBarChart,
#pie_legend {
display: inline-flex;
padding: 0;
margin: 0;
}
JQUERY
var optionsPie = {
responsive: true,
scaleBeginAtZero: true,
legendTemplate: "<ul class=/"<%=name.toLowerCase()%>-legend/"><% for (var i=0; i<segments.length; i++){%><li><span style=/"background-color:<%=segments[i].fillColor%>/"></span><%if(segments[i].label){%><%=segments[i].label%><%}%></li><%}%></ul>"
}
var ctx = $("#top10ItemsChart").get(0).getContext("2d");
var data = [{
value: 2755,
color: "#FFE135",
label: "Bananas: 2,755 (18%)"
. . .
}, {
value: 1048,
color: "#FEA620",
label: "Melons, Cantaloupe: 1,048 (7%)"
}];
var top10PieChart = new Chart(ctx).Pie(data, optionsPie);
$("#pie_legend").html(top10PieChart.generateLegend());
... y sin embargo, el pastel es más elástico que los pantalones elásticos en un elefante.
Actualización 7
Tal vez hay un problema de configuración o algo así. Decidí "actualizar" a la versión 2.1.3 de Chart.JS (comenzó con la versión 1.0.2):
@*<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/1.0.2/Chart.min.js"></script>*@
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.1.3/Chart.js"></script>
... y copié casi exactamente el CodePen de Teo Dragovic here .
Las únicas cosas que cambié fueron los nombres de dos clases de CSS ("tabla" se convirtió en "legendTable" y "celda" se convirtió en "legendCell") y el color del borde de la tabla de rojo a forestgreen, y ahora lo obtengo:
¿Necesito también una referencia a un archivo CSS de Chart.JS o algo así?
Como mencionó @ B.ClayShannon, la versión 2 es bastante diferente a la versión 1. Este es un ejemplo de cómo personalizar la plantilla de leyenda usando la versión 2.
options: {
legendCallback: function (chart) {
var text = [];
text.push(''<ul class="'' + chart.id + ''-legend" style="list-style:none">'');
for (var i = 0; i < chart.data.datasets[0].data.length; i++) {
text.push(''<li><div style="width:10px;height:10px;display:inline-block;background:'' + chart.data.datasets[0].backgroundColor[i] + ''" /> '');
if (chart.data.labels[i]) {
text.push(chart.data.labels[i]);
}
text.push(''</li>'');
}
text.push(''</ul>'');
return text.join('''');
},
legend: {display: false},
}
No se muestra directamente en la solución aceptada anteriormente, pero para representar su leyenda en otro lugar, querrá llamar:
$("#myChartLegend").html(myChart.generateLegend());
Finalmente, algunos HTML para juntarlos (nota que clearfix es una clase Bootstrap que:
<div class="chart">
<div style="float:left">
<canvas id="myChart" class="pie" style="max-width:300px;"></canvas>
</div>
<div class="legend" id="myChartLegend" style="float:left;"></div>
<div style="clear: both;"/>
</div>
Creo que esto es lo que quieres: here
Primero, debe hacer que el canvas
responda, anulando el ancho y la altura fijos y envuélvalo en un div
adicional que pueda usarse para el posicionamiento. Utilicé display: table
para centrar elementos, pero la configuración de divs internos inline-block
en inline-block
también funciona si desea que el gráfico y la leyenda ocupen una cantidad de espacio diferente a 50:50.
HTML:
<div class="table">
<div class="cell">
<canvas id="top10ItemsChart" class="pie"></canvas>
</div>
<div class="cell" id="top10Legend"></div>
</div>
CSS:
canvas {
width: 100% !important;
height: auto !important;
}
.table {
border: 1px solid red;
display: table;
width: 100%;
table-layout: fixed;
}
.cell {
display: table-cell;
vertical-align: middle;
}
ACTUALIZACIÓN: Hice algún ajuste basado en información adicional por OP NUEVA DEMO
HTML:
<div class="container">
<div class="row">
<div class="col-md-6">
<div class="topleft">
<h2 class="sectiontext">Top 10 Items</h2>
<br />
<div class="chart">
<div class="pie">
<canvas id="top10ItemsChart" class="pie"></canvas>
</div>
<div class="legend" id="top10Legend">
</div>
</div>
</div>
</div>
</div>
</div>
CSS:
.topleft {
margin-top: -4px;
margin-left: 16px;
margin-bottom: 16px;
padding: 16px;
border: 1px solid black;
}
canvas {
width: 100% !important;
height: auto !important;
margin-left: -25%;
}
.chart {
border: 1px solid forestgreen;
width: 100%;
overflow: hidden;
position: relative;
}
.pie {
position: relative;
padding: 10px 0;
// adjust as necessary
padding-left: 10px;
padding-right: 0;
}
.legend {
position: absolute;
right: 10px;
top: 10px;
height: 100%;
// adjust as necessary:
width: 48%;
}
@media (max-width: 480px) {
.legend {
position: relative;
width: 100%;
}
.pie {
margin: 0;
}
}
.pie-legend ul {
list-style: none;
margin: 0;
padding: 0;
width: 300px;
}
.pie-legend span {
display: inline-block;
width: 14px;
height: 12px;
border-radius: 100%;
margin-right: 4px;
margin-bottom: -2px;
}
.pie-legend li {
margin-bottom: 4px;
display: inline-block;
margin-right: 4px;
}
Esto es lo que funciona (más o menos) con la versión 2 de Chart.JS:
HTML
<h2 class="sectiontext">Top 10 Items</h2>
<br />
<div class="chart">
<canvas id="top10ItemsChart" class="pie"></canvas>
<div id="pie_legend"></div>
</div>
JQUERY
var data = {
labels: [
"Bananas: 2,755 (18%)",
"Lettuce, Romaine: 2,256 (14%)",
"Melons, Watermelon: 1,637 (10%)",
"Pineapple: 1,608 (10%)",
"Berries: 1,603 (10%)",
"Lettuce, Spring Mix: 1,433 (9%)",
"Broccoli: 1,207 (8%)",
"Melons, Honeydew: 1,076 (7%)",
"Grapes: 1,056 (7%)",
"Melons, Cantaloupe: 1,048 (7%)"
],
datasets: [
{
data: [2755, 2256, 1637, 1608, 1603, 1433, 1207, 1076, 1056, 1048],
backgroundColor: [
"#FFE135",
"#3B5323",
"#fc6c85",
"#ffec89",
"#021c3d",
"#3B5323",
"#046b00",
"#cef45a",
"#421C52",
"#FEA620"
],
}]
};
var optionsPie = {
responsive: true,
scaleBeginAtZero: true
}
var ctx = $("#top10ItemsChart").get(0).getContext("2d");
var top10PieChart = new Chart(ctx,
{
type: ''pie'',
data: data,
options: optionsPie
});
$("#top10Legend").html(top10PieChart.generateLegend());
Digo, "más o menos" porque los trozos de pastel todavía son lamentablemente pequeños: