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
  • 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