Matrix

Palette

SVG Matrix

SVG is a web native standard for scalable vector graphics.

We can use Matrix to make transforms embedded in an SVG.

SVG transforms can be applied a few ways:

These transforms tend to be limited to a 3x2 matrix (though technically should support both).

We can always set use the style attribute to provide a custom style, or use the class attribute to style our SVG using CSS.

There are numerous things we can do with SVG transforms.

For example, we can use a scale transform to give object apparent depth.

If we want an object to appear twice as far away, we can scale it down by 0.5.

If we want an object to appear four times as far away, we can scale it by 0.25.

The general formula for apparent distance scaling is:

1/[Math]::Pow(2, $scale - 1)

We can think of this a step function.

function copyz {
    param(
    [int]
    $StepCount = 4,

    [double]
    $InitialScale = 1,

    [double]
    $FinalScale = 9,

    [string]
    $Element = 'rect',

    [string[]]
    $Attribute,

    [string[]]
    $Children
    )

    if (-not $StepCount) {
        $stepCount = 1
    }

    $attribute += @(
        "fill='transparent'"
        "stroke='currentColor' class='foreground-stroke'"
        "x='0%' y='0%'"
        "width='100%' height='100%'"
        "transform-origin='50% 50%'"
    )
    
    $scaleStep = ($FinalScale - $InitialScale)/$StepCount    
    for ($scale = $InitialScale; [Math]::Abs($scale) -lt [Math]::Abs($FinalScale); $scale += $scaleStep) {
        $scaleFactor = 1/[Math]::Pow(2,($scale - 1))

        "<$element$(
            if ($Attribute) {
                " $attribute"
            }    
        )$(
            " transform='$((Scale $scaleFactor).CSS)'"
        )>$($Children -join [Environment]::Newline)</$element>"
    }    
}

4 steps

8 steps

16 steps

32 steps

64 steps

128 steps

As the steps increase, the object seems deeper

Drawing diagonals might help understand what is happenning

The center of the X is the center of our perpsective

transform-origin

Changing our

transform-origin
changes the center of the effect

transform-origin:0% 0%

transform-origin:100% 0%

transform-origin:0% 100%

transform-origin:100% 100%

Transform Origin Animation

We can animate our transform origin with CSS keyframes


@keyframes look-up-and-down {
    0%, 100% {
        transform-origin: 50% 50%;
    }
    33% {
        transform-origin: 50% 25%;
    }
    66% {
        transform-origin: 50% 75%;
    }    
}
.look-up-and-down {
    animation-name: look-up-and-down;
    animation-duration: 4.2s;
    animation-iteration-count: infinite;
}

We can look left and right


@keyframes look-left-and-right {
    0%, 100% {
        transform-origin: 50% 50%;
    }
    33% {
        transform-origin: 25% 50%;
    }
    66% {
        transform-origin: 75% 50%;
    }    
}
.look-left-and-right {
    animation-name: look-left-and-right;
    animation-duration: 4.2s;
    animation-iteration-count: infinite;
}

We can look around


@keyframes look-around {
    0%, 100% {
        transform-origin: 50% 50%;
    }
    20% {
        transform-origin: 25% 25%;
    }
    40% {
        transform-origin: 75% 25%;
    }
    60% {
        transform-origin: 25% 75%;
    }
    80% {
        transform-origin: 75% 75%;
    }    
}
.look-around {
    animation-name: look-around;
    animation-duration: 8.4s;
    animation-iteration-count: infinite;
}

Motion

We can animate the transform to give us motion

If we scale from our factor to 1, the object seems to get closer

If we scale from 1 to our factor, the object seems to get farther away

We can also transform the element itself, with all of our inner transforms intact

We can animate this, too

We can also animate our transform-origin as we animate our transform

Let's revisit our lookaround examples, with some added motion

Circles

We can perform this magic trick with any shape.

Using instead of produces some interesting results.

We can also look up and down

Or look left and right

We can use a transform-origin that exceeds 100%.

This will make things appear outside of their original bounds.

When animated, this can look like we are moving outside the original object.

@keyframes look-far-left-and-right {
    0%, 100% {
        transform-origin: 50% 50%;
    }
    33% {
        transform-origin: -25% 50%;
    }
    66% {
        transform-origin: 125% 50%;
    }    
}
.look-far-left-and-right {
    animation-name: look-far-left-and-right;
    animation-duration: 4.2s;
    animation-iteration-count: infinite;
}