let shape = document.querySelector("#shape1"); let canvas = document.querySelector("canvas"); let ctx = canvas.getContext("2d"); let size = 200; let viewBox = {x:0, y:0, width:100, height:100}; let sizeRatio = size / viewBox.width; const gradient = ctx.createLinearGradient(0, 0, viewBox.width, viewBox.height); gradient.addColorStop(0.2, "rgb(255, 135, 9)"); gradient.addColorStop(0.7, "rgb(247, 189, 248)"); setDisplay(); gsap.defaults({ease: "power2.inOut"}); gsap.set(".container", { autoAlpha: 1 }); //set a default render function for all morphSVG animations. You can set it on a per-animation basis too, like morphSVG:{shape:"#id", render:yourFunction} // MorphSVGPlugin.defaultRender = draw; var tl = gsap.timeline({ repeat: -1, id:"morphing", paused:false, defaults: { duration: 2, ease: "expo.inOut" }}) .to(shape, { morphSVG: {shape: "#shape2", render: draw} }) .to(shape, { morphSVG: {shape: "#shape3", render: draw} }, "+=0.5") .to(shape, { morphSVG: {shape: "#shape4", render: draw} }, "+=0.5") .to(shape, { morphSVG: {shape: "#shape1", render: draw} }, "+=0.5") tl.progress(0.0001); //just to force the first render; // GSDevTools.create({animation:tl, globalSync:false, paused:true}); document.body.addEventListener("click", function() { tl.paused(!tl.paused()); }); function draw(rawPath, target) { var l, segment, j, i; ctx.clearRect(0, 0, size, size); ctx.fillStyle = gradient; ctx.fill("evenodd"); ctx.beginPath(); for (j = 0; j < rawPath.length; j++) { segment = rawPath[j]; l = segment.length; ctx.moveTo(segment[0], segment[1]); for (i = 2; i < l; i+=6) { ctx.bezierCurveTo(segment[i], segment[i+1], segment[i+2], segment[i+3], segment[i+4], segment[i+5]); } if (segment.closed) { ctx.closePath(); } } ctx.fill("evenodd"); } function setDisplay() { var ratio = window.devicePixelRatio || 1; canvas.width = size * ratio; canvas.height = size * ratio; gsap.set(canvas, { width: size, height: size }); ratio *= sizeRatio; ctx.translate(-viewBox.x * ratio, -viewBox.y * ratio); ctx.scale(ratio, ratio); }