<!DOCTYPE html>
<html>
<head lang="en">
    <title>Balloons</title>
    <style>
        * {
            user-select: none;
            -webkit-user-select: none;
        }
        body {
            background-color: #303030;
        }
    </style>
</head>
<body>
    <canvas id="canvas2" style="display: none" width="0" height="0"></canvas>
    <canvas id="canvas"
        style="position: absolute; top: 20px; left: 20px; background-color: #606060; border-radius: 25px;" width="0"
        height="0"></canvas>
    <script>
        // disable pinches: hard to implement resizing
        document.addEventListener("touchstart", function (e) {
            if (e.touches.length > 1) {
                e.preventDefault()
            }
        }, { passive: false })
        document.addEventListener("touchmove", function (e) {
            if (e.touches.length > 1) {
                e.preventDefault()
            }
        }, { passive: false })
        // disable trackpad zooming
        document.addEventListener("wheel", e => {
            if (e.ctrlKey) {
                e.preventDefault()
            }
        }, {
            passive: false
        })
        // This is the canvas that shows the result
        const canvas = document.getElementById("canvas")
        // This canvas is hidden and renders the balloon in the background
        const canvas2 = document.getElementById("canvas2")
        // Get contexts
        const ctx = canvas.getContext("2d")
        const ctx2 = canvas2.getContext("2d")
        // Scale the graphic, if you want
        const scaleX = 1
        const scaleY = 1
        // Set up parameters
        var prevRatio, w, h, trueW, trueH, ratio, redBalloon
        function draw() {
            for (var i = 0; i < 1000; i++) {
                ctx.drawImage(redBalloon, Math.round(Math.random() * w), Math.round(Math.random() * h))
            }
            requestAnimationFrame(draw)
        }
        // Updates graphics and canvas.
        function updateSvg() {
            var pW = trueW
            var pH = trueH
            trueW = window.innerWidth - 40
            trueH = Math.max(window.innerHeight - 40, 0)
            ratio = window.devicePixelRatio
            w = trueW * ratio
            h = trueH * ratio
            if (trueW === 0 || trueH === 0) {
                canvas.width = 0
                canvas.height = 0
                canvas.style.width = "0px"
                canvas.style.height = "0px"
                return
            }
            if (trueW !== pW || trueH !== pH || ratio !== prevRatio) {
                canvas.width = w
                canvas.height = h
                canvas.style.width = trueW + "px"
                canvas.style.height = trueH + "px"
                if (prevRatio !== ratio) {
                    // Update graphic
                    redBalloon = svgRed()
                    // Set new ratio
                    prevRatio = ratio
                }
            }
        }
        window.onresize = updateSvg
        updateSvg()
        draw()
        // The vector graphic (you may want to manually tweak the coordinates if they are slightly off (such as changing 25.240999999999997 to 25.241)
        function svgRed() {
            // Scale the hidden canvas
            canvas2.width = Math.round(44 * ratio * scaleX)
            canvas2.height = Math.round(65 * ratio * scaleY)
            ctx2.scale(ratio * scaleX, ratio * scaleY)
            // Draw the graphic
            ctx2.save()
            ctx2.beginPath()
            ctx2.moveTo(0, 0)
            ctx2.lineTo(44, 0)
            ctx2.lineTo(44, 65)
            ctx2.lineTo(0, 65)
            ctx2.closePath()
            ctx2.clip()
            ctx2.strokeStyle = '#0000'
            ctx2.lineCap = 'butt'
            ctx2.lineJoin = 'miter'
            ctx2.miterLimit = 4
            ctx2.save()
            ctx2.beginPath()
            ctx2.moveTo(0, 0)
            ctx2.lineTo(44, 0)
            ctx2.lineTo(44, 65)
            ctx2.lineTo(0, 65)
            ctx2.closePath()
            ctx2.clip()
            ctx2.save()
            ctx2.fillStyle = "#e02f2f"
            ctx2.beginPath()
            ctx2.moveTo(27, 65)
            ctx2.lineTo(22.9, 61.9)
            ctx2.lineTo(21.9, 61)
            ctx2.lineTo(21.1, 61.6)
            ctx2.lineTo(17, 65)
            ctx2.lineTo(27, 65)
            ctx2.closePath()
            ctx2.moveTo(21.8, 61)
            ctx2.lineTo(21.1, 60.5)
            ctx2.bezierCurveTo(13.4, 54.2, 0, 41.5, 0, 28)
            ctx2.bezierCurveTo(0, 9.3, 12.1, 0.4, 21.9, 0)
            ctx2.bezierCurveTo(33.8, -0.5, 45.1, 10.6, 43.9, 28)
            ctx2.bezierCurveTo(43, 40.8, 30.3, 53.6, 22.8, 60.2)
            ctx2.lineTo(21.8, 61)
            ctx2.fill()
            ctx2.stroke()
            ctx2.restore()
            ctx2.save()
            ctx2.fillStyle = "#f59595"
            ctx2.beginPath()
            ctx2.moveTo(18.5, 7)
            ctx2.bezierCurveTo(15.3, 7, 5, 11.5, 5, 26.3)
            ctx2.bezierCurveTo(5, 38, 16.9, 50.4, 19, 54)
            ctx2.bezierCurveTo(19, 54, 9, 38, 9, 28)
            ctx2.bezierCurveTo(9, 17.3, 15.3, 9.2, 18.5, 7)
            ctx2.fill()
            ctx2.stroke()
            ctx2.restore()
            ctx2.restore()
            ctx2.restore()
            // Save the results
            var image = new Image()
            image.src = canvas2.toDataURL()
            return image
        }
    </script>
</body>
</html>