
The dinosaur-bitten logo
Intro, SVG, Text
NewFree
A logo intro with a big paintbrush: it lands on the canvas, its bristles bend and splay, and it drags a wide, textured stroke that runs out of paint and turns dry at the end, with splashes and drips. The letters open in the paint in negative, a second yellow stroke fills them and at the end a drop falls from the brush. In the Playground you type your own name or upload your own logo.
A folder that runs on its own: index.html, style.css, script.js and the libraries from a CDN. The React and Vue tabs hold the same demo as a ready component, which switches its animations off when it leaves the page.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>The paintbrush logo</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/syne@5.3.0/index.css">
<link rel="stylesheet" href="style.css">
</head>
<body>
<main class="scena">
<!-- the stage: the script measures it, paints the canvas weave, builds the strokes and the brush, and paints the logo -->
<svg class="palco" data-stage role="img" aria-label="Daubry" xmlns="http://www.w3.org/2000/svg">
<defs>
<!-- the weave of the primed canvas: a little tile of threads the script paints on a canvas -->
<pattern id="weave" patternUnits="userSpaceOnUse" width="96" height="96">
<image width="96" height="96" data-weave-image />
</pattern>
<!-- the frayed, streaky edges of a brush stroke: a noise stretched along the stroke pushes the edges about -->
<filter id="fray" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB" data-fray>
<feTurbulence type="fractalNoise" numOctaves="2" result="streaks" data-fray-turb />
<feDisplacementMap in="SourceGraphic" in2="streaks" xChannelSelector="R" yChannelSelector="G" data-fray-disp />
</filter>
<filter id="fray-2" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB" data-fray-2>
<feTurbulence type="fractalNoise" numOctaves="2" result="streaks" data-fray-turb-2 />
<feDisplacementMap in="SourceGraphic" in2="streaks" xChannelSelector="R" yChannelSelector="G" data-fray-disp-2 />
</filter>
<!-- the logo cut out of the paint: white keeps the paint, the black letters open in it -->
<mask id="holes" maskUnits="userSpaceOnUse" data-holes-mask>
<rect fill="#fff" data-holes-rect />
<g data-holes></g>
</mask>
<!-- the brush is painted as wide as it goes: these two follow its tip -->
<clipPath id="reveal-1"><rect data-reveal-1 /></clipPath>
<clipPath id="reveal-2"><rect data-reveal-2 /></clipPath>
<!-- the brush's shadow on the canvas: its own outline, soft and dark -->
<filter id="brush-shadow" x="-40%" y="-40%" width="180%" height="180%">
<feGaussianBlur in="SourceAlpha" stdDeviation="6" result="soft" data-shadow-blur />
<feFlood class="ombra-tinta" result="tone" />
<feComposite in="tone" in2="soft" operator="in" />
</filter>
<!-- the wet shine that runs along the fresh paint -->
<linearGradient id="gloss-grad" x1="0" y1="0" x2="1" y2="0">
<stop offset="0" class="lucido-stop lucido-stop--via" />
<stop offset="0.5" class="lucido-stop" />
<stop offset="1" class="lucido-stop lucido-stop--via" />
</linearGradient>
</defs>
<!-- the primed canvas -->
<rect class="tela" data-wall />
<rect class="tela-trama" fill="url(#weave)" data-weave />
<g data-world>
<!-- the paint: the second colour under the first, the drips, the first stroke with the logo cut out of it -->
<g data-paint>
<g clip-path="url(#reveal-2)" data-coat-2></g>
<g data-drips></g>
<g mask="url(#holes)" data-coat-1-holder>
<g data-coat-1-place>
<g clip-path="url(#reveal-1)" data-coat-1></g>
</g>
<g data-rims></g>
<g data-ripples></g>
</g>
<g data-spots></g>
</g>
<!-- the brush and its shadow; 0 0 is the middle of the bristles' tip -->
<g data-shadow-place opacity="0">
<use href="#brush" filter="url(#brush-shadow)" />
</g>
<g data-brush-place>
<g id="brush">
<g data-handle-place>
<g data-handle></g>
</g>
<path class="setole" data-bristles />
<path class="setole-colore" data-bristles-paint />
<path class="setole-fili" data-strands />
<path class="setole-lucido" data-strands-light />
<path class="ghiera" data-ferrule />
<path class="ghiera-righe" data-ferrule-lines />
<path class="ghiera-luce" data-ferrule-light />
<g class="goccia-pennello" data-hanging>
<line data-hanging-neck />
<circle data-hanging-drop />
</g>
</g>
</g>
<g data-fx></g>
</g>
</svg>
<p class="nota">Click or tap to see it again</p>
</main>
<script src="https://cdn.jsdelivr.net/npm/gsap@3.15.0/dist/gsap.min.js"></script>
<script src="script.js"></script>
</body>
</html>Change values, colours and text with the controls and watch the animation respond live. Or write in the code yourself. Then download the folder with your changes.
30 values to change
With the Animorio connector, Claude Code takes it from here, guide included, and fits it into your project. Paste this request:
Take “The paintbrush logo” from Animorio and fit it into my siteThe stage is an SVG whose viewBox is as big as the window, so one unit is one pixel. The letters are measured on a canvas in the same typeface (measureText, actualBoundingBoxAscent for the true height) and everything is counted in letter heights: the stroke is as tall as the logo plus a margin, starts one height before it and ends, dry, a little after; the brush is as wide as the stroke. On a tall screen the logo takes the whole width and the dry ends may run off the edge.
The body is a single path: an upper and a lower edge moved by a sum of sines, a fat round start where the brush landed and an end that breaks into fingers of paint. A filter pushes the edges about with a feDisplacementMap driven by a feTurbulence stretched along the stroke (low frequency across, high frequency up and down), so the edges turn into threads. On top lie the dark ridges and the shiny streaks, all parallel to the stroke; towards the end, canvas-coloured streaks with a rising gradient and a random dash let the canvas show through, and past the end broken streaks remain. The stroke is uncovered by a clipPath whose rectangle grows with the same ease as the brush.
Each bristle is a quadratic curve from the mouth of the ferrule to the tip. Three numbers do it all: pressure shortens the tuft and fans it out, drag moves the control point so that the tips trail behind, and how much paint there is decides how far up the coloured part goes (the same piece of curve, worked out with de Casteljau). The ferrule goes from the flat mouth to the round handle, and the handle is drawn once along its own axis. The shadow is a use of the brush with a blur filter, shifted further and paler the further the brush is from the canvas.
The red stroke has a mask: a white rectangle with the letters on it in black, each scaled up from zero with elastic.out around its own centre, so they open as holes in the paint. The same letters, with a dark outline only, make the ridge round the holes. The yellow stroke lies under the red one: it shows only through the holes, under the edge and past the end, so it fills the logo. If IMAGE holds an address, a filter turns the dark and coloured parts of the picture black for the mask, and feMorphology dilate makes the rim.
The whole intro is one timeline, with the labels start, arrive, press, stroke, lift, reveal, fill, drop, rest and leave and timeScale for the speed. The brush follows the stroke through an object that moves along and at every step reads the height of the stroke at that point; an inverse of the ease tells when the brush passes a point, so splashes and drips start at the right moment. The hanging drop stretches, comes away with the jerk and becomes an ellipse that falls with power2.in and splats on the canvas with elastic.out. The first painting is always the same (a random generator with a fixed seed), so the poster always shows the same logo.
| Name | File | Default | What it changes |
|---|---|---|---|
NAME | script.js | 'Daubry' | The logo as a word: it opens in the paint letter by letter. |
IMAGE | script.js | '' | The logo as a picture: the address of a file, or upload it from your computer. If there is one, it takes the place of the word. |
PAINT | script.js | 1 | How loaded the brush is: splashes and drips (0 = clean strokes, 2 = paint dripping everywhere). |
PRESSURE | script.js | 1 | How hard the brush presses: how much the bristles bend and splay, the slap on the canvas and the jolt. |
DRY | script.js | 1 | How long the dry, broken end of each stroke is (0.2 short, 2.5 long). |
TINT | script.js | true | A picture is filled with the second colour; with false it is filled with its own colours. |
SPEED | script.js | 1 | The speed of the whole animation: 2 is twice as fast, 0.5 half as fast. |
REST | script.js | 4 | How many seconds the painted logo stays on show before the paint runs off. |
LOOP | script.js | true | Whether the paint runs off and it is painted again. With false the logo stays, with a glint now and then. |
To present a logo with a gesture full of colour and handwork: the opening of a painter-decorator's site, a paint shop, an art school, a festival, a streetwear brand or a venue, a preview for a client, a loading screen, a social post. It works with a written wordmark and with a picture.
The same animation with the sizes adapted: on a tall screen the logo is almost as wide as the screen, the dry ends of the strokes run off the edge and the big brush comes in and out at the sides. A tap restarts it.
Nothing moves: the brush fades in over the canvas, then the red stroke with its drips fades in and the brush fades away; the letters appear in negative in the stroke and then the yellow that fills them. If the animation starts again, the paint leaves with a fade.
GSAP 3.15.0, Syne (font variabile) 5.3.0.
Compressed with gzip, the three demo files weigh 17 KB; the libraries: GSAP 28 KB.
Tested on 11 October 2026
Use it in your own projects and in your clients’ projects. Do not resell it or redistribute it as is. GSAP stays under its own Standard license. Full license.
With your account’s email and password.
or with your email
You’re signed in as .
With your account, you can download the zip of every animation and every pack, for free.