HTML 5 Canvas Animation messed up while changing resolution and not working on mobile

This is my canvas code, it’s just a simple circle animation with some mousemove effect, but when i try to change my resolution it will make it bigger and messy. Also not working on mobile. IT usually hapens when we scroll down a bit fast, I have added an image you can check dowm below. here’s my code.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="style.css">
    <title>Document</title>
</head>
<body>
    
    <div id="main">
        <div class="hp-hands-wrapper" data-scroll-section="" style="z-index: initial; transform: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); opacity: 1; pointer-events: all;" data-scroll-section-inview="">   
            <div class="object3d-anchor is-inview" data-scroll="" data-scroll-repeat="" data-scroll-call="3dObject" data-scroll-offset="20%"></div>   
            <div class="bg-circle">
              <div class="mobile-circle-wrapper">
                <div class="inner">
                  <div class="mobile-pink-circle"></div>        
                  <div class="mobile-circle mc-01"></div>
                  <div class="mobile-circle mc-02"></div>
                </div>        
              </div>
            </div>
            <h1 class="hands-hdl show is-inview" data-scroll-speed="2" data-scroll="" style="transform: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1.2, 0, 1);">
              <span id="trigger" class="hands-hdl-01 hands-hdl thinkers txt show">predicting the</span> <br>
              <span class="hands-hdl-03 hands-hdl doers txt show">next trend</span>
            </h1>
            <canvas class="scene show is-inview" id="bubble" data-scroll="" width="1920" height="919" style="width: 1920px; height: 919px;"></canvas>
            <h3 class="hands-subhdl el-fade-in is-inview" data-scroll="" data-scroll-speed="1.5" style="transform: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 14.475, 0, 1);">
              with 10 years of experience we already know what today’s trends mean for tomorrow’s world.    </h3>    
            <a href="#" class="btn-scroll-down mlink"></a>
        
            <div class="el-plax el-plax--00 is-inview" data-scroll="" data-scroll-speed="4" style="transform: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 23.35, 0, 1);"></div>
          </div>


    </div>
        <!-- three.js -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/97/three.min.js"></script>
    <script src="https://cdn.rawgit.com/josephg/noisejs/master/perlin.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/2.1.2/TweenMax.min.js"></script>         
    <script>
        /*--------------------
Setup
--------------------*/
let isMobile = window.matchMedia("only screen and (max-width: 649px)").matches;
let isTablet = window.matchMedia("only screen and (min-width: 650px) and (max-width: 990px)").matches;
let isTabletProAndDesktop = window.matchMedia("only screen and (min-width: 830px)").matches;
let isDesktop = window.matchMedia("only screen and (min-width: 1113px)").matches;
let isTouchDevice = window.matchMedia("only screen and (hover: none) and (pointer: coarse)").matches;

console.clear();
const canvas = document.querySelector('#bubble');
let pixelRatio = window.devicePixelRatio
let AA = true
if (pixelRatio > 1) {
  AA = false
}
let width = canvas.offsetWidth,
    height = canvas.offsetHeight;
const renderer = new THREE.WebGLRenderer({
    canvas: canvas,
    antialias: AA,
    powerPreference: "high-performance",
    alpha: true
});
const scene = new THREE.Scene();

const setup = () => {
    renderer.setPixelRatio(window.devicePixelRatio);
    renderer.setSize(width, height);
    renderer.setClearColor(0xebebeb, 0);
    renderer.shadowMap.enabled = true;
    renderer.shadowMapSoft = true;

    // scene.fog = new THREE.Fog(0x4814B8, 20, 950);

    const aspectRatio = width / height;
    const fieldOfView = 100;
    const nearPlane = 0.1;
    const farPlane = 10000;
    camera = new THREE.PerspectiveCamera(
        fieldOfView,
        aspectRatio,
        nearPlane,
        farPlane
    );
    camera.position.x = 0;
    if(isMobile){
        camera.position.y = -60;    
    }else{
        camera.position.y = -10;
    }
    // camera.position.y = -100;
    camera.position.z = 270;
}
setup();


/*--------------------
Lights
--------------------*/
let hemispshereLight, shadowLight, light2;
const createLights = () => {
    hemisphereLight = new THREE.HemisphereLight(0xFCDCEF, 0x4A7DFF, .3),

        shadowLight = new THREE.DirectionalLight(0xE4C8FF, .1);
    shadowLight.position.set(0, 1650, 450);
    shadowLight.castShadow = true;
    shadowLight.shadow.radius = 18;
    shadowLight.shadow.camera.left = -950;
    shadowLight.shadow.camera.right = 950;
    shadowLight.shadow.camera.top = 950;
    shadowLight.shadow.camera.bottom = -950;
    shadowLight.shadow.camera.near = 1;
    shadowLight.shadow.camera.far = 4000;
 

    shadowLight.shadow.mapSize.width = 4096;
    shadowLight.shadow.mapSize.height = 4096;
    
    light2 = new THREE.DirectionalLight(0xFBD44B, .25);
    light2.position.set(-600, 350, 350);

    light3 = new THREE.DirectionalLight(0x8EBBFF, .45);
    light3.position.set(0, -250, 300);

    scene.add(hemisphereLight);
    scene.add(shadowLight);
    scene.add(light2);
    scene.add(light3);
}
createLights();
initGui();

/*--------------------
Bubble
--------------------*/
const vertex = width > 575 ? 80 : 40;
const bubbleGeometry = new THREE.SphereGeometry(120, vertex, vertex);
let bubble, bubbleMaterial;
const createBubble = () => {
    for (let i = 0; i < bubbleGeometry.vertices.length; i++) {
        let vector = bubbleGeometry.vertices[i];
        vector.original = vector.clone();
    }
    bubbleMaterial = new THREE.MeshStandardMaterial({
        emissive: 0xAA8CFF,   //change color code here
        emissiveIntensity: 0.7,
        roughness: 0.8,
        metalness: 0.5,
        side: THREE.FrontSide
    });
    bubble = new THREE.Mesh(bubbleGeometry, bubbleMaterial);
    bubble.castShadow = true;
    bubble.receiveShadow = false;
    scene.add(bubble);
}
createBubble();


/*--------------------
Plane
--------------------*/
const createPlane = () => {
    // const planeGeometry = new THREE.PlaneBufferGeometry(2000, 2000);
    const planeGeometry = new THREE.PlaneBufferGeometry(2500, 2500);
    const planeMaterial = new THREE.ShadowMaterial({
        opacity: 0.1
    });
    const plane = new THREE.Mesh(planeGeometry, planeMaterial);
    plane.position.y = -200;
    plane.position.x = 0;
    plane.position.z = 0;
    plane.rotation.x = Math.PI / 180 * -90;
    plane.receiveShadow = true;
    scene.add(plane);
}
createPlane();


/*--------------------
Map
--------------------*/
const map = (num, in_min, in_max, out_min, out_max) => {
    return (num - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}


/*--------------------
Distance
--------------------*/
const distance = (a, b) => {
    const dx = a.x - b.x;
    const dy = a.y - b.y;
    const d = Math.sqrt(dx * dx + dy * dy);
    return d;
}


/*--------------------
Mouse
--------------------*/
let mouse = new THREE.Vector2(0, 0);
const onMouseMove = (e) => {
    TweenMax.to(mouse, 0.8, {
        x: e.clientX || e.pageX || e.touches[0].pageX || 0,
        y: e.clientY || e.pageY || e.touches[0].pageY || 0,
        ease: Power2.easeOut
    });
};
if(!isTouchDevice){
    ['mousemove', 'touchmove'].forEach(event => {
        window.addEventListener(event, onMouseMove);
    });
}



/*--------------------
Spring
--------------------*/
let spring = {
    scale: 1
};
const clicking = {
    down: () => {
        TweenMax.to(spring, 1.1, {
            scale: 1.0,
            ease: Power3.easeOut
        });
    },
    up: () => {
        TweenMax.to(spring, .9, {
            scale: 1,
            ease: Elastic.easeOut
        });
    }
};
if(!isTouchDevice){
    ['mousedown', 'touchstart'].forEach(event => {
        window.addEventListener(event, clicking.down);
    });
    ['mouseup', 'touchend'].forEach(event => {
        window.addEventListener(event, clicking.up);
    });
}


/*--------------------
Resize
--------------------*/
const onResize = () => {
    canvas.style.width = '';
    canvas.style.height = '';
    width = canvas.offsetWidth;
    height = canvas.offsetHeight;
    camera.aspect = width / height;
    camera.updateProjectionMatrix();
    maxDist = distance(mouse, {
        x: width / 2,
        y: height / 2
    });
    renderer.setSize(width, height);
}
let resizeTm;
window.addEventListener('resize', function () {
    resizeTm = clearTimeout(resizeTm);
    resizeTm = setTimeout(onResize, 200);
});


/*--------------------
Noise
--------------------*/
let dist = new THREE.Vector2(0, 0);
let maxDist = distance(mouse, {
    x: width / 2,
    y: height / 2
});
const updateVertices = (time) => {
    dist = distance(mouse, {
        x: width / 2,
        y: height / 2
    });
    dist /= maxDist;
    dist = map(dist, 1, 0, 0, 1);
    for (let i = 0; i < bubbleGeometry.vertices.length; i++) {
        let vector = bubbleGeometry.vertices[i];
        vector.copy(vector.original);
        let perlin = noise.simplex3(
            (vector.x * 0.005) + (time * 0.0005), // Adjust the time multiplier for faster animation
            (vector.y * 0.005) + (time * 0.0005), // Adjust the time multiplier for faster animation
            (vector.z * 0.005)
        );
        let ratio = ((perlin * 0.35 * (dist + 0.3)) + 0.8);  //scale the animation
        vector.multiplyScalar(ratio);
    }
    bubbleGeometry.verticesNeedUpdate = true;
}

function initGui() {
    const trigger = document.getElementById('trigger');

    trigger.addEventListener('mouseenter', e => {
        changeColors();
    });
    trigger.addEventListener('mouseleave', e => {
        revertColors();
    });
}

function revertColors() {
    
    light2.color.setHex(0xAA8CFF); // Change color here
    bubbleMaterial.emissive.setHex(0xAA8CFF); // Change color here
    conf.light1Color = chroma.random().hex();
    conf.light2Color = chroma.random().hex();
    conf.light3Color = chroma.random().hex();
    light1.color = new THREE.Color(conf.light1Color);
    light2.color = new THREE.Color(conf.light2Color);
    light3.color = new THREE.Color(conf.light3Color);
    console.log(conf);
}


function changeColors() {
    light2.color.setHex(0xAA8CFF); // Change color here
    bubbleMaterial.emissive.setHex(0xAA8CFF); // Change color here
    conf.light1Color = chroma.random().hex();
    conf.light2Color = chroma.random().hex();
    conf.light3Color = chroma.random().hex();
    light1.color = new THREE.Color(conf.light1Color);
    light2.color = new THREE.Color(conf.light2Color);
    light3.color = new THREE.Color(conf.light3Color);
    console.log(conf);
}

/*--------------------
Animate
--------------------*/
var stopRender = false;
const render = (a) => {
    if(stopRender){
        return true;
    }
    requestAnimationFrame(render);
    bubble.rotation.y = -4 + map(mouse.x, 0, width, 0, 4);
    bubble.rotation.z = 4 + map(mouse.y, 0, height, 0, -4);
    // bubble.rotation.y = -4 + map(mouse.x, 0, width, 0, 4);
    // bubble.rotation.z = 4 + map(mouse.y, 0, height, 0, -4);
    bubble.scale.set(spring.scale, spring.scale, spring.scale);
    updateVertices(a);
    renderer.clear();
    renderer.render(scene, camera);
}

function frameThrottle(original) {
    let pending = false;

    function wrap() {
        pending = false;
        original();
    }

    function proxy() {
        if (!pending) {
            pending = true;
            requestAnimationFrame(wrap);
        }
    }

    return proxy;
}

if(isTabletProAndDesktop){
    frameThrottle(requestAnimationFrame(render));
    renderer.render(scene, camera);    
}




if(isTabletProAndDesktop){
    function stopRendering(){
        stopRender = true;
    }
    function resumeRendering(){
        stopRender = false;
       requestAnimationFrame(render);
    }
}



        
    </script>
</body>
</html>