import { select, event, svg } from 'd3'; export default function initGraph(options) { const { el, width, height, margin, thickness, fontSize } = getConfig(options); const svg = select(el).append('svg') .attr('width', width).attr('height', height); let { value, ticks, mode } = options 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, mode); return { updateTitle(text) { titleLabel.text(text); }, updateSubTitle(text) { subtitleLabel.text(text); }, updateValue(text) { const { width, height, margin, thickness } = getConfig({ el }); svg.attr('width', width).attr('height', height); 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, mode); }, }; } function fit(svg, el, value, ticks, tooltip, valuePath, maxPath, valueLabel, titleLabel, subtitleLabel, mode) { 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, mode); 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, Math.min(value, 100), 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 = select('#percent-gauge-tooltip'); if (tooltip.empty()) { tooltip = 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 > 100 ? 100 : value); return { valuePath, maxPath, }; } function getValueLabelY(height, fontSize) { return height / 5 + fontSize / 1.2; } function getTitleLabelY(height, fontSize, mode) { if (mode === 'monitoring') { return height / 5 + 4.3 * fontSize; } return height / 5 + 1.9 * fontSize; } function getSubtitleLabelY(height, fontSize, mode) { if (mode === 'monitoring') { return height / 5 + 1.7 * fontSize; } return height / 5 + 2.5 * fontSize; } function addLabels(svg, options, width, height, fontSize, mode) { const valueClass = (mode === 'monitoring' ? 'reservedPercent' : 'value') return { valueLabel: addText(options.value ? `${ options.value }%` : '0%', svg, width / 2, getValueLabelY(height, fontSize), fontSize, valueClass, 3.5), titleLabel: addText(options.title, svg, width / 2, getTitleLabelY(height, fontSize, mode), fontSize / 3, 'title', mode), subtitleLabel: addText(options.subtitle, svg, width / 2, getSubtitleLabelY(height, fontSize, mode), fontSize / 3, 'subtitle', mode), } } function repaintLabels(valueLabel, titleLabel, subtitleLabel, width, height, fontSize, mode) { 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, mode)) .attr('dy', fontSize / 6) .style('font-size', `${ fontSize / 3 }px`); subtitleLabel.attr('x', width / 2) .attr('y', getSubtitleLabelY(height, fontSize, mode)) .attr('dy', fontSize / 6) .style('font-size', `${ fontSize / 3 }px`); } function addTicks(svg, tooltip, width, height, margin, ticks, currentValue, thickness) { let { max, min } = getRange(ticks); (ticks || []).forEach((tick) => { if (tick.value !== 0 && !tick.value) { return } let value = parseInt(tick.value, 10); if ((value !== max && value !== min) || max === min) { return } if (min === value && value === currentValue && value !== 0) { value -= 1 } if (max === value && value === currentValue && max !== 100) { value += 1 } 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') } |
|---|