|
11 | 11 | viewBox="@ViewBox" |
12 | 12 | preserveAspectRatio="@PreserveAspectRatio" |
13 | 13 | overflow="visible" |
14 | | - style="width: 100%; height: 100%;@(Options.ShowBackground ? $" background-color: {Options.BackgroundColor};" : "")"> |
| 14 | + style="@GetSvgElementStyle()"> |
15 | 15 |
|
16 | 16 | <defs> |
17 | 17 | @* Gradients for tile faces *@ |
|
111 | 111 |
|
112 | 112 | @foreach (var depth in allDepths) |
113 | 113 | { |
114 | | - @if (UsesBezierCurves) |
| 114 | + @if (UsesBezierCurves && ConnectorOptions.ConnectionMode != ConnectionMode.ColumnCurves) |
115 | 115 | { |
116 | | - @* For curve modes: render tiles first, then connectors (curves go on top of their source row) *@ |
| 116 | + @* For row curve modes: render tiles first, then connectors (curves go on top of their source row) *@ |
117 | 117 | @foreach (var tile in tiles.Where(t => t.Depth == depth)) |
118 | 118 | { |
119 | 119 | @RenderTile(tile) |
|
129 | 129 | } |
130 | 130 | else |
131 | 131 | { |
132 | | - @* For straight-line mode: render connectors first (behind tiles at this depth) *@ |
| 132 | + @* For straight-line mode and column curves: render connectors first (behind tiles at this depth) *@ |
133 | 133 | @if (connectorsByDepth.TryGetValue(depth, out var depthConnectors)) |
134 | 134 | { |
135 | 135 | @foreach (var conn in depthConnectors) |
|
149 | 149 | </div> |
150 | 150 |
|
151 | 151 | @* Child content - overlaid on top of the tile grid *@ |
152 | | - @if (ChildContent != null) |
| 152 | + @if (ChildContent != null && !Options.ContentWrapping) |
153 | 153 | { |
154 | 154 | <div class="pd-tiles-content" style="@GetChildContentStyle()"> |
155 | 155 | @ChildContent |
156 | 156 | </div> |
157 | 157 | } |
| 158 | + else if (ChildContent != null && Options.ContentWrapping) |
| 159 | + { |
| 160 | + <div class="pd-tiles-content-wrap" style="@GetChildContentWrapStyle()"> |
| 161 | + @* Invisible float spacer matching the grid area *@ |
| 162 | + <div class="pd-tiles-float-spacer" style="@GetFloatSpacerStyle()"></div> |
| 163 | + @ChildContent |
| 164 | + </div> |
| 165 | + } |
158 | 166 | </div> |
159 | 167 |
|
160 | 168 | @code { |
|
308 | 316 | @if (pattern == ConnectorFillPattern.Bars) |
309 | 317 | { |
310 | 318 | <g clip-path="url(#@clipId)"> |
311 | | - @RenderBarsPattern(t0, t1, b0, b1, color, opacity) |
| 319 | + @RenderBarsPattern(t0, t1, b0, b1, color, opacity, conn.Connector.Reversed) |
312 | 320 | </g> |
313 | 321 | } |
314 | 322 | else if (pattern == ConnectorFillPattern.Chevrons) |
315 | 323 | { |
316 | 324 | <g clip-path="url(#@clipId)"> |
317 | | - @RenderChevronsPattern(t0, t1, b0, b1, color, opacity) |
| 325 | + @RenderChevronsPattern(t0, t1, b0, b1, color, opacity, conn.Connector.Reversed) |
318 | 326 | </g> |
319 | 327 | } |
320 | 328 | else if (pattern == ConnectorFillPattern.Solid) |
|
372 | 380 | { |
373 | 381 | @* Bars pattern - follow the bezier curve *@ |
374 | 382 | <g clip-path="url(#@clipId)"> |
375 | | - @RenderBezierBarsPattern(bezierData, color, opacity) |
| 383 | + @RenderBezierBarsPattern(bezierData, color, opacity, conn.Connector.Reversed) |
376 | 384 | </g> |
377 | 385 | } |
378 | 386 | else if (pattern == ConnectorFillPattern.Chevrons) |
379 | 387 | { |
380 | 388 | @* Chevrons pattern - follow the bezier curve *@ |
381 | 389 | <g clip-path="url(#@clipId)"> |
382 | | - @RenderBezierChevronsPattern(bezierData, color, opacity) |
| 390 | + @RenderBezierChevronsPattern(bezierData, color, opacity, conn.Connector.Reversed) |
383 | 391 | </g> |
384 | 392 | } |
385 | 393 |
|
|
398 | 406 | }; |
399 | 407 |
|
400 | 408 | private RenderFragment RenderBarsPattern((double X, double Y) t0, (double X, double Y) t1, |
401 | | - (double X, double Y) b0, (double X, double Y) b1, string color, double opacity) => __builder => |
| 409 | + (double X, double Y) b0, (double X, double Y) b1, string color, double opacity, bool reversed) => __builder => |
402 | 410 | { |
403 | 411 | var length = Math.Sqrt(Math.Pow(t1.X - t0.X, 2) + Math.Pow(t1.Y - t0.Y, 2)); |
404 | 412 | var barCount = Math.Max(3, (int)(length / 30)); |
405 | | - var offset = _animationOffset; |
| 413 | + var offset = reversed ? 1.0 - _animationOffset : _animationOffset; |
406 | 414 |
|
407 | 415 | for (var i = -1; i <= barCount; i++) |
408 | 416 | { |
|
422 | 430 | }; |
423 | 431 |
|
424 | 432 | private RenderFragment RenderChevronsPattern((double X, double Y) t0, (double X, double Y) t1, |
425 | | - (double X, double Y) b0, (double X, double Y) b1, string color, double opacity) => __builder => |
| 433 | + (double X, double Y) b0, (double X, double Y) b1, string color, double opacity, bool reversed) => __builder => |
426 | 434 | { |
427 | | - var length = Math.Sqrt(Math.Pow(t1.X - t0.X, 2) + Math.Pow(t1.Y - t0.Y, 2)); |
| 435 | + // When reversed, swap start/end so chevrons point the opposite direction |
| 436 | + var (at0, at1, ab0, ab1) = reversed ? (t1, t0, b1, b0) : (t0, t1, b0, b1); |
| 437 | + var length = Math.Sqrt(Math.Pow(at1.X - at0.X, 2) + Math.Pow(at1.Y - at0.Y, 2)); |
428 | 438 | var chevronCount = Math.Max(2, (int)(length / 45)); |
429 | 439 | var chevronWidth = 0.6; |
430 | 440 | var pointDepth = 0.3; |
431 | 441 | var notchDepth = 0.3; |
432 | | - var offset = _animationOffset; |
| 442 | + var offset = reversed ? 1.0 - _animationOffset : _animationOffset; |
433 | 443 |
|
434 | 444 | for (var i = -1; i <= chevronCount; i++) |
435 | 445 | { |
|
438 | 448 | var fBody = (i + offset + chevronWidth) / chevronCount; |
439 | 449 | var fPoint = (i + offset + chevronWidth + pointDepth) / chevronCount; |
440 | 450 |
|
441 | | - var bl = Lerp(b0, b1, fTrail); |
442 | | - var tl = Lerp(t0, t1, fTrail); |
443 | | - var nm = LerpMid(t0, t1, b0, b1, fNotch); |
444 | | - var br = Lerp(b0, b1, fBody); |
445 | | - var tr = Lerp(t0, t1, fBody); |
446 | | - var pm = LerpMid(t0, t1, b0, b1, fPoint); |
| 451 | + var bl = Lerp(ab0, ab1, fTrail); |
| 452 | + var tl = Lerp(at0, at1, fTrail); |
| 453 | + var nm = LerpMid(at0, at1, ab0, ab1, fNotch); |
| 454 | + var br = Lerp(ab0, ab1, fBody); |
| 455 | + var tr = Lerp(at0, at1, fBody); |
| 456 | + var pm = LerpMid(at0, at1, ab0, ab1, fPoint); |
447 | 457 |
|
448 | 458 | <polygon points="@($"{F(bl.X)},{F(bl.Y)} {F(br.X)},{F(br.Y)} {F(pm.X)},{F(pm.Y)} {F(tr.X)},{F(tr.Y)} {F(tl.X)},{F(tl.Y)} {F(nm.X)},{F(nm.Y)}")" |
449 | 459 | fill="@color" |
|
485 | 495 | ); |
486 | 496 | } |
487 | 497 |
|
488 | | - private RenderFragment RenderBezierBarsPattern(BezierConnectorData data, string color, double opacity) => __builder => |
| 498 | + private RenderFragment RenderBezierBarsPattern(BezierConnectorData data, string color, double opacity, bool reversed) => __builder => |
489 | 499 | { |
490 | 500 | // Estimate arc length from the top curve for consistent bar spacing |
491 | 501 | var chordLen = Math.Sqrt(Math.Pow(data.EndTop.X - data.StartTop.X, 2) + Math.Pow(data.EndTop.Y - data.StartTop.Y, 2)); |
492 | 502 | var barCount = Math.Max(3, (int)(chordLen / 30)); |
493 | | - var offset = _animationOffset; |
| 503 | + var offset = reversed ? 1.0 - _animationOffset : _animationOffset; |
494 | 504 |
|
495 | 505 | for (var i = -1; i <= barCount; i++) |
496 | 506 | { |
|
509 | 519 | } |
510 | 520 | }; |
511 | 521 |
|
512 | | - private RenderFragment RenderBezierChevronsPattern(BezierConnectorData data, string color, double opacity) => __builder => |
| 522 | + private RenderFragment RenderBezierChevronsPattern(BezierConnectorData data, string color, double opacity, bool reversed) => __builder => |
513 | 523 | { |
514 | | - var chordLen = Math.Sqrt(Math.Pow(data.EndTop.X - data.StartTop.X, 2) + Math.Pow(data.EndTop.Y - data.StartTop.Y, 2)); |
| 524 | + // When reversed, evaluate bezier from end?start to flip chevron direction |
| 525 | + var (sTop, sTopCtrl, eTopCtrl, eTop) = reversed |
| 526 | + ? (data.EndTop, data.EndTopCtrl, data.StartTopCtrl, data.StartTop) |
| 527 | + : (data.StartTop, data.StartTopCtrl, data.EndTopCtrl, data.EndTop); |
| 528 | + var (sBot, sBotCtrl, eBotCtrl, eBot) = reversed |
| 529 | + ? (data.EndBottom, data.EndBottomCtrl, data.StartBottomCtrl, data.StartBottom) |
| 530 | + : (data.StartBottom, data.StartBottomCtrl, data.EndBottomCtrl, data.EndBottom); |
| 531 | + |
| 532 | + var chordLen = Math.Sqrt(Math.Pow(eTop.X - sTop.X, 2) + Math.Pow(eTop.Y - sTop.Y, 2)); |
515 | 533 | var chevronCount = Math.Max(2, (int)(chordLen / 45)); |
516 | 534 | var chevronWidth = 0.6; |
517 | 535 | var pointDepth = 0.3; |
518 | 536 | var notchDepth = 0.3; |
519 | | - var offset = _animationOffset; |
| 537 | + var offset = reversed ? 1.0 - _animationOffset : _animationOffset; |
520 | 538 |
|
521 | 539 | for (var i = -1; i <= chevronCount; i++) |
522 | 540 | { |
|
525 | 543 | var fBody = (i + offset + chevronWidth) / chevronCount; |
526 | 544 | var fPoint = (i + offset + chevronWidth + pointDepth) / chevronCount; |
527 | 545 |
|
528 | | - var tl = CubicBezier(data.StartTop, data.StartTopCtrl, data.EndTopCtrl, data.EndTop, fTrail); |
529 | | - var bl = CubicBezier(data.StartBottom, data.StartBottomCtrl, data.EndBottomCtrl, data.EndBottom, fTrail); |
530 | | - var tr = CubicBezier(data.StartTop, data.StartTopCtrl, data.EndTopCtrl, data.EndTop, fBody); |
531 | | - var br = CubicBezier(data.StartBottom, data.StartBottomCtrl, data.EndBottomCtrl, data.EndBottom, fBody); |
| 546 | + var tl = CubicBezier(sTop, sTopCtrl, eTopCtrl, eTop, fTrail); |
| 547 | + var bl = CubicBezier(sBot, sBotCtrl, eBotCtrl, eBot, fTrail); |
| 548 | + var tr = CubicBezier(sTop, sTopCtrl, eTopCtrl, eTop, fBody); |
| 549 | + var br = CubicBezier(sBot, sBotCtrl, eBotCtrl, eBot, fBody); |
532 | 550 |
|
533 | 551 | // Notch and point are midpoints between the top and bottom curves at their respective t values |
534 | | - var nTop = CubicBezier(data.StartTop, data.StartTopCtrl, data.EndTopCtrl, data.EndTop, fNotch); |
535 | | - var nBot = CubicBezier(data.StartBottom, data.StartBottomCtrl, data.EndBottomCtrl, data.EndBottom, fNotch); |
| 552 | + var nTop = CubicBezier(sTop, sTopCtrl, eTopCtrl, eTop, fNotch); |
| 553 | + var nBot = CubicBezier(sBot, sBotCtrl, eBotCtrl, eBot, fNotch); |
536 | 554 | var nm = (X: (nTop.X + nBot.X) / 2, Y: (nTop.Y + nBot.Y) / 2); |
537 | 555 |
|
538 | | - var pTop = CubicBezier(data.StartTop, data.StartTopCtrl, data.EndTopCtrl, data.EndTop, fPoint); |
539 | | - var pBot = CubicBezier(data.StartBottom, data.StartBottomCtrl, data.EndBottomCtrl, data.EndBottom, fPoint); |
| 556 | + var pTop = CubicBezier(sTop, sTopCtrl, eTopCtrl, eTop, fPoint); |
| 557 | + var pBot = CubicBezier(sBot, sBotCtrl, eBotCtrl, eBot, fPoint); |
540 | 558 | var pm = (X: (pTop.X + pBot.X) / 2, Y: (pTop.Y + pBot.Y) / 2); |
541 | 559 |
|
542 | 560 | <polygon points="@($"{F(bl.X)},{F(bl.Y)} {F(br.X)},{F(br.Y)} {F(pm.X)},{F(pm.Y)} {F(tr.X)},{F(tr.Y)} {F(tl.X)},{F(tl.Y)} {F(nm.X)},{F(nm.Y)}")" |
|
0 commit comments