<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Interactive Pie Chart - Chart.js</title>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-datalabels@2.0.0"></script>
<style>
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
margin: 0;
padding: 20px;
background-color: #f5f7fa;
display: flex;
flex-direction: column;
align-items: center;
color: #333;
}
.container {
width: 90%;
max-width: 1000px;
background: white;
border-radius: 10px;
box-shadow: 0 4px 12px rgba(0,0,0,0.1);
padding: 20px;
margin-top: 20px;
}
h1 {
color: #2c3e50;
text-align: center;
margin-bottom: 10px;
}
.chart-container {
position: relative;
height: 400px;
width: 100%;
margin: 20px 0;
transition: all 0.3s ease;
transform-origin: center top;
}
.controls {
display: flex;
flex-wrap: wrap;
gap: 15px;
justify-content: center;
margin-bottom: 20px;
padding: 15px;
background: #f8f9fa;
border-radius: 8px;
}
.control-group {
display: flex;
align-items: center;
gap: 8px;
}
label {
font-weight: 500;
font-size: 14px;
color: #495057;
}
button, select, input {
padding: 8px 12px;
border: 1px solid #ced4da;
border-radius: 4px;
background-color: white;
font-size: 14px;
cursor: pointer;
transition: all 0.2s;
}
button:hover, select:hover {
background-color: #e9ecef;
}
button.active {
background-color: #4e73df;
color: white;
border-color: #4e73df;
}
input[type="range"] {
width: 120px;
}
.value-display {
min-width: 40px;
text-align: center;
font-weight: bold;
}
/* Toggle Switch Styles */
.switch-container {
display: flex;
align-items: center;
gap: 10px;
}
.switch {
position: relative;
display: inline-block;
width: 60px;
height: 30px;
}
.switch input {
opacity: 0;
width: 0;
height: 0;
}
.slider {
position: absolute;
cursor: pointer;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: #4e73df;
transition: .4s;
border-radius: 34px;
}
.slider:before {
position: absolute;
content: "";
height: 22px;
width: 22px;
left: 4px;
bottom: 4px;
background-color: white;
transition: .4s;
border-radius: 50%;
}
input:checked + .slider {
background-color: #4e73df;
}
input:checked + .slider:before {
transform: translateX(30px);
}
.switch-label {
font-weight: bold;
min-width: 70px;
text-align: center;
}
/* Larger Data Labels */
.data-label {
font-weight: bold;
font-size: 16px;
text-shadow: 2px 2px 4px rgba(0,0,0,0.8);
}
/* Custom legend bullet spots */
.legend-bullet {
display: inline-block;
width: 12px;
height: 12px;
border-radius: 50%;
margin-right: 8px;
}
</style>
</head>
<body>
<div class="container">
<h1>Market Share Distribution</h1>
<!-- Control Panel -->
<div class="controls">
<div class="control-group">
<label>Cutout %:</label>
<input type="range" id="cutout" min="0", max="90", step="5", value="50">
<span id="cutoutValue" class="value-display">50%</span>
</div>
<div class="control-group">
<label>Chart Border:</label>
<input type="range" id="borderWidth" min="0", max="10", step="1", value="2">
<span id="borderWidthValue" class="value-display">2</span>
</div>
<div class="control-group">
<label>Scale:</label>
<input type="range" id="chartScale" min="50", max="150", step="5", value="100">
<span id="chartScaleValue" class="value-display">100%</span>
</div>
<div class="control-group">
<label>Display:</label>
<div class="switch-container">
<span class="switch-label" id="displayLabel">%</span>
<label class="switch">
<input type="checkbox" id="displayToggle">
<span class="slider"></span>
</label>
<span class="switch-label" id="displayLabel">Value</span>
</div>
</div>
<button id="resetBtn">Reset Settings</button>
</div>
<!-- Chart Container -->
<div class="chart-container">
<canvas id="pieChart"></canvas>
</div>
</div>
<script>
// Initial data
const data = {
labels: ["Apple", "Samsung", "Huawei", "Xiaomi", "Others"],
datasets: [{
data: [45, 25, 12, 8, 10],
backgroundColor: [
"#4e73df",
"#1cc88a",
"#36b9cc",
"#f6c23e",
"#e74a3b"
],
borderColor: "#ffffff",
borderWidth: 2,
cutout: '50%'
}]
};
// Display settings
let showPercentage = true;
// Create chart
let myChart;
function initChart() {
const ctx = document.getElementById('pieChart').getContext('2d');
myChart = new Chart(ctx, {
type: 'pie',
data: data,
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: {
position: 'right',
labels: {
boxWidth: 12,
padding: 20,
usePointStyle: true,
pointStyle: 'circle',
font: {
size: 12
},
generateLabels: function(chart) {
const data = chart.data;
if (data.labels.length && data.datasets.length) {
return data.labels.map(function(label, i) {
return {
text: label,
fillStyle: data.datasets[0].backgroundColor[i],
hidden: false,
index: i
};
});
}
return [];
}
}
},
title: {
display: true,
text: 'Global Smartphone Market Share (2023)',
font: { size: 16 }
},
datalabels: {
formatter: (value, context) => {
const total = context.chart.data.datasets[0].data.reduce((a, b) => a + b, 0);
const percentage = Math.round((value / total) * 100);
return showPercentage ? `${percentage}%` : `${value}`;
},
color: '#fff',
font: {
weight: 'bold',
size: 16
},
textAlign: 'center',
padding: {
top: 0,
bottom: 0
},
display: function(context) {
return context.dataset.data[context.dataIndex] > 5;
}
}
}
},
plugins: [ChartDataLabels]
});
}
// Interactive controls
document.getElementById('cutout').addEventListener('input', function() {
const value = parseInt(this.value);
document.getElementById('cutoutValue').textContent = `${value}%`;
myChart.data.datasets[0].cutout = `${value}%`;
myChart.update();
});
document.getElementById('borderWidth').addEventListener('input', function() {
const value = parseInt(this.value);
document.getElementById('borderWidthValue').textContent = value;
myChart.data.datasets[0].borderWidth = value;
myChart.update();
});
document.getElementById('chartScale').addEventListener('input', function() {
const scale = parseInt(this.value) / 100;
document.getElementById('chartScaleValue').textContent = `${this.value}%`;
const container = document.querySelector('.chart-container');
container.style.transform = `scale(${scale})`;
if(myChart) {
setTimeout(() => myChart.resize(), 100);
}
});
// Toggle switch
document.getElementById('displayToggle').addEventListener('change', function() {
showPercentage = !this.checked;
myChart.update();
});
// Reset button
document.getElementById('resetBtn').addEventListener('click', function() {
document.getElementById('cutout').value = 50;
document.getElementById('borderWidth').value = 2;
document.getElementById('chartScale').value = 100;
document.getElementById('displayToggle').checked = false;
document.getElementById('cutoutValue').textContent = '50%';
document.getElementById('borderWidthValue').textContent = '2';
document.getElementById('chartScaleValue').textContent = '100%';
const container = document.querySelector('.chart-container');
container.style.transform = 'scale(1)';
showPercentage = true;
myChart.destroy();
initChart();
});
// Initialize
document.addEventListener('DOMContentLoaded', initChart);
</script>
</body>
</html>