Concentric Spin

동심원 회전

Nested rings rotate the underlying image by different amounts.

Also known as: ConcentricSpinRing spin

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, ConcentricSpin, ImageTexture } from 'shaders/react'

export default function ShaderEffect() {
  return (
    <Shader style={{ width: '100%', height: 320 }} disableTelemetry>
      <ImageTexture
        objectFit="cover"
        url="/samples/poster.jpg" />
      <ConcentricSpin />
    </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, ConcentricSpin, ImageTexture } from 'shaders/vue'
</script>

<template>
  <Shader style="width: 100%; height: 320px" :disable-telemetry="true">
    <ImageTexture
      object-fit="cover"
      url="/samples/poster.jpg"/>
    <ConcentricSpin/>
  </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, ConcentricSpin, ImageTexture } from 'shaders/svelte'
</script>

<Shader style="width: 100%; height: 320px" disableTelemetry>
  <ImageTexture
    objectFit="cover"
    url="/samples/poster.jpg" />
  <ConcentricSpin />
</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, ConcentricSpin, ImageTexture } from 'shaders/solid'

export default function ShaderEffect() {
  return (
    <Shader style={{ width: '100%', height: '320px' }} disableTelemetry>
      <ImageTexture
        objectFit="cover"
        url="/samples/poster.jpg" />
      <ConcentricSpin />
    </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: 'ConcentricSpin',
    }
  ]
}, { disableTelemetry: true })

Props · ConcentricSpin

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

NameValueDefaultRange / optionsDescription
intensityIntensity200 – 100 (step 1)Maximum rotation angle per ring
ringsRings81 – 30 (step 1)Number of concentric rings
smoothnessSmoothness0.030 – 1 (step 0.01)Softness of transitions between rings
seedSeed00 – 100 (step 1)Randomization seed for per-ring rotation variation
speedSpeed0.1-5 – 5 (step 0.1)Speed of continuous ring rotation
speedRandomnessSpeed Randomness0.50 – 1 (step 0.01)How much each ring varies in rotation speed and direction
edgesEdgesmirrorstretch · transparent · mirror · wrapHow to handle edges when distortion pushes content out of bounds
centerCenter Position
x0.5y0.5
{"x":0.5,"y":0.5}x, y: 0 – 1Center point of the concentric rings

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

Like ripples drawn as nested circles, each ring turns the underlying image by a different amount.

Move `center` to reposition the rings and set their number with `rings`. `intensity` changes the amount of rotation, `smoothness` softens boundaries between rings, and higher `speed` makes the rotation faster.

Apply it above an image or pattern layer. Pair it with `Kaleidoscope` to add rotational rhythm to radial symmetry. Faces and copy can break across rings, so use abstract input or short transitions.

When to use

Use it for radial abstract backgrounds, music visuals, and circular transitions. Avoid it when faces or long copy need to stay whole.

Open as page ↗