Erweiterungen
This commit is contained in:
Binary file not shown.
@@ -45,6 +45,9 @@ window.initProfileInvoiceGenerator = function() {
|
|||||||
var elementStart = { x: 0, y: 0 };
|
var elementStart = { x: 0, y: 0 };
|
||||||
var gridSize = 5;
|
var gridSize = 5;
|
||||||
|
|
||||||
|
// Image cache to prevent flickering during resize
|
||||||
|
var imageCache = {};
|
||||||
|
|
||||||
// Page dimensions
|
// Page dimensions
|
||||||
var padding = 10;
|
var padding = 10;
|
||||||
var pageX, pageY, pageWidth, pageHeight;
|
var pageX, pageY, pageWidth, pageHeight;
|
||||||
@@ -167,35 +170,58 @@ window.initProfileInvoiceGenerator = function() {
|
|||||||
ctx.stroke();
|
ctx.stroke();
|
||||||
} else if (el.type === 'image') {
|
} else if (el.type === 'image') {
|
||||||
if (el.imageData) {
|
if (el.imageData) {
|
||||||
// Draw the uploaded image with aspect ratio preserved
|
// Check if image is already cached
|
||||||
var img = new Image();
|
if (imageCache[el.imageData]) {
|
||||||
img.onload = function() {
|
// Use cached image for flicker-free rendering
|
||||||
|
var img = imageCache[el.imageData];
|
||||||
// Calculate dimensions to maintain aspect ratio (object-fit: contain)
|
// Calculate dimensions to maintain aspect ratio (object-fit: contain)
|
||||||
var imgAspect = img.width / img.height;
|
var imgAspect = img.width / img.height;
|
||||||
var boxAspect = w / h;
|
var boxAspect = w / h;
|
||||||
var drawW, drawH, drawX, drawY;
|
var drawW, drawH, drawX, drawY;
|
||||||
|
|
||||||
if (imgAspect > boxAspect) {
|
if (imgAspect > boxAspect) {
|
||||||
// Image is wider than box - fit to width
|
|
||||||
drawW = w;
|
drawW = w;
|
||||||
drawH = w / imgAspect;
|
drawH = w / imgAspect;
|
||||||
drawX = x;
|
drawX = x;
|
||||||
drawY = y + (h - drawH) / 2; // Center vertically
|
drawY = y + (h - drawH) / 2;
|
||||||
} else {
|
} else {
|
||||||
// Image is taller than box - fit to height
|
|
||||||
drawW = h * imgAspect;
|
drawW = h * imgAspect;
|
||||||
drawH = h;
|
drawH = h;
|
||||||
drawX = x + (w - drawW) / 2; // Center horizontally
|
drawX = x + (w - drawW) / 2;
|
||||||
drawY = y;
|
drawY = y;
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.drawImage(img, drawX, drawY, drawW, drawH);
|
ctx.drawImage(img, drawX, drawY, drawW, drawH);
|
||||||
// Redraw selection if this element is selected
|
} else {
|
||||||
if (selectedElement && selectedElement.id === el.id) {
|
// Load and cache the image
|
||||||
drawSelection(el);
|
var img = new Image();
|
||||||
}
|
img.onload = function() {
|
||||||
};
|
imageCache[el.imageData] = img;
|
||||||
img.src = el.imageData;
|
// Calculate dimensions to maintain aspect ratio
|
||||||
|
var imgAspect = img.width / img.height;
|
||||||
|
var boxAspect = w / h;
|
||||||
|
var drawW, drawH, drawX, drawY;
|
||||||
|
|
||||||
|
if (imgAspect > boxAspect) {
|
||||||
|
drawW = w;
|
||||||
|
drawH = w / imgAspect;
|
||||||
|
drawX = x;
|
||||||
|
drawY = y + (h - drawH) / 2;
|
||||||
|
} else {
|
||||||
|
drawW = h * imgAspect;
|
||||||
|
drawH = h;
|
||||||
|
drawX = x + (w - drawW) / 2;
|
||||||
|
drawY = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.drawImage(img, drawX, drawY, drawW, drawH);
|
||||||
|
// Redraw selection if this element is selected
|
||||||
|
if (selectedElement && selectedElement.id === el.id) {
|
||||||
|
drawSelection(el);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
img.src = el.imageData;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// Draw placeholder
|
// Draw placeholder
|
||||||
ctx.fillStyle = '#f0f0f0';
|
ctx.fillStyle = '#f0f0f0';
|
||||||
@@ -799,10 +825,41 @@ window.initProfileInvoiceGenerator = function() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Get canvas data
|
// Get canvas data
|
||||||
|
// Helper functions for percentage conversion
|
||||||
|
function toPercentX(value) {
|
||||||
|
return (value / basePageWidth * 100).toFixed(2);
|
||||||
|
}
|
||||||
|
function toPercentY(value) {
|
||||||
|
return (value / basePageHeight * 100).toFixed(2);
|
||||||
|
}
|
||||||
|
function fromPercentX(percent) {
|
||||||
|
return Math.round(parseFloat(percent) / 100 * basePageWidth);
|
||||||
|
}
|
||||||
|
function fromPercentY(percent) {
|
||||||
|
return Math.round(parseFloat(percent) / 100 * basePageHeight);
|
||||||
|
}
|
||||||
|
|
||||||
window.getProfileCanvasData = function() {
|
window.getProfileCanvasData = function() {
|
||||||
saveState();
|
saveState();
|
||||||
|
// Convert pixel values to percentages for storage
|
||||||
|
var elementsWithPercent = elements.map(function(el) {
|
||||||
|
return {
|
||||||
|
id: el.id,
|
||||||
|
type: el.type,
|
||||||
|
text: el.text,
|
||||||
|
xPercent: toPercentX(el.x),
|
||||||
|
yPercent: toPercentY(el.y),
|
||||||
|
widthPercent: toPercentX(el.width),
|
||||||
|
heightPercent: toPercentY(el.height),
|
||||||
|
fontSize: el.fontSize,
|
||||||
|
fontStyle: el.fontStyle,
|
||||||
|
color: el.color,
|
||||||
|
isStatic: el.isStatic,
|
||||||
|
imageData: el.imageData
|
||||||
|
};
|
||||||
|
});
|
||||||
return {
|
return {
|
||||||
elements: elements
|
elements: elementsWithPercent
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -868,6 +925,21 @@ window.initProfileInvoiceGenerator = function() {
|
|||||||
elementCounter++;
|
elementCounter++;
|
||||||
el.id = 'element-' + elementCounter;
|
el.id = 'element-' + elementCounter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Convert percentages to pixels if they exist, otherwise use legacy pixel values
|
||||||
|
if (el.xPercent !== undefined) {
|
||||||
|
el.x = fromPercentX(el.xPercent);
|
||||||
|
}
|
||||||
|
if (el.yPercent !== undefined) {
|
||||||
|
el.y = fromPercentY(el.yPercent);
|
||||||
|
}
|
||||||
|
if (el.widthPercent !== undefined) {
|
||||||
|
el.width = fromPercentX(el.widthPercent);
|
||||||
|
}
|
||||||
|
if (el.heightPercent !== undefined) {
|
||||||
|
el.height = fromPercentY(el.heightPercent);
|
||||||
|
}
|
||||||
|
|
||||||
elements.push(el);
|
elements.push(el);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -273,19 +273,44 @@ public class CustomerInvoiceService {
|
|||||||
for (com.fasterxml.jackson.databind.JsonNode element : elements) {
|
for (com.fasterxml.jackson.databind.JsonNode element : elements) {
|
||||||
String type = element.has("type") ? element.get("type").asText("text") : "text";
|
String type = element.has("type") ? element.get("type").asText("text") : "text";
|
||||||
String text = element.has("text") ? element.get("text").asText("") : "";
|
String text = element.has("text") ? element.get("text").asText("") : "";
|
||||||
double x = element.has("x") ? element.get("x").asDouble(0) : 0;
|
|
||||||
double y = element.has("y") ? element.get("y").asDouble(0) : 0;
|
// Use percentage values if available, otherwise fall back to legacy pixel values
|
||||||
double width = element.has("width") ? element.get("width").asDouble(150) : 150;
|
double xPercent, yPercent, widthPercent, heightPercent;
|
||||||
double height = element.has("height") ? element.get("height").asDouble(30) : 30;
|
if (element.has("xPercent")) {
|
||||||
|
xPercent = element.get("xPercent").asDouble(0);
|
||||||
|
} else {
|
||||||
|
// Legacy: convert pixels to percent
|
||||||
|
double x = element.get("x").asDouble(0);
|
||||||
|
xPercent = x / 595.0 * 100;
|
||||||
|
}
|
||||||
|
if (element.has("yPercent")) {
|
||||||
|
yPercent = element.get("yPercent").asDouble(0);
|
||||||
|
} else {
|
||||||
|
double y = element.get("y").asDouble(0);
|
||||||
|
yPercent = y / 842.0 * 100;
|
||||||
|
}
|
||||||
|
if (element.has("widthPercent")) {
|
||||||
|
widthPercent = element.get("widthPercent").asDouble(15);
|
||||||
|
} else {
|
||||||
|
double width = element.get("width").asDouble(150);
|
||||||
|
widthPercent = width / 595.0 * 100;
|
||||||
|
}
|
||||||
|
if (element.has("heightPercent")) {
|
||||||
|
heightPercent = element.get("heightPercent").asDouble(3);
|
||||||
|
} else {
|
||||||
|
double height = element.get("height").asDouble(30);
|
||||||
|
heightPercent = height / 842.0 * 100;
|
||||||
|
}
|
||||||
|
|
||||||
int fontSize = element.has("fontSize") ? element.get("fontSize").asInt(14) : 14;
|
int fontSize = element.has("fontSize") ? element.get("fontSize").asInt(14) : 14;
|
||||||
String fontStyle = element.has("fontStyle") ? element.get("fontStyle").asText("") : "";
|
String fontStyle = element.has("fontStyle") ? element.get("fontStyle").asText("") : "";
|
||||||
String color = element.has("color") ? element.get("color").asText("#333333") : "#333333";
|
String color = element.has("color") ? element.get("color").asText("#333333") : "#333333";
|
||||||
|
|
||||||
// Convert canvas coordinates to mm (assuming 96 DPI)
|
// Convert percentages to mm (A4 is 210mm x 297mm)
|
||||||
double mmX = x * 25.4 / 96;
|
double mmX = xPercent / 100.0 * 210.0;
|
||||||
double mmY = y * 25.4 / 96;
|
double mmY = yPercent / 100.0 * 297.0;
|
||||||
double mmWidth = width * 25.4 / 96;
|
double mmWidth = widthPercent / 100.0 * 210.0;
|
||||||
double mmHeight = height * 25.4 / 96;
|
double mmHeight = heightPercent / 100.0 * 297.0;
|
||||||
|
|
||||||
htmlBuilder.append("<div class='element ").append(type).append("' ");
|
htmlBuilder.append("<div class='element ").append(type).append("' ");
|
||||||
htmlBuilder.append("style='");
|
htmlBuilder.append("style='");
|
||||||
|
|||||||
Reference in New Issue
Block a user