d3#pie TypeScript Examples
The following examples show how to use
d3#pie.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: PieChart.ts From anichart.js with MIT License | 6 votes |
private getPieData(sec: number) {
const currentData = [...this.dataScales.values()].map((scale) => {
return scale(sec);
});
const minRadio = this.minRadio / 360;
const sumValue = sum(currentData, (d) => d[this.valueField]);
const minValue = sumValue * minRadio;
const pieGen = pie()
.padAngle((Math.PI / 180) * this.padAngle)
.value((d) => max([d[this.valueField], minValue]));
currentData.sort((a, b) => {
if (Number.isNaN(b[this.valueField])) {
return -1;
} else if (Number.isNaN(a[this.valueField])) {
return 1;
} else {
return b[this.idField] - a[this.idField];
}
});
const pieData = pieGen(currentData);
return pieData;
}
Example #2
Source File: PieChart.tsx From grafana-chinese with Apache License 2.0 | 5 votes |
draw() {
const { values, pieType, strokeWidth } = this.props;
if (values.length === 0) {
return;
}
const data = values.map(datapoint => datapoint.numeric);
const names = values.map(datapoint => formattedValueToString(datapoint));
const colors = values.map((p, idx) => {
if (p.color) {
return p.color;
}
return grafana_colors[idx % grafana_colors.length];
});
const total = sum(data) || 1;
const percents = data.map((item: number) => (item / total) * 100);
const width = this.containerElement.offsetWidth;
const height = this.containerElement.offsetHeight;
const radius = Math.min(width, height) / 2;
const outerRadius = radius - radius / 10;
const innerRadius = pieType === PieChartType.PIE ? 0 : radius - radius / 3;
const svg = select(this.svgElement)
.html('')
.attr('width', width)
.attr('height', height)
.append('g')
.attr('transform', `translate(${width / 2},${height / 2})`);
const pieChart = pie();
const customArc = arc()
.outerRadius(outerRadius)
.innerRadius(innerRadius)
.padAngle(0);
svg
.selectAll('path')
.data(pieChart(data))
.enter()
.append('path')
.attr('d', customArc as any)
.attr('fill', (d: any, idx: number) => colors[idx])
.style('fill-opacity', 0.15)
.style('stroke', (d: any, idx: number) => colors[idx])
.style('stroke-width', `${strokeWidth}px`)
.on('mouseover', (d: any, idx: any) => {
select(this.tooltipElement).style('opacity', 1);
select(this.tooltipValueElement).text(`${names[idx]} (${percents[idx].toFixed(2)}%)`);
})
.on('mousemove', () => {
select(this.tooltipElement)
.style('top', `${event.pageY - height / 2}px`)
.style('left', `${event.pageX}px`);
})
.on('mouseout', () => {
select(this.tooltipElement).style('opacity', 0);
});
}
Example #3
Source File: pie.ts From obsidian-tracker with MIT License | 4 votes |
function renderPie(
canvas: HTMLElement,
chartElements: ChartElements,
renderInfo: RenderInfo,
pieInfo: PieInfo
) {
// console.log("renderPie");
// console.log(renderInfo);
let errorMessage = "";
let radius = renderInfo.dataAreaSize.width * 0.5;
let outterRadius = radius * 0.7;
let innerRadius = outterRadius * pieInfo.ratioInnerRadius;
// values
let values: Array<number> = [];
for (let strExpr of pieInfo.data) {
let retValue = expr.resolveValue(strExpr, renderInfo);
if (typeof retValue === "string") {
errorMessage = retValue;
break;
} else if (typeof retValue === "number") {
values.push(retValue);
}
}
if (errorMessage !== "") {
return errorMessage;
}
// console.log(values);
// labels
let labels: Array<string> = [];
for (let strExpr of pieInfo.label) {
let retLabel = expr.resolveTemplate(strExpr, renderInfo);
// console.log(retLabel);
if (retLabel.startsWith("Error")) {
errorMessage = retLabel;
break;
}
labels.push(retLabel);
}
if (errorMessage !== "") {
return errorMessage;
}
// console.log(labels);
// hideLabelLessThan
let hideLabelLessThan = pieInfo.hideLabelLessThan;
// label sizes
let labelSizes = labels.map(function (n) {
return helper.measureTextSize(n, "tracker-tick-label");
});
// extLabel
let extLabels: Array<string> = [];
for (let strExpr of pieInfo.extLabel) {
let retExtLabel = expr.resolveTemplate(strExpr, renderInfo);
if (retExtLabel.startsWith("Error")) {
errorMessage = retExtLabel;
break;
}
extLabels.push(retExtLabel);
}
if (errorMessage !== "") {
return errorMessage;
}
// console.log(extLabels);
// extLabel sizes
let extLabelSizes = extLabels.map(function (n) {
return helper.measureTextSize(n, "tracker-pie-label");
});
// console.log(extLabelSizes);
let showExtLabelOnlyIfNoLabel = pieInfo.showExtLabelOnlyIfNoLabel;
// scale
let colorScale = d3.scaleOrdinal().range(pieInfo.dataColor);
let sectorsGroup = chartElements.dataArea.append("g");
sectorsGroup.attr("transform", function () {
let strTranslate =
"translate(" +
renderInfo.dataAreaSize.width * 0.5 +
"," +
renderInfo.dataAreaSize.height * 0.5 +
")";
return strTranslate;
});
let pie = d3.pie();
let pieValues = pie(values);
let sectors = sectorsGroup
.selectAll("sector")
.data(pieValues)
.enter()
.append("g")
.attr("class", "sector");
let arc = d3.arc().innerRadius(innerRadius).outerRadius(outterRadius);
var hiddenArc = d3
.arc()
.innerRadius(radius * 0.9)
.outerRadius(radius * 0.9);
let sectorPaths = sectors
.append("path")
.attr("fill", function (d: any, i: number) {
return colorScale(i.toString());
})
.attr("d", arc);
function isLabelHidden(arcObj: any) {
// console.log(`start/end: ${arcObj.startAngle}/${arcObj.endAngle}`);
let fraction = (arcObj.endAngle - arcObj.startAngle) / (2.0 * Math.PI);
if (fraction < hideLabelLessThan) {
return true;
}
return false;
}
// label elements
let labelElements = sectorsGroup
.selectAll("label")
.data(pie(values))
.enter()
.append("text")
.text(function (arcObj: any, i: number) {
if (isLabelHidden(arcObj)) {
return "";
}
return labels[i];
})
.attr("transform", function (d: any) {
return (
"translate(" +
arc.centroid(d)[0] +
"," +
arc.centroid(d)[1] +
")"
);
})
.style("text-anchor", "middle")
.attr("class", "tracker-pie-label");
function getMidAngle(arcObj: any) {
return arcObj.startAngle + (arcObj.endAngle - arcObj.startAngle) / 2;
}
// external label elements
let extLabelElements = sectorsGroup
.selectAll("extLabel")
.data(pieValues)
.enter()
.append("text")
.text(function (arcObj: any, i: number) {
if (showExtLabelOnlyIfNoLabel) {
if (labels[i] === "" || isLabelHidden(arcObj)) {
return extLabels[i];
}
return "";
} else {
return extLabels[i];
}
})
.attr("transform", function (arcObj: any, i: number) {
let posLabel = hiddenArc.centroid(arcObj);
let midAngle = getMidAngle(arcObj);
posLabel[0] =
(radius * 0.99 - extLabelSizes[i].width) *
(midAngle < Math.PI ? 1 : -1);
return "translate(" + posLabel[0] + "," + posLabel[1] + ")";
})
.style("text-anchor", function (arcObj: any) {
let midAngle = getMidAngle(arcObj);
return midAngle < Math.PI ? "start" : "end";
})
.attr("class", "tracker-pie-label");
function getPointsForConnectionLines(arcObj: any, i: number) {
let labelWidth = labelSizes[i].width;
let extLabelWidth = extLabelSizes[i].width;
let labelHidden = isLabelHidden(arcObj);
let midAngle = getMidAngle(arcObj);
let posLabel = arc.centroid(arcObj); // line insertion in the slice
let posMiddle = hiddenArc.centroid(arcObj); // line break: we use the other arc generator that has been built only for that
let posExtLabel = hiddenArc.centroid(arcObj); // Label position = almost the same as posB
// console.log(labels[i]);
// console.log(`label/middle/extLabel: ${posLabel}/${posMiddle}/${posExtLabel}`);
let distMiddleToLabel = Math.sqrt(
(posMiddle[0] - posLabel[0]) ** 2 +
(posMiddle[1] - posLabel[1]) ** 2
);
if (labels[i] !== "") {
// shift posLabel, toward the middle point
posLabel[0] =
posLabel[0] +
((posMiddle[0] - posLabel[0]) * labelWidth) / distMiddleToLabel;
posLabel[1] =
posLabel[1] +
((posMiddle[1] - posLabel[1]) * labelWidth) / distMiddleToLabel;
// shift posExtLabel
posExtLabel[0] =
(radius * 0.99 - extLabelWidth - 3) *
(midAngle < Math.PI ? 1 : -1); // multiply by 1 or -1 to put it on the right or on the left
}
distMiddleToLabel = Math.sqrt(
(posMiddle[0] - posLabel[0]) ** 2 +
(posMiddle[1] - posLabel[1]) ** 2
);
let distExtLabelToLabel = Math.sqrt(
(posExtLabel[0] - posLabel[0]) ** 2 +
(posExtLabel[1] - posLabel[1]) ** 2
);
if (distMiddleToLabel > distExtLabelToLabel) {
// console.log("two points");
return [posLabel, posExtLabel];
}
return [posLabel, posMiddle, posExtLabel];
}
// Add lines between sectors and external labels
let lines = sectorsGroup
.selectAll("line")
.data(pieValues)
.enter()
.append("polyline")
.attr("stroke", "black")
.style("fill", "none")
.attr("stroke-width", 1)
.attr("points", function (arcObj: any, i: number) {
if (showExtLabelOnlyIfNoLabel) {
if (labels[i] === "" || isLabelHidden(arcObj)) {
if (extLabels[i] !== "") {
return getPointsForConnectionLines(arcObj, i);
}
}
} else {
if (extLabels[i] !== "") {
return getPointsForConnectionLines(arcObj, i);
}
}
})
.attr("class", "tracker-axis");
}