1function renderSimpleChart(containerElement, rawData) { 2 d3.select(containerElement).select("svg").remove(); 3 4 const highlightColor = document.querySelector('[data-highlightcolor]')?.dataset.highlightcolor || ''; 5 const chartBackground = document.querySelector('[data-chartbackground]')?.dataset.chartbackground || ''; 6 7 const parseTime = d3.utcParse("%Y-%m-%d"); 8 const parsed = rawData.map(([dateStr, valueStr]) => ({ 9 time: parseTime(dateStr), 10 value: parseFloat(valueStr) 11 })).filter(d => d.time && !isNaN(d.value)); 12 13 const maxDate = d3.max(parsed, d => d.time); 14 const threeYearsAgo = d3.timeYear.offset(maxDate, -3); 15 const filtered = parsed.filter(d => d.time >= threeYearsAgo); 16 const baseValue = filtered[0]?.value || 1; 17 const formattedData = filtered.map(d => ({ 18 time: d.time, 19 value: ((d.value / baseValue) - 1) * 100 20 })); 21 22 formattedData.forEach(d => { 23 d.value = Math.round(d.value * 100) / 100; 24 }); 25 26 const margin = { top: 10, right: 10, bottom: 30, left: 10 }, 27 containerWidth = containerElement.getBoundingClientRect().width, 28 containerHeight = 250, 29 width = containerWidth - margin.left - margin.right, 30 height = containerHeight - margin.top - margin.bottom; 31 32 const minPossibleDate = d3.min(formattedData, d => d.time); 33 const minDate = d3.timeDay.offset((minPossibleDate > threeYearsAgo) ? minPossibleDate : threeYearsAgo, 0); 34 35 const x = d3.scaleTime().domain([minDate, maxDate]).range([0, width]); 36 const padding = 0; 37 const minValue = d3.min(formattedData, d => d.value); 38 const maxValue = d3.max(formattedData, d => d.value); 39 console.log("Y-Domain min/max:", minValue, maxValue); 40 const y = d3.scaleLinear() 41 .domain([ 42 Math.min(0, minValue - padding), 43 Math.max(0, maxValue + padding) 44 ]) 45 .range([height, 0]); 46 47 const germanLocale = d3.timeFormatLocale({ 48 dateTime: "%A, der %e. %B %Y, %X", 49 date: "%d.%m.%Y", 50 time: "%H:%M:%S", 51 periods: ["AM", "PM"], 52 days: ["Sonntag", "Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag"], 53 shortDays: ["So", "Mo", "Di", "Mi", "Do", "Fr", "Sa"], 54 months: ["Januar", "Februar", "März", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Dezember"], 55 shortMonths: ["Jan", "Feb", "Mär", "Apr", "Mai", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dez"] 56 }); 57 const formatDate = germanLocale.format("%b %Y"); 58 59 const xAxisGenerator = d3.axisBottom(x) 60 .tickValues([minDate, maxDate]) 61 .tickFormat(formatDate); 62 const lineGenerator = d3.line() 63 .x(d => x(d.time)) 64 .y(d => y(d.value)); 65 66 67 const svg = d3.select(containerElement) 68 .append('svg') 69 .attr('width', containerWidth) 70 .attr('height', containerHeight); 71 72 const imageWidth = containerWidth * 0.3; 73 svg.append('image') 74 .attr("href", `${chartBackground}/Logos/logo.svg`) 75 .attr('width', imageWidth) 76 .attr('height', (imageWidth / containerWidth) * containerHeight) 77 .attr('x', (containerWidth - imageWidth) / 2) 78 .attr('y', (containerHeight - (imageWidth / containerWidth) * containerHeight) / 2) 79 .style('opacity', 0.2); 80 81 const g = svg.append('g') 82 .attr('transform', `translate(${margin.left},${margin.top})`); 83 g.append("path") 84 .datum(formattedData) 85 .attr("d", lineGenerator) 86 .attr("fill", "none") 87 .attr("stroke", highlightColor) 88 .attr("stroke-width", 1); 89 90 g.append("g") 91 .attr("transform", `translate(0,${height})`) 92 .call(xAxisGenerator) 93 .selectAll("text") 94 .attr("text-anchor", (d, i, nodes) => { 95 if (i === 0) return "start"; 96 if (i === nodes.length - 1) return "end"; 97 return "middle"; 98 }) 99 .attr("dx", (d, i, nodes) => { 100 if (i === 0) return "0.5em"; 101 if (i === nodes.length - 1) return "-0.5em"; 102 return "0"; 103 }); 104} 105 106document.addEventListener('DOMContentLoaded', function () { 107 const chartContainers = Array.from(document.querySelectorAll('[data-js="fondsTileGraph"]')); 108 109 chartContainers.forEach(container => { 110 const jsonEl = container.querySelector('.graphData'); 111 if (jsonEl) { 112 try { 113 const rawData = JSON.parse(jsonEl.textContent); 114 115 let resizeTimer; 116 117 const draw = () => renderSimpleChart(container, rawData); 118 draw(); 119 window.addEventListener('resize', () => { 120 clearTimeout(resizeTimer); 121 resizeTimer = setTimeout(() => { 122 draw(); 123 }, 200); 124 }); 125 } catch (e) { 126 console.error("Ungültiges JSON in graphData", e); 127 } 128 } 129 }); 130});
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.