This commit is contained in:
ct
2025-06-17 20:55:51 +08:00
parent 933e12d7fb
commit bf54d37306
2 changed files with 35 additions and 16 deletions

View File

@@ -292,7 +292,7 @@ const VideoPreview = ({
[onElementUpdate, timelineElements], [onElementUpdate, timelineElements],
); );
// Handle transform events (scale, rotate) with snapping - USES NATIVE KONVA ROTATION SNAPPING // Handle transform events - TRANSFORMER IS SOURCE OF TRUTH
const handleTransform = useCallback( const handleTransform = useCallback(
(elementId) => { (elementId) => {
const node = elementRefs.current[elementId]; const node = elementRefs.current[elementId];
@@ -307,11 +307,25 @@ const VideoPreview = ({
const scaleY = node.scaleY(); const scaleY = node.scaleY();
let newWidth, newHeight; let newWidth, newHeight;
let updates = { rotation };
if (element.type === 'text') { if (element.type === 'text') {
// For text, allow free scaling // For text: Convert scale to actual fontSize and reset scale to 1
newWidth = node.width() * scaleX; const avgScale = Math.max(Math.abs(scaleX), Math.abs(scaleY));
newHeight = node.height() * scaleY; const newFontSize = Math.round(element.fontSize * avgScale);
// Clamp font size to reasonable limits
const clampedFontSize = Math.max(8, Math.min(120, newFontSize));
updates.fontSize = clampedFontSize;
// Reset scale to 1 since we've applied it to fontSize
node.scaleX(1);
node.scaleY(1);
// Text dimensions are handled by Konva based on content and fontSize
newWidth = node.width();
newHeight = node.height();
} else { } else {
// For images/videos, maintain aspect ratio by using the larger scale // For images/videos, maintain aspect ratio by using the larger scale
const scale = Math.max(Math.abs(scaleX), Math.abs(scaleY)); const scale = Math.max(Math.abs(scaleX), Math.abs(scaleY));
@@ -327,6 +341,9 @@ const VideoPreview = ({
// Update offset for center rotation // Update offset for center rotation
node.offsetX(newWidth / 2); node.offsetX(newWidth / 2);
node.offsetY(newHeight / 2); node.offsetY(newHeight / 2);
updates.width = newWidth;
updates.height = newHeight;
} }
// Calculate position for snapping // Calculate position for snapping
@@ -375,16 +392,12 @@ const VideoPreview = ({
}); });
} }
// Update state with the final calculated values // Add position to updates
const finalTransform = { updates.x = topLeftX;
x: topLeftX, updates.y = topLeftY;
y: topLeftY,
width: newWidth,
height: newHeight,
rotation: rotation,
};
onElementUpdate(elementId, finalTransform); // Update state with all calculated values
onElementUpdate(elementId, updates);
}, },
[onElementUpdate, dimensions.width, dimensions.height, timelineElements], [onElementUpdate, dimensions.width, dimensions.height, timelineElements],
); );
@@ -471,6 +484,9 @@ const VideoPreview = ({
align="center" align="center"
// Let text have natural width and height for multiline support // Let text have natural width and height for multiline support
wrap="word" wrap="word"
// Always scale 1 - size changes go through fontSize
scaleX={1}
scaleY={1}
draggable draggable
dragBoundFunc={createDragBoundFunc(element.id)} dragBoundFunc={createDragBoundFunc(element.id)}
onClick={() => handleElementSelect(element.id)} onClick={() => handleElementSelect(element.id)}

View File

@@ -35,11 +35,11 @@ export default function TextSidebar({ isOpen, onClose }) {
const MAX_FONT_SIZE = 120; const MAX_FONT_SIZE = 120;
const FONT_SIZE_STEP = 2; const FONT_SIZE_STEP = 2;
// Update state when selected element changes // Update state when selected element changes - THIS KEEPS SIDEBAR IN SYNC WITH TRANSFORMER
useEffect(() => { useEffect(() => {
if (selectedTextElement) { if (selectedTextElement) {
setTextValue(selectedTextElement.text || ''); setTextValue(selectedTextElement.text || '');
setFontSize(selectedTextElement.fontSize || 24); setFontSize(selectedTextElement.fontSize || 24); // Always use current fontSize from element
setIsBold(selectedTextElement.fontWeight === 'bold' || selectedTextElement.fontWeight === 700 || true); setIsBold(selectedTextElement.fontWeight === 'bold' || selectedTextElement.fontWeight === 700 || true);
setIsItalic(selectedTextElement.fontStyle === 'italic' || false); setIsItalic(selectedTextElement.fontStyle === 'italic' || false);
setFontFamily(selectedTextElement.fontFamily || 'Montserrat'); setFontFamily(selectedTextElement.fontFamily || 'Montserrat');
@@ -59,7 +59,7 @@ export default function TextSidebar({ isOpen, onClose }) {
} }
}; };
// Handle font size changes // Handle font size changes - CLAMP AND UPDATE
const handleFontSizeChange = (newSize) => { const handleFontSizeChange = (newSize) => {
const clampedSize = Math.max(MIN_FONT_SIZE, Math.min(MAX_FONT_SIZE, newSize)); const clampedSize = Math.max(MIN_FONT_SIZE, Math.min(MAX_FONT_SIZE, newSize));
setFontSize(clampedSize); setFontSize(clampedSize);
@@ -196,6 +196,9 @@ export default function TextSidebar({ isOpen, onClose }) {
<div className="mt-1 text-center text-xs text-gray-500"> <div className="mt-1 text-center text-xs text-gray-500">
Size range: {MIN_FONT_SIZE}px - {MAX_FONT_SIZE}px Size range: {MIN_FONT_SIZE}px - {MAX_FONT_SIZE}px
</div> </div>
{/* Note about transformer resize */}
<div className="mt-1 text-center text-xs text-blue-600">💡 You can also resize by dragging the corners</div>
</div> </div>
{/* Font Style Controls */} {/* Font Style Controls */}