Refactor PDF editor styles and add throttling logic
Refactored `SenderPdfImageEditor.razor` to use culture-invariant formatting for dynamic styles and introduced the `GetPageCanvasStyle` method for calculating `aspect-ratio` and `cursor` styles. Enhanced layout control with additional CSS properties. Updated `envelope-editor.js` to include a throttling mechanism for mouse movement events using `_moveThrottle` and `requestAnimationFrame`. Added `getClickCoordsOnPdfPageThrottled` with a promise-based approach to improve performance during rapid interactions.
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
@using EnvelopeGenerator.Application.Resources
|
||||
@using EnvelopeGenerator.Application.Common.Dto
|
||||
@using System.Globalization
|
||||
@using Microsoft.Extensions.Localization
|
||||
@inject IStringLocalizer<Resource> UiLocalizer
|
||||
@inject IJSRuntime JSRuntime
|
||||
@@ -39,7 +40,7 @@
|
||||
data-page-height-pt="@heightPt">
|
||||
<div class="sender-image-editor__page-canvas"
|
||||
data-editor-page-canvas="@pageNumber"
|
||||
style="@( _isDragging ? "cursor:grabbing;" : string.Empty)">
|
||||
style="@GetPageCanvasStyle(widthPt, heightPt)">
|
||||
@if (!string.IsNullOrWhiteSpace(pagePreview?.ImageDataUrl))
|
||||
{
|
||||
<img class="sender-image-editor__page-image"
|
||||
@@ -117,15 +118,40 @@
|
||||
var widthPercent = (127.44 / pageWidthPt) * 100.0;
|
||||
var heightPercent = (141.12 / pageHeightPt) * 100.0;
|
||||
|
||||
var left = leftPercent.ToString("F4", CultureInfo.InvariantCulture);
|
||||
var top = topPercent.ToString("F4", CultureInfo.InvariantCulture);
|
||||
var width = widthPercent.ToString("F4", CultureInfo.InvariantCulture);
|
||||
var height = heightPercent.ToString("F4", CultureInfo.InvariantCulture);
|
||||
|
||||
return string.Join(' ',
|
||||
$"left:{leftPercent:F4}%;",
|
||||
$"top:{topPercent:F4}%;",
|
||||
$"width:{widthPercent:F4}%;",
|
||||
$"height:{heightPercent:F4}%;",
|
||||
"position:absolute;",
|
||||
$"left:{left}%;",
|
||||
$"top:{top}%;",
|
||||
$"width:{width}%;",
|
||||
$"height:{height}%;",
|
||||
"border:2px solid;",
|
||||
"border-radius:8px;",
|
||||
"display:flex;",
|
||||
"align-items:flex-start;",
|
||||
"justify-content:space-between;",
|
||||
"gap:0.35rem;",
|
||||
"padding:0.2rem 0.3rem;",
|
||||
"overflow:hidden;",
|
||||
"z-index:30;",
|
||||
$"border-color:{field.Color};",
|
||||
$"background-color:{field.Color}22;");
|
||||
}
|
||||
|
||||
private string GetPageCanvasStyle(double pageWidthPt, double pageHeightPt)
|
||||
{
|
||||
var ratio = pageHeightPt <= 0 ? 595.0 / 842.0 : pageWidthPt / pageHeightPt;
|
||||
var ratioText = ratio.ToString("F6", CultureInfo.InvariantCulture);
|
||||
var cursor = _isDragging
|
||||
? "grabbing"
|
||||
: (IsPlacementMode ? "crosshair" : "default");
|
||||
return $"aspect-ratio:{ratioText};cursor:{cursor};";
|
||||
}
|
||||
|
||||
private async Task HandleClickAsync(MouseEventArgs args)
|
||||
{
|
||||
if (EditorClick.HasDelegate)
|
||||
@@ -182,7 +208,7 @@
|
||||
await MoveField.InvokeAsync(new SenderPdfFieldMoveRequest(_draggedFieldIndex.Value, pageNumber, xPt, yPt));
|
||||
}
|
||||
|
||||
private void OnEditorMouseUp(MouseEventArgs _)
|
||||
private void OnEditorMouseUp(MouseEventArgs args)
|
||||
{
|
||||
_draggedFieldIndex = null;
|
||||
_isDragging = false;
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
window.envelopeEditor = {
|
||||
|
||||
_moveThrottle: {
|
||||
rafId: 0,
|
||||
latest: null,
|
||||
waiters: []
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the click position normalised to [0,1] relative to the rendered PDF page
|
||||
* element inside DxPdfViewer (or DxReportViewer as fallback).
|
||||
@@ -93,5 +99,33 @@ window.envelopeEditor = {
|
||||
pageIndex: targetIndex,
|
||||
pageNumber: parseInt(targetPage.getAttribute('data-editor-page') || String(targetIndex + 1), 10)
|
||||
};
|
||||
},
|
||||
|
||||
getClickCoordsOnPdfPageThrottled: function (viewerCssClass, clientX, clientY) {
|
||||
return new Promise((resolve) => {
|
||||
const state = window.envelopeEditor._moveThrottle;
|
||||
state.latest = { viewerCssClass, clientX, clientY };
|
||||
state.waiters.push(resolve);
|
||||
|
||||
if (state.rafId !== 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
state.rafId = window.requestAnimationFrame(() => {
|
||||
state.rafId = 0;
|
||||
|
||||
const args = state.latest;
|
||||
state.latest = null;
|
||||
|
||||
const result = args
|
||||
? window.envelopeEditor.getClickCoordsOnPdfPage(args.viewerCssClass, args.clientX, args.clientY)
|
||||
: null;
|
||||
|
||||
const waiters = state.waiters.splice(0, state.waiters.length);
|
||||
for (const waiter of waiters) {
|
||||
waiter(result);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user