Draw On Element with Cursor
Category: Cursor Animations. Last updated: Aug 20, 2025
Setup — External Scripts
Setup: External Scripts
html
<script src="https://cdn.jsdelivr.net/npm/gsap@3.12.5/dist/gsap.min.js"></script>Code
index.html
html
<div class="draw-section">
<div data-draw="" class="draw-section-bg">
<img src="images/bg-image.avif" loading="lazy" alt="" class="section-bg-image">
</div>
<div class="draw-section-overlay">
<h1 class="draw-heading">draw with</h1>
<h1 class="draw-heading align-right">your cursor</h1>
</div>
</div>styles.css
css
.draw-section {
width: 100%;
height: 100vh;
margin-bottom: 50vh;
position: relative;
}
.draw-heading {
text-transform: uppercase;
margin-top: 0;
margin-bottom: 0;
font-family: PP Neue Corp Tight, Arial, sans-serif;
font-size: 11.25em;
font-weight: 700;
line-height: 1;
}
.draw-heading.align-right {
text-align: right;
}
.draw-section-bg {
z-index: 0;
width: 100%;
height: 100%;
}
.section-bg-image {
object-fit: cover;
width: 100%;
height: 100%;
}
.draw-section-overlay {
z-index: 2;
pointer-events: none;
flex-flow: column;
justify-content: space-between;
align-items: stretch;
padding: 2em;
display: flex;
position: absolute;
inset: 0%;
}
[data-draw]{
position: relative;
}
svg.cursor-svg {
position: absolute;
z-index: 10;
top: 0;
left: 0;
height: 100%;
width: 100%;
pointer-events: none;
mix-blend-mode: difference;
}
svg.cursor-svg line {
stroke: #FF9900;
stroke-width: 15;
stroke-linecap: round;
stroke-linejoin: round;
}
[data-draw]{
position: relative;
}
svg.cursor-svg {
position: absolute;
z-index: 10;
top: 0;
left: 0;
height: 100%;
width: 100%;
pointer-events: none;
mix-blend-mode: difference;
}
svg.cursor-svg line {
stroke: #FF9900;
stroke-width: 15;
stroke-linecap: round;
stroke-linejoin: round;
}script.js
javascript
function supportsTouch() {
return (('ontouchstart' in window) ||
(navigator.maxTouchPoints > 0) ||
(navigator.msMaxTouchPoints > 0));
}
function initDrawing() {
if (supportsTouch()) { return; } // Exit function if it's a touch device
let svgns = "http://www.w3.org/2000/svg";
// Function that creates an SVG Line
function createLine(root, x, y) {
let line = document.createElementNS(svgns, "line");
line.setAttribute("x1", x);
line.setAttribute("y1", y);
line.setAttribute("x2", x);
line.setAttribute("y2", y);
root.appendChild(line);
return line;
}
function handleDrawing(element) {
// Create an empty SVG inside the [data-draw] wrapper. This is where we will render the lines in
let svgRoot = document.createElementNS(svgns, "svg");
svgRoot.classList.add("cursor-svg");
element.appendChild(svgRoot);
let currentLine = null;
// Place first coordinate on mouseenter of [data-draw] element
element.addEventListener("mouseenter", (event) => {
currentLine = createLine(svgRoot, event.offsetX, event.offsetY);
});
// Create lines on every mousemove
element.addEventListener("mousemove", (event) => {
if (currentLine) {
currentLine.setAttribute("x2", event.offsetX);
currentLine.setAttribute("y2", event.offsetY);
currentLine = createLine(svgRoot, event.offsetX, event.offsetY);
}
});
// On mouseleave of the [data-draw] wrap, smoothly remove all lines
element.addEventListener("mouseleave", () => {
if (currentLine) {
gsap.to(svgRoot.querySelectorAll("line"), {
strokeOpacity: 0,
duration: 0.01,
stagger: 0.01,
ease: "none",
onComplete: () => {
svgRoot
.querySelectorAll("line")
.forEach((line) => svgRoot.removeChild(line));
},
});
currentLine = null;
}
});
}
document.querySelectorAll("[data-draw]").forEach(handleDrawing);
}
// Initialize Draw on Element with Cursor
document.addEventListener('DOMContentLoaded', () => {
initDrawing();
});Guide
Implementation
Add a div or other HTML element anywhere on your site with an attribute of data-draw and make sure it has any position that is not static. The JS will add an SVG element in this data-draw wrapper. So you can get creative with adding this over images, videos, or simply coloured blocks.
Customising
Play around with the styling of the SVG line element in the CSS to determine what the drawn line looks like. For an extra effect, we added a blend-mode of difference to the SVG element.