Overview
Transform
is a widget that applies transformations to its child before painting. Inspired by Flutter’s Transform, it uses Matrix4 to apply various transformations including rotation, scaling, translation, and skewing.
Unlike RotatedBox, Transform applies transformations just before painting rather than before layout, meaning the transformation is not considered when calculating the widget’s space consumption. This provides performance benefits but requires careful consideration of layout implications.
See: https://api.flutter.dev/flutter/widgets/Transform-class.html
When to Use?
- When you need to rotate a widget
- When you need to scale (resize) a widget
- When you need to translate (move) a widget
- When creating 3D effects or perspective
- When creating animation effects
- When adding visual effects or decorations
Basic Usage
import { Transform, Matrix4, Container } from 'flitter';
// 45-degree rotation
const RotatedBox = Transform.rotate({
angle: Math.PI / 4, // Radians
child: Container({
width: 100,
height: 100,
color: '#3498db'
})
});
// Scaling
const ScaledBox = Transform.scale({
scale: 1.5, // 1.5x scale
child: Container({
width: 100,
height: 100,
color: '#e74c3c'
})
});
// Translation
const TranslatedBox = Transform.translate({
offset: new Offset({ x: 50, y: 30 }),
child: Container({
width: 100,
height: 100,
color: '#2ecc71'
})
});
Props
transform (required)
Value: Matrix4
A 4x4 transformation matrix representing the transformation to apply. Can be created using various static methods of the Matrix4 class.
// Translation transform
transform: Matrix4.translationValues(50, 30, 0)
// Scaling transform
transform: Matrix4.diagonal3Values(2.0, 1.5, 1.0) // 2x X-axis, 1.5x Y-axis
// Skew transform
transform: Matrix4.skewX(0.5) // Skew along X-axis
origin (optional)
Value: Offset
Specifies the origin point for the transformation. If not specified, it’s determined by alignment.
// Rotate around top-left corner
origin: new Offset({ x: 0, y: 0 })
// Rotate around bottom-right corner
origin: new Offset({ x: 100, y: 100 })
alignment (optional)
Value: Alignment (default: Alignment.center)
Specifies the alignment reference point for the transformation. Used when origin is not specified.
// Center reference (default)
alignment: Alignment.center
// Top-left reference
alignment: Alignment.topLeft
// Bottom-right reference
alignment: Alignment.bottomRight
child (optional)
Value: Widget
The child widget to which the transformation will be applied.
Convenience Methods
Transform widget provides static methods for common transformations:
Transform.rotate()
Transform.rotate({
angle: number, // Rotation angle in radians
origin?: Offset, // Rotation origin point
alignment?: Alignment, // Alignment reference
child?: Widget
})
Transform.scale()
Transform.scale({
scale?: number, // Uniform scaling
scaleX?: number, // X-axis scaling
scaleY?: number, // Y-axis scaling
origin?: Offset, // Scale origin point
alignment?: Alignment, // Alignment reference
child?: Widget
})
Transform.translate()
Transform.translate({
offset: Offset, // Translation distance
child?: Widget
})
Real-World Examples
Example 1: Various Rotation Transformations
import { Transform, Container, Row, Column, Text } from 'flitter';
const RotationExamples = Row({
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Column({
children: [
Transform.rotate({
angle: Math.PI / 6, // 30 degrees
child: Container({
width: 80,
height: 80,
color: '#e74c3c',
child: Center({
child: Text('30°', { style: { color: 'white' } })
})
})
}),
Text('30° Rotation')
]
}),
Column({
children: [
Transform.rotate({
angle: Math.PI / 4, // 45 degrees
child: Container({
width: 80,
height: 80,
color: '#3498db',
child: Center({
child: Text('45°', { style: { color: 'white' } })
})
})
}),
Text('45° Rotation')
]
}),
Column({
children: [
Transform.rotate({
angle: Math.PI / 2, // 90 degrees
child: Container({
width: 80,
height: 80,
color: '#2ecc71',
child: Center({
child: Text('90°', { style: { color: 'white' } })
})
})
}),
Text('90° Rotation')
]
})
]
});
Example 2: Scaling Transformations
import { Transform, Container, Row } from 'flitter';
const ScaleExamples = Row({
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
// Uniform scaling
Transform.scale({
scale: 1.5,
child: Container({
width: 60,
height: 60,
color: '#9b59b6'
})
}),
// X-axis only scaling
Transform.scale({
scaleX: 2.0,
scaleY: 1.0,
child: Container({
width: 60,
height: 60,
color: '#e67e22'
})
}),
// Y-axis only scaling
Transform.scale({
scaleX: 1.0,
scaleY: 2.0,
child: Container({
width: 60,
height: 60,
color: '#1abc9c'
})
}),
// Scaling down
Transform.scale({
scale: 0.5,
child: Container({
width: 60,
height: 60,
color: '#f39c12'
})
})
]
});
Example 3: Combined Transformations (Rotation + Scaling)
import { Transform, Matrix4, Container } from 'flitter';
const CombinedTransform = () => {
// Direct Matrix4 manipulation for combined transforms
const matrix = Matrix4.identity();
matrix.translate(50, 0, 0); // Translation
matrix.rotateZ(Math.PI / 4); // 45-degree rotation
matrix.scale(1.5, 1.5, 1.0); // 1.5x scaling
return Transform({
transform: matrix,
child: Container({
width: 80,
height: 80,
color: '#e74c3c',
child: Center({
child: Text('Combined\nTransform', {
style: {
color: 'white',
fontSize: 12,
textAlign: 'center'
}
})
})
})
});
};
Example 4: 3D Perspective Effect
import { Transform, Matrix4, Container } from 'flitter';
const PerspectiveCard = Transform({
transform: (() => {
const matrix = Matrix4.identity();
matrix.setEntry(3, 2, 0.001); // Perspective effect
matrix.rotateX(Math.PI / 6); // 30-degree X-axis rotation
return matrix;
})(),
alignment: Alignment.center,
child: Container({
width: 200,
height: 120,
decoration: new BoxDecoration({
color: '#34495e',
borderRadius: BorderRadius.circular(12),
boxShadow: [
new BoxShadow({
color: 'rgba(0, 0, 0, 0.3)',
offset: new Offset({ x: 0, y: 8 }),
blurRadius: 16
})
]
}),
child: Center({
child: Text('3D Card', {
style: {
color: 'white',
fontSize: 18,
fontWeight: 'bold'
}
})
})
})
});
Example 5: Animation with Transform
import { Transform, AnimationController, Tween } from 'flitter';
class AnimatedTransform extends StatefulWidget {
createState() {
return new AnimatedTransformState();
}
}
class AnimatedTransformState extends State {
animationController!: AnimationController;
rotationTween!: Tween<number>;
scaleTween!: Tween<number>;
initState() {
this.animationController = new AnimationController({
duration: 2000
});
this.rotationTween = new Tween({
begin: 0,
end: Math.PI * 2
});
this.scaleTween = new Tween({
begin: 0.5,
end: 1.5
});
this.animationController.addListener(() => this.setState());
this.animationController.repeat({ reverse: true });
}
dispose() {
this.animationController.dispose();
}
build() {
const rotation = this.rotationTween.evaluate(this.animationController);
const scale = this.scaleTween.evaluate(this.animationController);
return Transform({
transform: (() => {
const matrix = Matrix4.identity();
matrix.rotateZ(rotation);
matrix.scale(scale, scale, 1.0);
return matrix;
})(),
alignment: Alignment.center,
child: Container({
width: 100,
height: 100,
decoration: new BoxDecoration({
color: '#3498db',
borderRadius: BorderRadius.circular(12)
}),
child: Center({
child: Text('Animation', {
style: { color: 'white', fontWeight: 'bold' }
})
})
})
});
}
}
Example 6: Card Flip Effect
import { Transform, Matrix4, GestureDetector } from 'flitter';
class FlipCard extends StatefulWidget {
createState() {
return new FlipCardState();
}
}
class FlipCardState extends State {
isFlipped = false;
toggleFlip = () => {
this.setState(() => {
this.isFlipped = !this.isFlipped;
});
};
build() {
return GestureDetector({
onTap: this.toggleFlip,
child: Transform({
transform: (() => {
const matrix = Matrix4.identity();
matrix.rotateY(this.isFlipped ? Math.PI : 0);
return matrix;
})(),
alignment: Alignment.center,
child: Container({
width: 200,
height: 120,
decoration: new BoxDecoration({
color: this.isFlipped ? '#e74c3c' : '#3498db',
borderRadius: BorderRadius.circular(12),
boxShadow: [
new BoxShadow({
color: 'rgba(0, 0, 0, 0.2)',
offset: new Offset({ x: 0, y: 4 }),
blurRadius: 8
})
]
}),
child: Center({
child: Text(
this.isFlipped ? 'Back' : 'Front',
{
style: {
color: 'white',
fontSize: 18,
fontWeight: 'bold'
}
}
)
})
})
})
});
}
}
Best Practices
- No Layout Impact: Transform doesn’t affect widget space consumption, which may cause overlapping with other widgets
- Performance: Complex transformations or many Transform widgets can impact performance
- Angle Units: Rotation angles use radians (degrees * Math.PI / 180)
- Understanding Reference Points: Understand the difference between origin and alignment and use appropriately
- 3D Transformations: Z-axis transformations may require perspective settings
- Animation: Use with AnimationController for smooth transformation animations
Related Widgets
- AnimatedContainer: When you need automatically animated transformations
- RotatedBox: When you need rotation that affects layout
- FractionalTranslation: When you need size-ratio-based translation
- AnimatedRotation: When you need rotation animations
- AnimatedScale: When you need scale animations