Latest 0.4
License MIT
Platforms ios 11.0
Frameworks UIKit, CoreGraphics, QuartzCore

Perspective Transform

Build Status
Carthage compatible

PerspectiveTransform caclulates homogeneous transformation matrix for a view 3D projection in 2D. It can be used to place views within given image visual perspective using Core Animation CATransform3D and CALayer.tranform. Projection is caclulated between source and destination perspectives that are defined by 4 corners, assuming they form a Quadrilateral.


To place an overlay image on top of a container image with matching persperctive we can use Core Animation transform matrix. CATransform3D is a tranformation matrix that is used to rotate, scale, translate, skew, and project the layer content. It can also be used to describe a perspective projectection of 2D shape in 3D space.

Container Overlay Combination
Container Overlay Combined image

Core Animation allow applying CATransform3D to CALayer via transform property:

let layer = UIView().layer
layer.transform = CATransform3D(m11: sX,  m12: r12, m13: r13, m14: 0,
                                m21: r21, m22: sY,  m23: r23, m24: 0,
                                m31: r31, m32: r32, m33: 0,   m34: 0,
                                m41: tX,  m42: tY,  m43: 0,   m44: 1)

In detail CATransform3D is a 4 x 4 matrix which takes 16 parameters to build.

Translation and scale are represented by their axis components: (tX, tY) and (sX, sY) within the matrix. While 3D rotation is represented by multiple values: r12, r21, r13, r31, r32, r23.

Perspective Transform based on 4 corners

We can easily see 4 points with container image where the corners of the overlay image should be. In general it is a 4 point polygon. Using an SVG editor we can draw that polygon using container image as a background. Here is preview of the SVG file desribing placement of iPad screen corners

SVG polygon

Click image to see original SVG file defining polygon with points. From those 4 points we can calculate nessesary CATransform3D matrix using this PerspectiveTransform library.

Visual Example

We can see how 4 points polygon fits on the background image:

SVG polygon

SVG Points

We can even take coordinates of those 4 points from SVG file:

<polygon points="377.282671 41.4352201 459.781253 251.836131 193.321418 330.023027 108.315837 80.1687782 "></polygon>

Those are 4 pairs of X and Y coordinates:

377.282671 41.4352201
459.781253 251.836131
193.321418 330.023027
108.315837 80.1687782

Swift Code Example

Here is complete example of placing overlay view using those coordinates:

import PerspectiveTransform

// note order: top left, top right, bottom left, bottom right
let destination = Perspective(
    CGPoint(x: 108.315837, y: 80.1687782),
    CGPoint(x: 377.282671, y: 41.4352201),
    CGPoint(x: 193.321418, y: 330.023027),
    CGPoint(x: 459.781253, y: 251.836131)

// Starting perspective is the current overlay frame
let start = Perspective(overlayView.frame)

// Caclulate CATransform3D from start to destination
overlayView.layer.transform = start.projectiveTransform(destination: destination)

CALayer transform

Since CALayer transform is animatable property we can easily define smooth transition:

SVG polygon

Example Project

See Example iOS project illustating animation and interactive tranform within view controllers. To build Example project run pod install within Example folder.

Example project also includes Swift Playground with couple of live examples.


PerspectiveTransform is available through CocoaPods. To install
it, simply add the following line to your Podfile:

pod 'PerspectiveTransform'

Useful Links


Paul Zabelin,


PerspectiveTransform is available under the MIT license. See the LICENSE file for more info.

Latest podspec

    "name": "PerspectiveTransform",
    "cocoapods_version": "~> 1.5",
    "version": "0.4",
    "summary": "Perspective Transform calculates CATransform3D",
    "description": "Calculates CATransform3D to transform rectangular frame to convex quadrilateralnAllows to overlay images in UIView given 4 points.",
    "homepage": "",
    "screenshots": "",
    "license": {
        "type": "MIT"
    "authors": {
        "Paul Zabelin": ""
    "source": {
        "git": "",
        "tag": "0.4"
    "social_media_url": "",
    "platforms": {
        "ios": "11.0"
    "swift_version": "4.2",
    "source_files": "Pod/Classes/**/*",
    "frameworks": [
    "testspecs": [
            "name": "UnitSpecs",
            "test_type": "unit",
            "source_files": [
            "dependencies": {
                "Quick": "~> 1.3",
                "Nimble": "~> 7.1"
            "name": "AppSpecs",
            "test_type": "unit",
            "requires_app_host": true,
            "resources": "Example/Tests/**/*.{png,jpg,svg}",
            "source_files": [
            "dependencies": {
                "Quick": "~> 1.3",
                "Nimble-Snapshots": "~> 6.8",
                "iOSSnapshotTestCase": "~> 4.0"

Pin It on Pinterest

Share This