export default function initGraph(options) { const { el, width, height, margin, thickness, fontSize } = getConfig(options); const svg = d3.select(el).append('svg') .attr('width', width).attr('height', height); let value = options.value; let ticks = options.ticks; const { valuePath, maxPath } = addArcValue(svg, width, margin, thickness, options.value); let tooltip = addTooltip(); addTicks(svg, tooltip, width, height, margin, ticks, options.value, thickness); const { valueLabel, titleLabel, subtitleLabel } = addLabels(svg, options, width, height, fontSize); return { updateTitle(text) { titleLabel.text(text); }, updateSubTitle(text) { subtitleLabel.text(text); }, updateValue(text) { text = text ? `${text}%` : ''; valueLabel.text(text); if (text) { value = parseInt(text, 10); const r = calcR(width, margin); valuePath.attr('d', createArc(-135, value, r, thickness)); } }, updateTicks(t) { ticks = t; repaintTicks(svg, tooltip, width, height, margin, ticks, value, thickness); }, fit() { fit(svg, el, value, ticks, tooltip, valuePath, maxPath, valueLabel, titleLabel, subtitleLabel); }, }; } function fit(svg, el, value, ticks, tooltip, valuePath, maxPath, valueLabel, titleLabel, subtitleLabel) { const { width, height, margin, thickness, fontSize } = getConfig({ el }); svg.attr('width', width).attr('height', height); repaintArc(width, margin, value, thickness, valuePath, maxPath); repaintLabels(valueLabel, titleLabel, subtitleLabel, width, height, fontSize); repaintTicks(svg, tooltip, width, height, margin, ticks, value, thickness); } function repaintTicks(svg, tooltip, width, height, margin, ticks, value, thickness) { svg.selectAll('path[tick = "custom"]').remove(); svg.selectAll('circle[tick = "custom"]').remove(); addTicks(svg, tooltip, width, height, margin, ticks, value, thickness); } function repaintArc(width, margin, value, thickness, valuePath, maxPath) { const r = calcR(width, margin); valuePath.attr('d', createArc(-135, value, r, thickness)) .attr('transform', 'translate(' + (margin + r) + ',' + (margin + r) + '), scale(1, 1)'); maxPath.attr('d', createArc(-135, 100, r, thickness)) .attr('transform', 'translate(' + (margin + r) + ',' + (margin + r) + '), scale(1, 1)'); } function addTooltip() { let tooltip = d3.select('#percent-gauge-tooltip'); if (tooltip.empty()) { tooltip = d3.select("body").append("div") .attr('class', 'hover-label') .attr("class", "percent-gauge-tooltip") .attr("id", "percent-gauge-tooltip") .style("opacity", 0); } return tooltip; } function addArcValue(svg, width, margin, thickness, value) { const maxPath = addArc(svg, width, margin, thickness, 'gauge-max-path', 100); const valuePath = addArc(svg, width, margin, thickness, 'gauge-value-path', value); return { valuePath, maxPath, }; } function getValueLabelY(height, fontSize) { return height / 5 + fontSize / 1.2; } function getTitleLabelY(height, fontSize) { return height / 5 + 1.9 * fontSize; } function getSubtitleLabelY(height, fontSize) { return height / 5 + 2.5 * fontSize; } function addLabels(svg, options, width, height, fontSize) { return { valueLabel: addText(options.value ? `${options.value}%` : '0%', svg, width / 2, getValueLabelY(height, fontSize), fontSize, 'value', 3.5), titleLabel: addText(options.title, svg, width / 2, getTitleLabelY(height, fontSize), fontSize / 3, 'title'), subtitleLabel: addText(options.subtitle, svg, width / 2, getSubtitleLabelY(height, fontSize), fontSize / 3, 'subtitle'), } } function repaintLabels(valueLabel, titleLabel, subtitleLabel, width, height, fontSize) { valueLabel.attr("x", width / 2) .attr("y", getValueLabelY(height, fontSize)) .attr("dy", fontSize / 2) .style("font-size", fontSize + "px"); titleLabel.attr("x", width / 2) .attr("y", getTitleLabelY(height, fontSize)) .attr("dy", fontSize / 6) .style("font-size", fontSize / 3 + "px"); subtitleLabel.attr("x", width / 2) .attr("y", getSubtitleLabelY(height, fontSize)) .attr("dy", fontSize / 6) .style("font-size", fontSize / 3 + "px"); } function addTicks(svg, tooltip, width, height, margin, ticks, currentValue, thickness) { let max; let min; (ticks || []).forEach(tick => { if (tick.value !== 0 && !tick.value) { return } const value = parseInt(tick.value, 10); max = (max === undefined || value > max) ? value : max; min = (min === undefined || value < min) ? value : min; const point = valueToPoint(width, height, margin, value, thickness); if (ticks.length > 1) { let tr = ''; tick.labels.forEach(label => { tr += `
| ${window.l('service:intl').t('clusterDashboard.node')} | ${window.l('service:intl').t('clusterDashboard.value')} |
|---|