Corner Pin

코너 핀

Each corner moves independently, warping the image to fit a skewed plane.

Also known as: CornerPinFour-corner warp

Moves in browsers that support WebGPU

This device could not render the demo — showing a still

React
// Renders only in browsers with WebGPU.
// /samples/… are this site’s sample files — point them at your own image or video.
import { Shader, CornerPin, ImageTexture } from 'shaders/react'

export default function ShaderEffect() {
  return (
    <Shader style={{ width: '100%', height: 320 }} disableTelemetry>
      <ImageTexture
        objectFit="cover"
        url="/samples/poster.jpg" />
      <CornerPin
        bottomLeft={{
          x: 0.03,
          y: 0.92
        }}
        bottomRight={{
          x: 0.96,
          y: 0.86
        }}
        topLeft={{
          x: 0.08,
          y: 0.14
        }}
        topRight={{
          x: 0.88,
          y: 0.04
        }} />
    </Shader>
  )
}
Vue
<!-- Renders only in browsers with WebGPU. -->
<!-- /samples/… are this site’s sample files — point them at your own image or video. -->
<script setup lang="ts">
import { Shader, CornerPin, ImageTexture } from 'shaders/vue'
</script>

<template>
  <Shader style="width: 100%; height: 320px" :disable-telemetry="true">
    <ImageTexture
      object-fit="cover"
      url="/samples/poster.jpg"/>
    <CornerPin
      :bottom-left="{
        x: 0.03,
        y: 0.92
      }"
      :bottom-right="{
        x: 0.96,
        y: 0.86
      }"
      :top-left="{
        x: 0.08,
        y: 0.14
      }"
      :top-right="{
        x: 0.88,
        y: 0.04
      }"/>
  </Shader>
</template>
Svelte
<!-- Renders only in browsers with WebGPU. -->
<!-- /samples/… are this site’s sample files — point them at your own image or video. -->
<script>
  import { Shader, CornerPin, ImageTexture } from 'shaders/svelte'
</script>

<Shader style="width: 100%; height: 320px" disableTelemetry>
  <ImageTexture
    objectFit="cover"
    url="/samples/poster.jpg" />
  <CornerPin
    bottomLeft={{
      x: 0.03,
      y: 0.92
    }}
    bottomRight={{
      x: 0.96,
      y: 0.86
    }}
    topLeft={{
      x: 0.08,
      y: 0.14
    }}
    topRight={{
      x: 0.88,
      y: 0.04
    }} />
</Shader>
Solid
// Renders only in browsers with WebGPU.
// /samples/… are this site’s sample files — point them at your own image or video.
import { Shader, CornerPin, ImageTexture } from 'shaders/solid'

export default function ShaderEffect() {
  return (
    <Shader style={{ width: '100%', height: '320px' }} disableTelemetry>
      <ImageTexture
        objectFit="cover"
        url="/samples/poster.jpg" />
      <CornerPin
        bottomLeft={{
          x: 0.03,
          y: 0.92
        }}
        bottomRight={{
          x: 0.96,
          y: 0.86
        }}
        topLeft={{
          x: 0.08,
          y: 0.14
        }}
        topRight={{
          x: 0.88,
          y: 0.04
        }} />
    </Shader>
  )
}
JavaScript
// Renders only in browsers with WebGPU.
// /samples/… are this site’s sample files — point them at your own image or video.
// expects <canvas id="canvas" style="width:100%;height:320px"></canvas> on the page
import { createShader } from 'shaders/js'

const shader = await createShader(document.getElementById("canvas"), {
  components: [
    {
      type: 'ImageTexture',
      props: {
        objectFit: 'cover',
        url: '/samples/poster.jpg',
      },
    },
    {
      type: 'CornerPin',
      props: {
        bottomLeft: {
          x: 0.03,
          y: 0.92
        },
        bottomRight: {
          x: 0.96,
          y: 0.86
        },
        topLeft: {
          x: 0.08,
          y: 0.14
        },
        topRight: {
          x: 0.88,
          y: 0.04
        },
      },
    }
  ]
}, { disableTelemetry: true })

Props · CornerPin

Changes apply to the demo above and to the code tabs. Descriptions come from the library registry (MIT).

NameValueDefaultRange / optionsDescription
topLeftTop Left
x0.08y0.14
{"x":0,"y":0}x, y: 0 – 1Position of the top-left corner
topRightTop Right
x0.88y0.04
{"x":1,"y":0}x, y: 0 – 1Position of the top-right corner
bottomLeftBottom Left
x0.03y0.92
{"x":0,"y":1}x, y: 0 – 1Position of the bottom-left corner
bottomRightBottom Right
x0.96y0.86
{"x":1,"y":1}x, y: 0 – 1Position of the bottom-right corner
amountAmount10 – 1 (step 0.01)Blends the warp in and out — 0 returns the content to its original rectangle, 1 fully pins the corners
edgesEdgestransparentstretch · transparent · mirror · wrapHow to handle areas outside the pinned quad

Every component also takes blendMode · opacity · visible · maskSource/maskType · boundingBox · id

Like projecting a flat screen onto a wall at an angle, the four corners move independently to fit the image into a skewed plane.

`topLeft`, `topRight`, `bottomLeft`, and `bottomRight` set the corner positions. `amount` blends between the original rectangle and the full corner warp.

Place it above an image layer. Pair it with `Perspective` for a more precisely fitted mockup. Pulling corners far can reveal empty edges or distort copy, so adjust `edges` and check legibility after the warp.

When to use

Use it to fit content to an angled device screen or create perspective mockups for posters and video. Avoid it when letter spacing and rectangular proportions must stay unchanged.

Open as page ↗