<script src="https://cdn.jsdelivr.net/npm/p5@1.9.0/lib/p5.js"></script>
body {margin:0px; padding:0px; overflow: hidden}
let originalShape = [];
let transformedShape = [];
let originalGrid = [];
let transformationMatrix;

function setup() {
    createCanvas(windowWidth, windowHeight);
    initializeShapes();
}

function draw() {
    background("#F7EDFF");
  
    const skewX = map(mouseX, 0, width, -0.5, 0.5);
    const skewY = map(mouseY, 0, height, -0.5, 0.5);
    transformationMatrix = [
        1, skewX, 0,
        skewY, 1, 0,
        0, 0, 1
    ];

    transformedShape = applyTransformation(originalShape, transformationMatrix);
    let transformedGrid = applyTransformation(originalGrid, transformationMatrix);
  
    push();
    translate(width / 4, height / 2);
    drawGrid(originalGrid);
    drawShape(originalShape);
    pop();
  
    push();
    translate(width / 4 * 3, height / 2);
    drawGrid(transformedGrid);
    drawShape(transformedShape);
    pop();
    
}

function initializeShapes() {
  const scale = min(width / 2, height / 2) * 0.4;
    let outerRadius = scale, innerRadius = outerRadius * 0.6, points = 18;
    for (let i = 0; i < points; i++) {
        let angle = TWO_PI * (i / points), r = i % 2 === 0 ? outerRadius : innerRadius;
        originalShape.push(createVector(cos(angle) * r, sin(angle) * r));
    }

    let gridSize = scale * 0.5, halfSize = scale;
    for (let i = -2; i <= 2; i++) {
        originalGrid.push(createVector(i * gridSize, -halfSize), createVector(i * gridSize, halfSize));
    }
    for (let j = -2; j <= 2; j++) {
        originalGrid.push(createVector(-halfSize, j * gridSize), createVector(halfSize, j * gridSize));
    }
}

function applyTransformation(points, matrix) {
    let result = [];
    for (let pt of points) {
        let xNew = matrix[0] * pt.x + matrix[1] * pt.y + matrix[2] * 1;
        let yNew = matrix[3] * pt.x + matrix[4] * pt.y + matrix[5] * 1;
        result.push(createVector(xNew, yNew));
    }
    return result;
}

function drawShape(points) {
    strokeWeight(2);
    noFill();
    beginShape();
    for (let pt of points) {
        vertex(pt.x, pt.y);
    }
    endShape(CLOSE);

    noStroke();
    fill(0);
    for (let pt of points) {
        ellipse(pt.x, pt.y, 8, 8);
    }
}

function drawGrid(points) {
  strokeWeight(1);
    for (let i = 0; i < points.length; i += 2) {
        line(points[i].x, points[i].y, points[i + 1].x, points[i + 1].y);
    }
}
Run Pen

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.