D3.js Datenvisualisierung Beispiele

Umfassende D3.js datenvisualisierung beispiele einschließlich diagramme, karten, animationen und interaktive visualisierungen

Key Facts

Category
Data Visualization
Items
3
Format Families
json, image, svg

Sample Overview

Umfassende D3.js datenvisualisierung beispiele einschließlich diagramme, karten, animationen und interaktive visualisierungen This sample set belongs to Data Visualization and can be used to test related workflows inside Elysia Tools.

💻 D3.js Basis-Diagramme javascript

🟢 simple ⭐⭐

Wesentliche D3.js-diagramme einschließlich balken-, linien-, torten- und streudiagramme mit interaktiven features

⏱️ 25 min 🏷️ d3, charts, visualization
Prerequisites: JavaScript, HTML, CSS, D3.js basics
// D3.js Basic Charts Examples

// 1. Bar Chart
// HTML: <div id="bar-chart"></div>
function createBarChart() {
    const data = [
        { name: 'Product A', value: 30 },
        { name: 'Product B', value: 80 },
        { name: 'Product C', value: 45 },
        { name: 'Product D', value: 60 },
        { name: 'Product E', value: 20 },
        { name: 'Product F', value: 90 },
        { name: 'Product G', value: 55 }
    ];

    // Set dimensions
    const margin = { top: 20, right: 30, bottom: 40, left: 40 };
    const width = 600 - margin.left - margin.right;
    const height = 400 - margin.top - margin.bottom;

    // Create SVG
    const svg = d3.select('#bar-chart')
        .append('svg')
        .attr('width', width + margin.left + margin.right)
        .attr('height', height + margin.top + margin.bottom)
        .append('g')
        .attr('transform', `translate(${margin.left},${margin.top})`);

    // Set scales
    const x = d3.scaleBand()
        .domain(data.map(d => d.name))
        .range([0, width])
        .padding(0.1);

    const y = d3.scaleLinear()
        .domain([0, d3.max(data, d => d.value)])
        .nice()
        .range([height, 0]);

    // Create x-axis
    svg.append('g')
        .attr('transform', `translate(0,${height})`)
        .call(d3.axisBottom(x))
        .selectAll('text')
        .style('text-anchor', 'end')
        .attr('dx', '-.8em')
        .attr('dy', '.15em')
        .attr('transform', 'rotate(-45)');

    // Create y-axis
    svg.append('g')
        .call(d3.axisLeft(y));

    // Create bars
    const bars = svg.selectAll('.bar')
        .data(data)
        .enter().append('rect')
        .attr('class', 'bar')
        .attr('x', d => x(d.name))
        .attr('width', x.bandwidth())
        .attr('y', d => y(d.value))
        .attr('height', d => height - y(d.value))
        .attr('fill', '#4e79a7')
        .on('mouseover', function(event, d) {
            d3.select(this)
                .transition()
                .duration(200)
                .attr('fill', '#f28e2c');

            // Show tooltip
            const tooltip = d3.select('body').append('div')
                .attr('class', 'tooltip')
                .style('position', 'absolute')
                .style('background', 'rgba(0,0,0,0.8)')
                .style('color', 'white')
                .style('padding', '8px')
                .style('border-radius', '4px')
                .style('pointer-events', 'none')
                .style('opacity', 0);

            tooltip.transition()
                .duration(200)
                .style('opacity', 1);

            tooltip.html(`${d.name}: ${d.value}`)
                .style('left', (event.pageX + 10) + 'px')
                .style('top', (event.pageY - 10) + 'px');
        })
        .on('mouseout', function(d) {
            d3.select(this)
                .transition()
                .duration(200)
                .attr('fill', '#4e79a7');

            // Remove tooltip
            d3.selectAll('.tooltip').remove();
        })
        .on('mousemove', function(event) {
            d3.select('.tooltip')
                .style('left', (event.pageX + 10) + 'px')
                .style('top', (event.pageY - 10) + 'px');
        });

    // Add labels
    svg.append('text')
        .attr('transform', 'rotate(-90)')
        .attr('y', 0 - margin.left)
        .attr('x', 0 - (height / 2))
        .attr('dy', '1em')
        .style('text-anchor', 'middle')
        .text('Value');

    svg.append('text')
        .attr('transform', `translate(${width / 2}, ${height + margin.bottom})`)
        .style('text-anchor', 'middle')
        .text('Product');
}

// 2. Line Chart
// HTML: <div id="line-chart"></div>
function createLineChart() {
    const data = [
        { date: new Date(2024, 0, 1), value: 30 },
        { date: new Date(2024, 1, 1), value: 45 },
        { date: new Date(2024, 2, 1), value: 35 },
        { date: new Date(2024, 3, 1), value: 50 },
        { date: new Date(2024, 4, 1), value: 65 },
        { date: new Date(2024, 5, 1), value: 55 },
        { date: new Date(2024, 6, 1), value: 70 },
        { date: new Date(2024, 7, 1), value: 85 },
        { date: new Date(2024, 8, 1), value: 75 },
        { date: new Date(2024, 9, 1), value: 90 },
        { date: new Date(2024, 10, 1), value: 80 },
        { date: new Date(2024, 11, 1), value: 95 }
    ];

    // Set dimensions
    const margin = { top: 20, right: 30, bottom: 40, left: 50 };
    const width = 600 - margin.left - margin.right;
    const height = 300 - margin.top - margin.bottom;

    // Create SVG
    const svg = d3.select('#line-chart')
        .append('svg')
        .attr('width', width + margin.left + margin.right)
        .attr('height', height + margin.top + margin.bottom)
        .append('g')
        .attr('transform', `translate(${margin.left},${margin.top})`);

    // Set scales
    const x = d3.scaleTime()
        .domain(d3.extent(data, d => d.date))
        .range([0, width]);

    const y = d3.scaleLinear()
        .domain([0, d3.max(data, d => d.value)])
        .nice()
        .range([height, 0]);

    // Create line generator
    const line = d3.line()
        .x(d => x(d.date))
        .y(d => y(d.value))
        .curve(d3.curveMonotoneX);

    // Add grid lines
    svg.append('g')
        .attr('class', 'grid')
        .attr('transform', `translate(0,${height})`)
        .call(d3.axisBottom(x)
            .tickSize(-height)
            .tickFormat('')
        )
        .style('stroke-dasharray', '3,3')
        .style('opacity', 0.3);

    svg.append('g')
        .attr('class', 'grid')
        .call(d3.axisLeft(y)
            .tickSize(-width)
            .tickFormat('')
        )
        .style('stroke-dasharray', '3,3')
        .style('opacity', 0.3);

    // Create axes
    svg.append('g')
        .attr('transform', `translate(0,${height})`)
        .call(d3.axisBottom(x));

    svg.append('g')
        .call(d3.axisLeft(y));

    // Create line
    svg.append('path')
        .datum(data)
        .attr('fill', 'none')
        .attr('stroke', '#4e79a7')
        .attr('stroke-width', 2)
        .attr('d', line);

    // Create area
    const area = d3.area()
        .x(d => x(d.date))
        .y0(height)
        .y1(d => y(d.value))
        .curve(d3.curveMonotoneX);

    svg.append('path')
        .datum(data)
        .attr('fill', '#4e79a7')
        .attr('opacity', 0.1)
        .attr('d', area);

    // Add dots
    svg.selectAll('.dot')
        .data(data)
        .enter().append('circle')
        .attr('class', 'dot')
        .attr('cx', d => x(d.date))
        .attr('cy', d => y(d.value))
        .attr('r', 4)
        .attr('fill', '#4e79a7')
        .on('mouseover', function(event, d) {
            d3.select(this)
                .transition()
                .duration(200)
                .attr('r', 6);

            showTooltip(event, `Date: ${d.date.toLocaleDateString()}<br>Value: ${d.value}`);
        })
        .on('mouseout', function() {
            d3.select(this)
                .transition()
                .duration(200)
                .attr('r', 4);

            hideTooltip();
        });
}

// 3. Pie Chart
// HTML: <div id="pie-chart"></div>
function createPieChart() {
    const data = [
        { label: 'Category A', value: 30, color: '#4e79a7' },
        { label: 'Category B', value: 25, color: '#f28e2c' },
        { label: 'Category C', value: 20, color: '#e15759' },
        { label: 'Category D', value: 15, color: '#76b7b2' },
        { label: 'Category E', value: 10, color: '#59a14f' }
    ];

    // Set dimensions
    const width = 400;
    const height = 400;
    const radius = Math.min(width, height) / 2;

    // Create SVG
    const svg = d3.select('#pie-chart')
        .append('svg')
        .attr('width', width)
        .attr('height', height)
        .append('g')
        .attr('transform', `translate(${width / 2},${height / 2})`);

    // Create pie layout
    const pie = d3.pie()
        .value(d => d.value)
        .sort(null);

    // Create arc generator
    const arc = d3.arc()
        .innerRadius(0)
        .outerRadius(radius);

    const arcHover = d3.arc()
        .innerRadius(0)
        .outerRadius(radius * 1.1);

    // Create pie slices
    const arcs = svg.selectAll('.arc')
        .data(pie(data))
        .enter().append('g')
        .attr('class', 'arc');

    arcs.append('path')
        .attr('d', arc)
        .attr('fill', d => d.data.color)
        .attr('stroke', 'white')
        .attr('stroke-width', 2)
        .style('cursor', 'pointer')
        .on('mouseover', function(event, d) {
            d3.select(this)
                .transition()
                .duration(200)
                .attr('d', arcHover);

            showTooltip(event, `${d.data.label}: ${d.data.value} (${d3.format('.1%')(d.value / d3.sum(data, d => d.value))})`);
        })
        .on('mouseout', function(event, d) {
            d3.select(this)
                .transition()
                .duration(200)
                .attr('d', arc);

            hideTooltip();
        });

    // Add labels
    arcs.append('text')
        .attr('transform', d => `translate(${arc.centroid(d)})`)
        .attr('text-anchor', 'middle')
        .style('fill', 'white')
        .style('font-weight', 'bold')
        .style('pointer-events', 'none')
        .text(d => d.data.value);
}

// 4. Scatter Plot
// HTML: <div id="scatter-plot"></div>
function createScatterPlot() {
    const data = Array.from({ length: 50 }, () => ({
        x: Math.random() * 100,
        y: Math.random() * 100,
        size: Math.random() * 30 + 5,
        category: ['A', 'B', 'C', 'D'][Math.floor(Math.random() * 4)]
    }));

    // Set dimensions
    const margin = { top: 20, right: 30, bottom: 40, left: 50 };
    const width = 600 - margin.left - margin.right;
    const height = 400 - margin.top - margin.bottom;

    // Create SVG
    const svg = d3.select('#scatter-plot')
        .append('svg')
        .attr('width', width + margin.left + margin.right)
        .attr('height', height + margin.top + margin.bottom)
        .append('g')
        .attr('transform', `translate(${margin.left},${margin.top})`);

    // Set scales
    const x = d3.scaleLinear()
        .domain([0, 100])
        .range([0, width]);

    const y = d3.scaleLinear()
        .domain([0, 100])
        .range([height, 0]);

    const size = d3.scaleLinear()
        .domain([5, 35])
        .range([3, 15]);

    // Create axes
    svg.append('g')
        .attr('transform', `translate(0,${height})`)
        .call(d3.axisBottom(x));

    svg.append('g')
        .call(d3.axisLeft(y));

    // Create color scale
    const color = d3.scaleOrdinal()
        .domain(['A', 'B', 'C', 'D'])
        .range(['#4e79a7', '#f28e2c', '#e15759', '#76b7b2']);

    // Create dots
    svg.selectAll('.dot')
        .data(data)
        .enter().append('circle')
        .attr('class', 'dot')
        .attr('cx', d => x(d.x))
        .attr('cy', d => y(d.y))
        .attr('r', d => size(d.size))
        .attr('fill', d => color(d.category))
        .attr('opacity', 0.7)
        .style('cursor', 'pointer')
        .on('mouseover', function(event, d) {
            d3.select(this)
                .transition()
                .duration(200)
                .attr('opacity', 1)
                .attr('r', d => size(d.size) * 1.2);

            showTooltip(event, `X: ${d.x.toFixed(1)}<br>Y: ${d.y.toFixed(1)}<br>Size: ${d.size.toFixed(1)}<br>Category: ${d.category}`);
        })
        .on('mouseout', function(event, d) {
            d3.select(this)
                .transition()
                .duration(200)
                .attr('opacity', 0.7)
                .attr('r', d => size(d.size));

            hideTooltip();
        });

    // Add axis labels
    svg.append('text')
        .attr('transform', 'rotate(-90)')
        .attr('y', 0 - margin.left)
        .attr('x', 0 - (height / 2))
        .attr('dy', '1em')
        .style('text-anchor', 'middle')
        .text('Y Value');

    svg.append('text')
        .attr('transform', `translate(${width / 2}, ${height + margin.bottom})`)
        .style('text-anchor', 'middle')
        .text('X Value');
}

// Utility functions
function showTooltip(event, content) {
    const tooltip = d3.select('body').append('div')
        .attr('class', 'tooltip')
        .style('position', 'absolute')
        .style('background', 'rgba(0,0,0,0.8)')
        .style('color', 'white')
        .style('padding', '8px')
        .style('border-radius', '4px')
        .style('pointer-events', 'none')
        .style('font-size', '12px')
        .style('opacity', 0);

    tooltip.transition()
        .duration(200)
        .style('opacity', 1);

    tooltip.html(content)
        .style('left', (event.pageX + 10) + 'px')
        .style('top', (event.pageY - 10) + 'px');
}

function hideTooltip() {
    d3.selectAll('.tooltip').remove();
}

// Initialize all charts
document.addEventListener('DOMContentLoaded', function() {
    createBarChart();
    createLineChart();
    createPieChart();
    createScatterPlot();
});

💻 D3.js Interaktives Dashboard javascript

🟡 intermediate ⭐⭐⭐⭐

Dynamisches dashboard mit mehreren verknüpften diagrammen, echtzeit-aktualisierungen und interaktiven filtern

⏱️ 45 min 🏷️ d3, dashboard, interactive, real-time
Prerequisites: Advanced JavaScript, D3.js, HTML/CSS, Data visualization concepts
// D3.js Interactive Dashboard

// Dashboard Configuration
const dashboardConfig = {
    width: 1200,
    height: 800,
    margin: { top: 20, right: 20, bottom: 40, left: 50 },
    colors: ['#4e79a7', '#f28e2c', '#e15759', '#76b7b2', '#59a14f', '#edc949', '#af7aa1', '#ff9da7']
};

// Sample data generator
class DataGenerator {
    constructor() {
        this.categories = ['Electronics', 'Clothing', 'Books', 'Home', 'Sports'];
        this.regions = ['North', 'South', 'East', 'West'];
    }

    generateSalesData(months = 12) {
        const data = [];
        const now = new Date();

        for (let i = 0; i < months; i++) {
            const date = new Date(now.getFullYear(), now.getMonth() - (months - 1 - i), 1);

            this.categories.forEach(category => {
                data.push({
                    date: date,
                    category: category,
                    sales: Math.floor(Math.random() * 10000) + 1000,
                    profit: Math.floor(Math.random() * 2000) + 200,
                    region: this.regions[Math.floor(Math.random() * this.regions.length)]
                });
            });
        }

        return data;
    }

    generateRealTimeData() {
        return {
            timestamp: new Date(),
            value: Math.floor(Math.random() * 100) + 20,
            category: this.categories[Math.floor(Math.random() * this.categories.length)],
            region: this.regions[Math.floor(Math.random() * this.regions.length)]
        };
    }
}

// Main Dashboard Class
class InteractiveDashboard {
    constructor(containerId) {
        this.container = d3.select(containerId);
        this.dataGenerator = new DataGenerator();
        this.data = this.dataGenerator.generateSalesData();
        this.filteredData = this.data;

        this.filters = {
            category: 'all',
            region: 'all',
            dateRange: [d3.min(this.data, d => d.date), d3.max(this.data, d => d.date)]
        };

        this.init();
    }

    init() {
        this.createLayout();
        this.createFilters();
        this.createKPIs();
        this.createCharts();
        this.setupEventListeners();
        this.startRealTimeUpdates();
    }

    createLayout() {
        // Create dashboard container
        this.dashboard = this.container.append('div')
            .attr('class', 'dashboard')
            .style('font-family', 'Arial, sans-serif')
            .style('padding', '20px');

        // Create header
        this.dashboard.append('h1')
            .text('Interactive Sales Dashboard')
            .style('text-align', 'center')
            .style('margin-bottom', '20px');

        // Create filter container
        this.filterContainer = this.dashboard.append('div')
            .attr('class', 'filters')
            .style('margin-bottom', '20px');

        // Create KPI container
        this.kpiContainer = this.dashboard.append('div')
            .attr('class', 'kpis')
            .style('display', 'flex')
            .style('justify-content', 'space-between')
            .style('margin-bottom', '20px');

        // Create charts container
        this.chartsContainer = this.dashboard.append('div')
            .attr('class', 'charts')
            .style('display', 'grid')
            .style('grid-template-columns', '1fr 1fr')
            .style('gap', '20px');
    }

    createFilters() {
        // Category filter
        this.filterContainer.append('label')
            .text('Category: ')
            .style('margin-right', '10px');

        const categorySelect = this.filterContainer.append('select')
            .attr('id', 'category-filter')
            .style('margin-right', '20px');

        categorySelect.selectAll('option')
            .data(['all', ...this.dataGenerator.categories])
            .enter()
            .append('option')
            .attr('value', d => d)
            .text(d => d.charAt(0).toUpperCase() + d.slice(1));

        // Region filter
        this.filterContainer.append('label')
            .text('Region: ')
            .style('margin-right', '10px');

        const regionSelect = this.filterContainer.append('select')
            .attr('id', 'region-filter');

        regionSelect.selectAll('option')
            .data(['all', ...this.dataGenerator.regions])
            .enter()
            .append('option')
            .attr('value', d => d)
            .text(d);

        // Date range filter
        this.filterContainer.append('label')
            .text('Date Range: ')
            .style('margin-right', '10px');

        const startDateInput = this.filterContainer.append('input')
            .attr('type', 'date')
            .attr('id', 'start-date')
            .style('margin-right', '10px');

        const endDateInput = this.filterContainer.append('input')
            .attr('type', 'date')
            .attr('id', 'end-date');

        // Set default date range
        const minDate = d3.min(this.data, d => d.date);
        const maxDate = d3.max(this.data, d => d.date);
        startDateInput.property('value', minDate.toISOString().split('T')[0]);
        endDateInput.property('value', maxDate.toISOString().split('T')[0]);
    }

    createKPIs() {
        const kpis = [
            { id: 'total-sales', label: 'Total Sales', value: 0, format: d3.format(',.0f') },
            { id: 'total-profit', label: 'Total Profit', value: 0, format: d3.format(',.0f') },
            { id: 'avg-sale', label: 'Average Sale', value: 0, format: d3.format(',.0f') },
            { id: 'top-category', label: 'Top Category', value: '-', format: d => d }
        ];

        kpis.forEach(kpi => {
            const kpiCard = this.kpiContainer.append('div')
                .attr('class', 'kpi-card')
                .style('background', 'white')
                .style('padding', '20px')
                .style('border-radius', '8px')
                .style('box-shadow', '0 2px 4px rgba(0,0,0,0.1)')
                .style('min-width', '200px');

            kpiCard.append('h3')
                .text(kpi.label)
                .style('margin', '0 0 10px 0')
                .style('color', '#666')
                .style('font-size', '14px');

            kpiCard.append('div')
                .attr('id', kpi.id)
                .style('font-size', '24px')
                .style('font-weight', 'bold')
                .style('color', '#333');

            this[kpi.id] = kpiCard;
        });
    }

    createCharts() {
        this.createSalesTrendChart();
        this.createCategoryDistribution();
        this.createRegionalPerformance();
        this.createRealTimeChart();
    }

    createSalesTrendChart() {
        const chartContainer = this.chartsContainer.append('div')
            .attr('class', 'chart')
            .style('background', 'white')
            .style('padding', '20px')
            .style('border-radius', '8px')
            .style('box-shadow', '0 2px 4px rgba(0,0,0,0.1)');

        chartContainer.append('h3')
            .text('Sales Trend')
            .style('margin', '0 0 20px 0');

        const margin = { top: 20, right: 30, bottom: 40, left: 50 };
        const width = 500 - margin.left - margin.right;
        const height = 300 - margin.top - margin.bottom;

        const svg = chartContainer.append('svg')
            .attr('width', width + margin.left + margin.right)
            .attr('height', height + margin.top + margin.bottom)
            .append('g')
            .attr('transform', `translate(${margin.left},${margin.top})`);

        // Set scales
        const x = d3.scaleTime()
            .domain(d3.extent(this.filteredData, d => d.date))
            .range([0, width]);

        const y = d3.scaleLinear()
            .domain([0, d3.max(this.filteredData, d => d.sales)])
            .nice()
            .range([height, 0]);

        // Create line generator
        const line = d3.line()
            .x(d => x(d.date))
            .y(d => y(d.sales))
            .curve(d3.curveMonotoneX);

        // Create axes
        svg.append('g')
            .attr('transform', `translate(0,${height})`)
            .call(d3.axisBottom(x));

        svg.append('g')
            .call(d3.axisLeft(y));

        // Create line
        svg.append('path')
            .datum(this.filteredData)
            .attr('fill', 'none')
            .attr('stroke', '#4e79a7')
            .attr('stroke-width', 2)
            .attr('d', line);

        this.salesTrendChart = { svg, x, y, line };
    }

    createCategoryDistribution() {
        const chartContainer = this.chartsContainer.append('div')
            .attr('class', 'chart')
            .style('background', 'white')
            .style('padding', '20px')
            .style('border-radius', '8px')
            .style('box-shadow', '0 2px 4px rgba(0,0,0,0.1)');

        chartContainer.append('h3')
            .text('Category Distribution')
            .style('margin', '0 0 20px 0');

        const width = 500;
        const height = 300;
        const radius = Math.min(width, height) / 2 - 20;

        const svg = chartContainer.append('svg')
            .attr('width', width)
            .attr('height', height)
            .append('g')
            .attr('transform', `translate(${width / 2},${height / 2})`);

        // Aggregate data by category
        const categoryData = d3.rollup(
            this.filteredData,
            v => d3.sum(v, d => d.sales),
            d => d.category
        );

        const pieData = Array.from(categoryData, ([key, value]) => ({ key, value }));

        // Create pie layout
        const pie = d3.pie()
            .value(d => d.value);

        const arc = d3.arc()
            .innerRadius(0)
            .outerRadius(radius);

        // Create pie slices
        const arcs = svg.selectAll('.arc')
            .data(pie(pieData))
            .enter()
            .append('g')
            .attr('class', 'arc');

        arcs.append('path')
            .attr('d', arc)
            .attr('fill', (d, i) => dashboardConfig.colors[i])
            .attr('stroke', 'white')
            .attr('stroke-width', 2);

        this.categoryChart = { svg, pie, arc };
    }

    createRegionalPerformance() {
        const chartContainer = this.chartsContainer.append('div')
            .attr('class', 'chart')
            .style('background', 'white')
            .style('padding', '20px')
            .style('border-radius', '8px')
            .style('box-shadow', '0 2px 4px rgba(0,0,0,0.1)')
            .style('grid-column', '1 / -1');

        chartContainer.append('h3')
            .text('Regional Performance')
            .style('margin', '0 0 20px 0');

        const margin = { top: 20, right: 30, bottom: 40, left: 50 };
        const width = 1000 - margin.left - margin.right;
        const height = 250 - margin.top - margin.bottom;

        const svg = chartContainer.append('svg')
            .attr('width', width + margin.left + margin.right)
            .attr('height', height + margin.top + margin.bottom)
            .append('g')
            .attr('transform', `translate(${margin.left},${margin.top})`);

        // Aggregate data by region
        const regionData = d3.rollup(
            this.filteredData,
            v => d3.sum(v, d => d.sales),
            d => d.region
        );

        const barData = Array.from(regionData, ([key, value]) => ({ key, value }));

        // Set scales
        const x = d3.scaleBand()
            .domain(barData.map(d => d.key))
            .range([0, width])
            .padding(0.1);

        const y = d3.scaleLinear()
            .domain([0, d3.max(barData, d => d.value)])
            .nice()
            .range([height, 0]);

        // Create bars
        svg.selectAll('.bar')
            .data(barData)
            .enter()
            .append('rect')
            .attr('class', 'bar')
            .attr('x', d => x(d.key))
            .attr('width', x.bandwidth())
            .attr('y', d => y(d.value))
            .attr('height', d => height - y(d.value))
            .attr('fill', '#4e79a7');

        // Create axes
        svg.append('g')
            .attr('transform', `translate(0,${height})`)
            .call(d3.axisBottom(x));

        svg.append('g')
            .call(d3.axisLeft(y));

        this.regionalChart = { svg, x, y };
    }

    createRealTimeChart() {
        const chartContainer = this.chartsContainer.append('div')
            .attr('class', 'chart')
            .style('background', 'white')
            .style('padding', '20px')
            .style('border-radius', '8px')
            .style('box-shadow', '0 2px 4px rgba(0,0,0,0.1)');

        chartContainer.append('h3')
            .text('Real-time Metrics')
            .style('margin', '0 0 20px 0');

        const margin = { top: 20, right: 30, bottom: 40, left: 50 };
        const width = 500 - margin.left - margin.right;
        const height = 200 - margin.top - margin.bottom;

        const svg = chartContainer.append('svg')
            .attr('width', width + margin.left + margin.right)
            .attr('height', height + margin.top + margin.bottom)
            .append('g')
            .attr('transform', `translate(${margin.left},${margin.top})`);

        // Real-time data
        this.realTimeData = [];

        // Set scales
        const x = d3.scaleTime()
            .domain([new Date(Date.now() - 60000), new Date()])
            .range([0, width]);

        const y = d3.scaleLinear()
            .domain([0, 100])
            .range([height, 0]);

        // Create axes
        svg.append('g')
            .attr('transform', `translate(0,${height})`)
            .call(d3.axisBottom(x));

        svg.append('g')
            .call(d3.axisLeft(y));

        // Create line
        const line = d3.line()
            .x(d => x(d.timestamp))
            .y(d => d.value)
            .curve(d3.curveMonotoneX);

        const path = svg.append('path')
            .datum(this.realTimeData)
            .attr('fill', 'none')
            .attr('stroke', '#f28e2c')
            .attr('stroke-width', 2)
            .attr('d', line);

        this.realTimeChart = { svg, x, y, line, path };
    }

    setupEventListeners() {
        // Category filter
        d3.select('#category-filter').on('change', (event) => {
            this.filters.category = event.target.value;
            this.updateDashboard();
        });

        // Region filter
        d3.select('#region-filter').on('change', (event) => {
            this.filters.region = event.target.value;
            this.updateDashboard();
        });

        // Date range filter
        d3.select('#start-date').on('change', (event) => {
            this.filters.dateRange[0] = new Date(event.target.value);
            this.updateDashboard();
        });

        d3.select('#end-date').on('change', (event) => {
            this.filters.dateRange[1] = new Date(event.target.value);
            this.updateDashboard();
        });
    }

    updateDashboard() {
        // Apply filters
        this.filteredData = this.data.filter(d => {
            const categoryMatch = this.filters.category === 'all' || d.category === this.filters.category;
            const regionMatch = this.filters.region === 'all' || d.region === this.filters.region;
            const dateMatch = d.date >= this.filters.dateRange[0] && d.date <= this.filters.dateRange[1];
            return categoryMatch && regionMatch && dateMatch;
        });

        // Update KPIs
        this.updateKPIs();

        // Update charts
        this.updateCharts();
    }

    updateKPIs() {
        const totalSales = d3.sum(this.filteredData, d => d.sales);
        const totalProfit = d3.sum(this.filteredData, d => d.profit);
        const avgSale = d3.mean(this.filteredData, d => d.sales);

        const topCategory = d3.rollup(
            this.filteredData,
            v => d3.sum(v, d => d.sales),
            d => d.category
        );
        const topCategoryName = Array.from(topCategory.entries())
            .sort((a, b) => b[1] - a[1])[0]?.[0] || '-';

        // Update KPI displays
        d3.select('#total-sales').text(d3.format(',')(totalSales));
        d3.select('#total-profit').text(d3.format(',')(totalProfit));
        d3.select('#avg-sale').text(d3.format(',')(Math.round(avgSale)));
        d3.select('#top-category').text(topCategoryName);
    }

    updateCharts() {
        // Update sales trend chart
        if (this.salesTrendChart) {
            const { svg, x, y, line } = this.salesTrendChart;

            x.domain(d3.extent(this.filteredData, d => d.date));
            y.domain([0, d3.max(this.filteredData, d => d.sales)]);

            svg.select('.x-axis').remove();
            svg.select('.y-axis').remove();

            svg.append('g')
                .attr('transform', `translate(0,${y.range()[0]})`)
                .call(d3.axisBottom(x));

            svg.append('g')
                .call(d3.axisLeft(y));

            svg.select('path')
                .datum(this.filteredData)
                .transition()
                .duration(750)
                .attr('d', line);
        }

        // Update category chart
        if (this.categoryChart) {
            const { svg, pie, arc } = this.categoryChart;

            const categoryData = d3.rollup(
                this.filteredData,
                v => d3.sum(v, d => d.sales),
                d => d.category
            );

            const pieData = Array.from(categoryData, ([key, value]) => ({ key, value }));

            const arcs = svg.selectAll('.arc')
                .data(pie(pieData));

            arcs.select('path')
                .transition()
                .duration(750)
                .attrTween('d', function(d) {
                    const interpolate = d3.interpolate(this._current, d);
                    this._current = interpolate(0);
                    return function(t) {
                        return arc(interpolate(t));
                    };
                });
        }

        // Update regional chart
        if (this.regionalChart) {
            const { svg, x, y } = this.regionalChart;

            const regionData = d3.rollup(
                this.filteredData,
                v => d3.sum(v, d => d.sales),
                d => d.region
            );

            const barData = Array.from(regionData, ([key, value]) => ({ key, value }));

            x.domain(barData.map(d => d.key));
            y.domain([0, d3.max(barData, d => d.value)]);

            const bars = svg.selectAll('.bar')
                .data(barData);

            bars.transition()
                .duration(750)
                .attr('y', d => y(d.value))
                .attr('height', d => y(0) - y(d.value));
        }
    }

    startRealTimeUpdates() {
        setInterval(() => {
            const newData = this.dataGenerator.generateRealTimeData();

            // Add to real-time data array
            this.realTimeData.push(newData);

            // Keep only last 60 seconds of data
            const oneMinuteAgo = new Date(Date.now() - 60000);
            this.realTimeData = this.realTimeData.filter(d => d.timestamp > oneMinuteAgo);

            // Update real-time chart
            if (this.realTimeChart) {
                const { x, y, line, path } = this.realTimeChart;

                x.domain([new Date(Date.now() - 60000), new Date()]);

                path.datum(this.realTimeData)
                    .transition()
                    .duration(200)
                    .attr('d', line);
            }
        }, 1000);
    }
}

// Initialize dashboard
document.addEventListener('DOMContentLoaded', function() {
    const dashboard = new InteractiveDashboard('#dashboard');
});

💻 D3.js Geografische Karten javascript

🔴 complex ⭐⭐⭐⭐

Interaktive geografische visualisierungen inklusive weltkarten, choropleth-karten und räumliche datenanalyse

⏱️ 50 min 🏷️ d3, maps, geographic, spatial
Prerequisites: Advanced D3.js, Geographic data concepts, TopoJSON, Projections
// D3.js Geographic Maps and Spatial Visualization

// 1. World Map with Data Points
function createWorldMap() {
    const width = 960;
    const height = 500;

    // Create SVG
    const svg = d3.select('#world-map')
        .append('svg')
        .attr('width', width)
        .attr('height', height);

    // Create projection
    const projection = d3.geoNaturalEarth1()
        .scale(width / (2 * Math.PI))
        .translate([width / 2, height / 2]);

    const path = d3.geoPath().projection(projection);

    // Create zoom behavior
    const zoom = d3.zoom()
        .scaleExtent([1, 8])
        .on('zoom', (event) => {
            g.attr('transform', event.transform);
        });

    svg.call(zoom);

    const g = svg.append('g');

    // Sample data points
    const cities = [
        { name: 'New York', lat: 40.7128, lon: -74.0060, population: 8419000, gdp: 1730000 },
        { name: 'London', lat: 51.5074, lon: -0.1278, population: 8982000, gdp: 615000 },
        { name: 'Tokyo', lat: 35.6762, lon: 139.6503, population: 13960000, gdp: 1520000 },
        { name: 'Paris', lat: 48.8566, lon: 2.3522, population: 2161000, gdp: 695000 },
        { name: 'Sydney', lat: -33.8688, lon: 151.2093, population: 5312000, gdp: 387000 },
        { name: 'São Paulo', lat: -23.5505, lon: -46.6333, population: 12330000, gdp: 430000 },
        { name: 'Mumbai', lat: 19.0760, lon: 72.8777, population: 20411000, gdp: 310000 },
        { name: 'Beijing', lat: 39.9042, lon: 116.4074, population: 21540000, gdp: 560000 }
    ];

    // Load world map data
    d3.json('https://cdn.jsdelivr.net/npm/world-atlas@2/countries-110m.json').then(function(world) {
        // Draw countries
        g.selectAll('.country')
            .data(topojson.feature(world, world.objects.countries).features)
            .enter().append('path')
            .attr('class', 'country')
            .attr('d', path)
            .attr('fill', '#e0e0e0')
            .attr('stroke', '#999')
            .attr('stroke-width', 0.5)
            .on('mouseover', function(event, d) {
                d3.select(this)
                    .attr('fill', '#c0c0c0');

                showTooltip(event, `${d.properties.name}`);
            })
            .on('mouseout', function() {
                d3.select(this)
                    .attr('fill', '#e0e0e0');

                hideTooltip();
            });

        // Draw cities
        const cityCircles = g.selectAll('.city')
            .data(cities)
            .enter().append('circle')
            .attr('class', 'city')
            .attr('cx', d => projection([d.lon, d.lat])[0])
            .attr('cy', d => projection([d.lon, d.lat])[1])
            .attr('r', d => Math.sqrt(d.population / 1000000) * 3)
            .attr('fill', '#4e79a7')
            .attr('opacity', 0.7)
            .attr('stroke', '#fff')
            .attr('stroke-width', 1)
            .on('mouseover', function(event, d) {
                d3.select(this)
                    .transition()
                    .duration(200)
                    .attr('r', d => Math.sqrt(d.population / 1000000) * 4)
                    .attr('opacity', 1);

                showTooltip(event, `
                    <strong>${d.name}</strong><br>
                    Population: ${d3.format(',')(d.population)}<br>
                    GDP: $${d3.format(',.0f')(d.gdp)}M
                `);
            })
            .on('mouseout', function(event, d) {
                d3.select(this)
                    .transition()
                    .duration(200)
                    .attr('r', d => Math.sqrt(d.population / 1000000) * 3)
                    .attr('opacity', 0.7);

                hideTooltip();
            });

        // Add city labels
        g.selectAll('.city-label')
            .data(cities)
            .enter().append('text')
            .attr('class', 'city-label')
            .attr('x', d => projection([d.lon, d.lat])[0])
            .attr('y', d => projection([d.lon, d.lat])[1] - 10)
            .attr('text-anchor', 'middle')
            .attr('font-size', '10px')
            .attr('font-weight', 'bold')
            .attr('fill', '#333')
            .text(d => d.name);
    });
}

// 2. Choropleth Map
function createChoroplethMap() {
    const width = 800;
    const height = 500;

    // Create SVG
    const svg = d3.select('#choropleth-map')
        .append('svg')
        .attr('width', width)
        .attr('height', height);

    // Create projection for US states
    const projection = d3.geoAlbersUsa()
        .scale(1000)
        .translate([width / 2, height / 2]);

    const path = d3.geoPath().projection(projection);

    // Sample data for US states
    const stateData = {
        'California': 39500000,
        'Texas': 29100000,
        'Florida': 21500000,
        'New York': 20200000,
        'Pennsylvania': 12900000,
        'Illinois': 12600000,
        'Ohio': 11700000,
        'Georgia': 10700000,
        'North Carolina': 10600000,
        'Michigan': 10000000
    };

    // Create color scale
    const colorScale = d3.scaleThreshold()
        .domain([10000000, 20000000, 30000000, 40000000])
        .range(['#fee5d9', '#fcae91', '#fb6a4a', '#de2d26', '#a50f15']);

    // Load US states data
    d3.json('https://cdn.jsdelivr.net/npm/us-atlas@3/states-10m.json').then(function(us) {
        // Draw states
        svg.selectAll('.state')
            .data(topojson.feature(us, us.objects.states).features)
            .enter().append('path')
            .attr('class', 'state')
            .attr('d', path)
            .attr('fill', d => {
                const population = stateData[d.properties.name] || 0;
                return colorScale(population);
            })
            .attr('stroke', '#fff')
            .attr('stroke-width', 1)
            .on('mouseover', function(event, d) {
                d3.select(this)
                    .attr('stroke', '#333')
                    .attr('stroke-width', 2);

                const population = stateData[d.properties.name] || 0;
                showTooltip(event, `
                    <strong>${d.properties.name}</strong><br>
                    Population: ${d3.format(',')(population)}
                `);
            })
            .on('mouseout', function() {
                d3.select(this)
                    .attr('stroke', '#fff')
                    .attr('stroke-width', 1);

                hideTooltip();
            });

        // Create legend
        const legend = svg.append('g')
            .attr('class', 'legend')
            .attr('transform', 'translate(650, 300)');

        legend.append('text')
            .attr('x', 0)
            .attr('y', -10)
            .text('Population')
            .style('font-weight', 'bold');

        const legendItems = legend.selectAll('.legend-item')
            .data(colorScale.range())
            .enter().append('g')
            .attr('class', 'legend-item')
            .attr('transform', (d, i) => `translate(0, ${i * 20})`);

        legendItems.append('rect')
            .attr('width', 18)
            .attr('height', 18)
            .attr('fill', d => d);

        legendItems.append('text')
            .attr('x', 24)
            .attr('y', 9)
            .attr('dy', '0.35em')
            .text((d, i) => {
                const thresholds = [10000000, 20000000, 30000000, 40000000];
                return i === 0 ? `< ${d3.format(',')(thresholds[0])}` :
                       i === thresholds.length ? `> ${d3.format(',')(thresholds[thresholds.length - 1])}` :
                       `${d3.format(',')(thresholds[i-1])} - ${d3.format(',')(thresholds[i])}`;
            });
    });
}

// 3. Flight Routes Map
function createFlightRoutesMap() {
    const width = 1000;
    const height = 600;

    // Create SVG
    const svg = d3.select('#flight-routes-map')
        .append('svg')
        .attr('width', width)
        .attr('height', height);

    // Create projection
    const projection = d3.geoNaturalEarth1()
        .scale(width / (2 * Math.PI))
        .translate([width / 2, height / 2]);

    const path = d3.geoPath().projection(projection);

    // Sample airport data
    const airports = [
        { iata: 'JFK', name: 'New York JFK', lat: 40.6413, lon: -73.7781 },
        { iata: 'LAX', name: 'Los Angeles LAX', lat: 33.9425, lon: -118.4081 },
        { iata: 'ORD', name: 'Chicago O\'Hare', lat: 41.9742, lon: -87.9073 },
        { iata: 'DFW', name: 'Dallas DFW', lat: 32.8998, lon: -97.0403 },
        { iata: 'DEN', name: 'Denver DEN', lat: 39.8617, lon: -104.6731 },
        { iata: 'SFO', name: 'San Francisco SFO', lat: 37.6213, lon: -122.3790 },
        { iata: 'SEA', name: 'Seattle SEA', lat: 47.4502, lon: -122.3088 },
        { iata: 'LAS', name: 'Las Vegas LAS', lat: 36.0840, lon: -115.1537 },
        { iata: 'PHX', name: 'Phoenix PHX', lat: 33.4484, lon: -112.0740 },
        { iata: 'IAH', name: 'Houston IAH', lat: 29.9902, lon: -95.3368 }
    ];

    // Sample flight routes
    const routes = [
        { from: 'JFK', to: 'LAX', passengers: 45000 },
        { from: 'JFK', to: 'SFO', passengers: 28000 },
        { from: 'LAX', to: 'ORD', passengers: 32000 },
        { from: 'ORD', to: 'DFW', passengers: 35000 },
        { from: 'DFW', to: 'IAH', passengers: 41000 },
        { from: 'SFO', to: 'SEA', passengers: 22000 },
        { from: 'DEN', to: 'LAS', passengers: 18000 },
        { from: 'PHX', to: 'LAX', passengers: 25000 },
        { from: 'SEA', to: 'SFO', passengers: 26000 },
        { from: 'LAS', to: 'PHX', passengers: 20000 }
    ];

    // Load world map
    d3.json('https://cdn.jsdelivr.net/npm/world-atlas@2/countries-110m.json').then(function(world) {
        // Draw countries
        svg.append('g')
            .selectAll('.country')
            .data(topojson.feature(world, world.objects.countries).features)
            .enter().append('path')
            .attr('class', 'country')
            .attr('d', path)
            .attr('fill', '#f0f0f0')
            .attr('stroke', '#ddd')
            .attr('stroke-width', 0.5);

        // Create route lines
        const routeLines = svg.append('g')
            .selectAll('.route')
            .data(routes)
            .enter().append('path')
            .attr('class', 'route')
            .attr('d', d => {
                const from = airports.find(a => a.iata === d.from);
                const to = airports.find(a => a.iata === d.to);

                const fromPoint = projection([from.lon, from.lat]);
                const toPoint = projection([to.lon, to.lat]);

                // Create curved path
                const midX = (fromPoint[0] + toPoint[0]) / 2;
                const midY = (fromPoint[1] + toPoint[1]) / 2 - 100;

                return `M ${fromPoint[0]},${fromPoint[1]} Q ${midX},${midY} ${toPoint[0]},${toPoint[1]}`;
            })
            .attr('fill', 'none')
            .attr('stroke', '#4e79a7')
            .attr('stroke-width', d => Math.sqrt(d.passengers / 10000))
            .attr('opacity', 0.3)
            .on('mouseover', function(event, d) {
                d3.select(this)
                    .transition()
                    .duration(200)
                    .attr('opacity', 0.8)
                    .attr('stroke', '#f28e2c');

                const from = airports.find(a => a.iata === d.from);
                const to = airports.find(a => a.iata === d.to);

                showTooltip(event, `
                    ${from.name} → ${to.name}<br>
                    Passengers: ${d3.format(',')(d.passengers)}
                `);
            })
            .on('mouseout', function() {
                d3.select(this)
                    .transition()
                    .duration(200)
                    .attr('opacity', 0.3)
                    .attr('stroke', '#4e79a7');

                hideTooltip();
            });

        // Draw airports
        svg.selectAll('.airport')
            .data(airports)
            .enter().append('circle')
            .attr('class', 'airport')
            .attr('cx', d => projection([d.lon, d.lat])[0])
            .attr('cy', d => projection([d.lon, d.lat])[1])
            .attr('r', 4)
            .attr('fill', '#e15759')
            .attr('stroke', '#fff')
            .attr('stroke-width', 2)
            .on('mouseover', function(event, d) {
                d3.select(this)
                    .transition()
                    .duration(200)
                    .attr('r', 6);

                showTooltip(event, `
                    <strong>${d.iata}</strong><br>
                    ${d.name}<br>
                    Lat: ${d.lat.toFixed(2)}<br>
                    Lon: ${d.lon.toFixed(2)}
                `);
            })
            .on('mouseout', function() {
                d3.select(this)
                    .transition()
                    .duration(200)
                    .attr('r', 4);

                hideTooltip();
            });

        // Add airport labels
        svg.selectAll('.airport-label')
            .data(airports)
            .enter().append('text')
            .attr('class', 'airport-label')
            .attr('x', d => projection([d.lon, d.lat])[0])
            .attr('y', d => projection([d.lon, d.lat])[1] + 15)
            .attr('text-anchor', 'middle')
            .attr('font-size', '10px')
            .attr('font-weight', 'bold')
            .attr('fill', '#333')
            .text(d => d.iata);
    });
}

// 4. Interactive Heatmap
function createHeatmap() {
    const data = [];
    const days = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'];
    const hours = Array.from({ length: 24 }, (_, i) => i);

    // Generate sample heatmap data
    for (let day = 0; day < days.length; day++) {
        for (let hour = 0; hour < 24; hour++) {
            data.push({
                day: days[day],
                hour: hour,
                value: Math.random() * 100,
                dayIndex: day,
                hourIndex: hour
            });
        }
    }

    const margin = { top: 50, right: 30, bottom: 30, left: 50 };
    const width = 800 - margin.left - margin.right;
    const height = 400 - margin.top - margin.bottom;
    const cellSize = Math.floor(width / 24);

    // Create SVG
    const svg = d3.select('#heatmap')
        .append('svg')
        .attr('width', width + margin.left + margin.right)
        .attr('height', height + margin.top + margin.bottom)
        .append('g')
        .attr('transform', `translate(${margin.left},${margin.top})`);

    // Create color scale
    const colorScale = d3.scaleSequential(d3.interpolateYlOrRd)
        .domain([0, 100]);

    // Create cells
    svg.selectAll('.cell')
        .data(data)
        .enter().append('rect')
        .attr('class', 'cell')
        .attr('x', d => d.hour * cellSize)
        .attr('y', d => d.day * cellSize)
        .attr('width', cellSize)
        .attr('height', cellSize)
        .attr('fill', d => colorScale(d.value))
        .attr('stroke', '#fff')
        .attr('stroke-width', 1)
        .on('mouseover', function(event, d) {
            d3.select(this)
                .attr('stroke', '#333')
                .attr('stroke-width', 2);

            showTooltip(event, `
                <strong>${days[d.dayIndex]} ${String(d.hour).padStart(2, '0')}:00</strong><br>
                Activity: ${d.value.toFixed(1)}%
            `);
        })
        .on('mouseout', function() {
            d3.select(this)
                .attr('stroke', '#fff')
                .attr('stroke-width', 1);

            hideTooltip();
        });

    // Add day labels
    svg.selectAll('.day-label')
        .data(days)
        .enter().append('text')
        .attr('class', 'day-label')
        .attr('x', -10)
        .attr('y', (d, i) => i * cellSize + cellSize / 2)
        .attr('dy', '0.35em')
        .attr('text-anchor', 'end')
        .style('font-size', '12px')
        .text(d => d);

    // Add hour labels
    svg.selectAll('.hour-label')
        .data(hours)
        .enter().append('text')
        .attr('class', 'hour-label')
        .attr('x', (d, i) => i * cellSize + cellSize / 2)
        .attr('y', height + 20)
        .attr('text-anchor', 'middle')
        .style('font-size', '12px')
        .text(d => d);

    // Add title
    svg.append('text')
        .attr('x', width / 2)
        .attr('y', -20)
        .attr('text-anchor', 'middle')
        .style('font-size', '16px')
        .style('font-weight', 'bold')
        .text('Weekly Activity Heatmap');
}

// Utility functions
function showTooltip(event, content) {
    const tooltip = d3.select('body').append('div')
        .attr('class', 'tooltip')
        .style('position', 'absolute')
        .style('background', 'rgba(0,0,0,0.8)')
        .style('color', 'white')
        .style('padding', '10px')
        .style('border-radius', '4px')
        .style('pointer-events', 'none')
        .style('font-size', '12px')
        .style('max-width', '200px')
        .style('opacity', 0);

    tooltip.transition()
        .duration(200)
        .style('opacity', 1);

    tooltip.html(content)
        .style('left', (event.pageX + 10) + 'px')
        .style('top', (event.pageY - 10) + 'px');
}

function hideTooltip() {
    d3.selectAll('.tooltip').remove();
}

// Initialize all maps
document.addEventListener('DOMContentLoaded', function() {
    createWorldMap();
    createChoroplethMap();
    createFlightRoutesMap();
    createHeatmap();
});