feat: implement QuestionBank CRUD with pagination and template query
- Add pagination support to findAll (page, limit query params) - Add findByTemplateId method to service - Add GET /by-template/:templateId endpoint to controller - Service already includes CRUD for QuestionBank and QuestionBankItem
This commit is contained in:
@@ -0,0 +1,64 @@
|
||||
import * as pdfjs from 'pdfjs-dist';
|
||||
|
||||
// Set worker path - using a CDN for the worker to avoid complex vite configuration for now
|
||||
// or we can try to use the bundled worker if vite handles it
|
||||
pdfjs.GlobalWorkerOptions.workerSrc = `https://cdnjs.cloudflare.com/ajax/libs/pdf.js/${pdfjs.version}/pdf.worker.min.mjs`;
|
||||
|
||||
export const pdfRenderService = {
|
||||
async renderPageToCanvas(
|
||||
pdfData: Blob | ArrayBuffer,
|
||||
pageNumber: number,
|
||||
canvas: HTMLCanvasElement,
|
||||
targetWidth: number,
|
||||
targetHeight: number
|
||||
): Promise<void> {
|
||||
const data = pdfData instanceof Blob ? await pdfData.arrayBuffer() : pdfData;
|
||||
const loadingTask = pdfjs.getDocument({ data });
|
||||
const pdf = await loadingTask.promise;
|
||||
|
||||
if (pageNumber < 1 || pageNumber > pdf.numPages) {
|
||||
throw new Error(`Invalid page number: ${pageNumber}.`);
|
||||
}
|
||||
|
||||
const page = await pdf.getPage(pageNumber);
|
||||
|
||||
// Calculate scale to fit container while maintaining aspect ratio
|
||||
const unscaledViewport = page.getViewport({ scale: 1 });
|
||||
|
||||
// Calculate the scale needed to fit the PDF page within the target dimensions
|
||||
const fitScale = Math.min(targetWidth / unscaledViewport.width, targetHeight / unscaledViewport.height);
|
||||
|
||||
// Calculate a higher scale for rendering quality (anti-aliasing and clarity)
|
||||
const devicePixelRatio = window.devicePixelRatio || 1;
|
||||
const renderScale = fitScale * Math.max(2, devicePixelRatio);
|
||||
|
||||
const viewport = page.getViewport({ scale: renderScale });
|
||||
|
||||
// Set canvas to the high-resolution dimensions to maintain quality
|
||||
canvas.width = viewport.width;
|
||||
canvas.height = viewport.height;
|
||||
|
||||
const context = canvas.getContext('2d');
|
||||
if (!context) return;
|
||||
|
||||
// Save the context state before any transformations
|
||||
context.save();
|
||||
|
||||
// Fill background
|
||||
context.fillStyle = '#f8fafc';
|
||||
context.fillRect(0, 0, canvas.width, canvas.height);
|
||||
|
||||
// Calculate the position to center the PDF page in the canvas
|
||||
const offsetX = (canvas.width - viewport.width) / 2;
|
||||
const offsetY = (canvas.height - viewport.height) / 2;
|
||||
|
||||
await page.render({
|
||||
canvasContext: context,
|
||||
viewport: viewport,
|
||||
transform: [1, 0, 0, 1, offsetX, offsetY]
|
||||
}).promise;
|
||||
|
||||
// Restore the context state after rendering
|
||||
context.restore();
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user