From 74961d1c868e47429fc1206679f0c9ba09b75ab5 Mon Sep 17 00:00:00 2001 From: Pierre <73789471+R2Jeu-prive@users.noreply.github.com> Date: Tue, 15 Apr 2025 15:32:13 +0200 Subject: [PATCH] Add selfJoin option for doughnut graphs (#12054) Co-authored-by: Pierre Gueguen --- src/elements/element.arc.ts | 42 +++++++++++++++++- src/types/index.d.ts | 6 +++ .../controller.doughnut/selfJoin/doughnut.js | 25 +++++++++++ .../controller.doughnut/selfJoin/doughnut.png | Bin 0 -> 14751 bytes .../controller.doughnut/selfJoin/pie.js | 26 +++++++++++ .../controller.doughnut/selfJoin/pie.png | Bin 0 -> 11313 bytes 6 files changed, 97 insertions(+), 2 deletions(-) create mode 100644 test/fixtures/controller.doughnut/selfJoin/doughnut.js create mode 100644 test/fixtures/controller.doughnut/selfJoin/doughnut.png create mode 100644 test/fixtures/controller.doughnut/selfJoin/pie.js create mode 100644 test/fixtures/controller.doughnut/selfJoin/pie.png diff --git a/src/elements/element.arc.ts b/src/elements/element.arc.ts index e2bd26f52..42f41f045 100644 --- a/src/elements/element.arc.ts +++ b/src/elements/element.arc.ts @@ -1,9 +1,42 @@ import Element from '../core/core.element.js'; import {_angleBetween, getAngleFromPoint, TAU, HALF_PI, valueOrDefault} from '../helpers/index.js'; -import {PI, _isBetween, _limitValue} from '../helpers/helpers.math.js'; +import {PI, _angleDiff, _normalizeAngle, _isBetween, _limitValue} from '../helpers/helpers.math.js'; import {_readValueToProps} from '../helpers/helpers.options.js'; import type {ArcOptions, Point} from '../types/index.js'; +function clipSelf(ctx: CanvasRenderingContext2D, element: ArcElement, endAngle: number) { + const {startAngle, x, y, outerRadius, innerRadius, options} = element; + const {borderWidth, borderJoinStyle} = options; + const outerAngleClip = Math.min(borderWidth / outerRadius, _normalizeAngle(startAngle - endAngle)); + ctx.beginPath(); + ctx.arc(x, y, outerRadius - borderWidth / 2, startAngle + outerAngleClip / 2, endAngle - outerAngleClip / 2); + + if (innerRadius > 0) { + const innerAngleClip = Math.min(borderWidth / innerRadius, _normalizeAngle(startAngle - endAngle)); + ctx.arc(x, y, innerRadius + borderWidth / 2, endAngle - innerAngleClip / 2, startAngle + innerAngleClip / 2, true); + } else { + const clipWidth = Math.min(borderWidth / 2, outerRadius * _normalizeAngle(startAngle - endAngle)); + + if (borderJoinStyle === 'round') { + ctx.arc(x, y, clipWidth, endAngle - PI / 2, startAngle + PI / 2, true); + } else if (borderJoinStyle === 'bevel') { + const r = 2 * clipWidth * clipWidth; + const endX = -r * Math.cos(endAngle + PI / 2) + x; + const endY = -r * Math.sin(endAngle + PI / 2) + y; + const startX = r * Math.cos(startAngle + PI / 2) + x; + const startY = r * Math.sin(startAngle + PI / 2) + y; + ctx.lineTo(endX, endY); + ctx.lineTo(startX, startY); + } + } + ctx.closePath(); + + ctx.moveTo(0, 0); + ctx.rect(0, 0, ctx.canvas.width, ctx.canvas.height); + + ctx.clip('evenodd'); +} + function clipArc(ctx: CanvasRenderingContext2D, element: ArcElement, endAngle: number) { const {startAngle, pixelMargin, x, y, outerRadius, innerRadius} = element; @@ -213,7 +246,7 @@ function drawBorder( circular: boolean, ) { const {fullCircles, startAngle, circumference, options} = element; - const {borderWidth, borderJoinStyle, borderDash, borderDashOffset} = options; + const {borderWidth, borderJoinStyle, borderDash, borderDashOffset, borderRadius} = options; const inner = options.borderAlign === 'inner'; if (!borderWidth) { @@ -246,6 +279,10 @@ function drawBorder( clipArc(ctx, element, endAngle); } + if (options.selfJoin && endAngle - startAngle >= PI && borderRadius === 0 && borderJoinStyle !== 'miter') { + clipSelf(ctx, element, endAngle); + } + if (!fullCircles) { pathArc(ctx, element, offset, spacing, endAngle, circular); ctx.stroke(); @@ -276,6 +313,7 @@ export default class ArcElement extends Element { spacing: 0, angle: undefined, circular: true, + selfJoin: false, }; static defaultRoutes = { diff --git a/src/types/index.d.ts b/src/types/index.d.ts index 807fe8208..175336ec7 100644 --- a/src/types/index.d.ts +++ b/src/types/index.d.ts @@ -1847,6 +1847,12 @@ export interface ArcBorderRadius { } export interface ArcOptions extends CommonElementOptions { + /** + * If true, Arc can take up 100% of a circular graph without any visual split or cut. This option doesn't support borderRadius and borderJoinStyle miter + * @default true + */ + selfJoin: boolean; + /** * Arc stroke alignment. */ diff --git a/test/fixtures/controller.doughnut/selfJoin/doughnut.js b/test/fixtures/controller.doughnut/selfJoin/doughnut.js new file mode 100644 index 000000000..f29939cec --- /dev/null +++ b/test/fixtures/controller.doughnut/selfJoin/doughnut.js @@ -0,0 +1,25 @@ +module.exports = { + config: { + type: 'doughnut', + data: { + labels: ['Red'], + datasets: [ + { + // option in dataset + data: [100], + borderWidth: 15, + backgroundColor: '#FF0000', + borderColor: '#000000', + borderAlign: 'center', + selfJoin: true + } + ] + } + }, + options: { + canvas: { + height: 256, + width: 512 + } + } +}; diff --git a/test/fixtures/controller.doughnut/selfJoin/doughnut.png b/test/fixtures/controller.doughnut/selfJoin/doughnut.png new file mode 100644 index 0000000000000000000000000000000000000000..af2d4b438736b45f0b08649e41050d3a17cb5da4 GIT binary patch literal 14751 zcmY*=cRbbc+xPbz2M6Jp*?aGiy_IZFQ0Mk>-t>R`x~dPr%p^rM+g7_v8Kj70|0=6zd`^w9{A&X%8�FK+{N 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 literal 0 HcmV?d00001 diff --git a/test/fixtures/controller.doughnut/selfJoin/pie.js b/test/fixtures/controller.doughnut/selfJoin/pie.js new file mode 100644 index 000000000..d0187db09 --- /dev/null +++ b/test/fixtures/controller.doughnut/selfJoin/pie.js @@ -0,0 +1,26 @@ +module.exports = { + config: { + type: 'pie', + data: { + labels: ['Red'], + datasets: [ + { + // option in dataset + data: [100], + borderWidth: 15, + backgroundColor: '#FF0000', + borderColor: '#000000', + borderAlign: 'center', + borderJoinStyle: 'round', + selfJoin: true + } + ] + } + }, + options: { + canvas: { + height: 256, + width: 512 + } + } +}; diff --git a/test/fixtures/controller.doughnut/selfJoin/pie.png b/test/fixtures/controller.doughnut/selfJoin/pie.png new file mode 100644 index 0000000000000000000000000000000000000000..17a2e3b195132b5cc05f35a951c352acd0b9b0aa GIT binary patch literal 11313 zcmY*XHGXXMCU z5wgecKJ|HjfA9BSc)0HCb-kX~bv>_f-?7GqT2yCP&p;p$DjjVNQwRhAe}zKeWZ;kX zlpc5DUw)=qYLK!X_9X~}8=|A3dNtT?Et9;#Rr66tWEbu}PXUh(E#uP{j|#a}ZD9=8 z&kMroHRzy>8qBj(j>-UFcF?JmoHVh!!;YL3@5-c4tbS#D{aedt!WYVFG#b zJAD1k;)|lPgWrw2!^)Gkzqu^+@vwA5f-U|-t30L>zn#}ieO&)M4xbHViJWAy&6%H; zMTWBMDf(Lf8uJg_nSv?k5mXe|8cAd^ZgiHA;Dr>?gV@v35!KE<7u2cpugEDy?Em4nLJpcH!E5gbm?JG2ERmKJmVjl`O>&9EAQE3*UwPjL*(@%(HzoN~V$n#nKDYNr z7(HCrI&8WeT0)(mS7Gix^h@&`&IJ{zODoLp0Fay`z#LEnWv>FnqMn`o&Ve;mS_9LR zw4f2tD*70z%(tgL0+F*rvYdwsK%(;3E8l1kc=7Z2XgsCundW56Y-j|@3(6OhF4uu;hLs|Z%$4c8Zj#X3aOY`ugYL{p&8Ls zKGu-xKsL>~MJ}iz)KCOVQFXSC2e~K#9%!2t-jNlL7it$h?ndABJ6oGchnTo_p2Uj3 zp(g>v_y>r_Lw9!rQMXXk!t`N|69JzMO2N-(4?OE4P{0=^W-&7Ac*i=zq zFIHj+#$h?fE+7l(K)a;VDc^wq(gQ*nGY)Pp;WAkt;Su-~yvV#Wz%NF$yhT#q!3AK0 zghtygtgsm8A#7;V&mD6!*z^~-!}J~CL=g^s2UDPnM1{;kCe4DbfoxQK&}GlBIQNbi ze+mkZKmkg{b#Ztl{4Ux^MqEf5X}o|-jmwN3fcQYO1Vi?Uws9we6v01MyfksijK`7Y z(MFNWhsD=^BQ1XCKEp7#&68)g9`gF$sE*&`vKC${EUj#ZDHwo?3ks&*F~eFc!Y(Wx zR@UWGx_YBD$p_E*PHz-C_56qrp*2(?FI4Nb&Dng^Gh@q<&St}qq+K{;)UCPS9Tb1R ze7Hn~e=op4z}cbe2Zg=;iSzQ}Ed26YE3bF0XXIWB{mIk7p;S z>SVGB3Zc0myV3QHH7Dn3i0$z0cgfHo%06-$Z{Q`pFJLTW$HpZFRbC!3o9~SD5+w`c z*fYNU^cJ3-RsLwkQRRcYro=}5I}Kb6GMhAs>&ph`5O_DxNSl_r%PfGx^2wGlnZ=u< zi>c)dw)ZBGa-xBZJ1Qk|RgXsQ7!4be)`{o}ZRZo>^>GN;3y72>cGX!0R#X2|-ytXB zscG5J%!A|iU+X#0OQw|9gW_QRAt=S)HTk&;Fvd76P;;K3dyi3V*LaR-=_PyXaxD7h zZt>4hJ_*m;SYxf-S7k05G!l>S7ah$yZnS?>7Gb<9_=b^&SBSk|{W(e=Jn?DUkVP>c zZYEp+STPr09gnxqS*D+rHD>&v#Who#dw|PonXt{gs8CZOZ+!cwi7lG*H5=?`e<<

Q0Zb{8`W9P+^<9!Lk<*{ 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 bQxd9MpOr03uAc+H0fy*k8fuiOIo$hyfUQq9 literal 0 HcmV?d00001