CoolFace
Apppublic

nicehero/ManualMask

sourceHugging Faceagpl-3.0updated 2y agoView on Hugging Face
1likes
mask3.html774 linesDownload Raw Back to root
1<!DOCTYPE html>2<html>3<head>4    <meta charset="UTF-8">5    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">6    <title>蒙版王</title>7    <style>8        /* 适用于手机的样式 */9        @media (max-width: 767px) {10            body {11                --bg-color: var(--tg-theme-bg-color);12                font: 12px/18px "Lucida Grande", "Lucida Sans Unicode", Arial, Helvetica, Verdana, sans-serif;13                background-color: var(--bg-color);14                color: var(--tg-theme-text-color);15 16                width: 350;17                margin: 0 auto; /* 水平居中 */18            }19            #canvas {20              border: 1px solid #000;21              width: 100%;22              height: auto;23            }24            html, body {25                overflow-x: hidden;26            }27            #uploadButton{28                width: 80%;29            }30            #save{31                width: 20%;32            }33            .myDiv {34                width: 98%;35                display: flex;36                flex-direction: row;37                justify-content: flex-start;38                margin: 0px 1%; 39                flex-wrap: wrap;40            }41            .myDiv1 {42                width: 98%;43                display: flex;44                flex-direction: row;45                justify-content: flex-start;46                margin: 0px 1%; 47            }48            .overlay {49                left: 20px;50            }51        }52        /* 适用于电脑的样式 */53        @media (min-width: 768px) {54            #canvas {55              border: 1px solid #000;56              width: auto;57              height: auto;58            }59            .myDiv {60                display: flex;61                flex-direction: row;62                justify-content: center;63                margin: 0 100px; 64                width: 512px;65                flex-wrap: wrap;66            }67            .myDiv1 {68                display: flex;69                flex-direction: row;70                justify-content: center;71                margin: 0 100px; 72                width: 512px;73            }74            .overlay {75                left: 100px;76            }77        }78        #circle {79            position: absolute;80            width: 10px;81            height: 10px;82            border-radius: 50%;83            border: 2px solid red;84            background-color: transparent;85            transition: opacity 1s;86            pointer-events: none;87        }88        .show {89            opacity: 1;90        }91        .hide {92            opacity: 0;93        }94        .overlay {95            position: absolute;96            top: 82px;97            z-index: 10;98            /* 设置悬浮控件的样式和尺寸 */99            /* 可以使用 z-index 属性来控制层叠顺序 */100        }101    </style>102</head>103<body>104    <div class="myDiv1">105        <button id="uploadButton" style="display: None;">106            选择图片107            <input type="file" id="upload" accept="image/*" style="position: absolute; top: 0; left: 0; width: 98%; height: 100%; opacity: 0; cursor: pointer;">108        </button>109        <button id="save" style="height: 50px;display: None">保存蒙版</button>110        <button id="saveToClipboard" style="height: 50px;box-sizing: border-box; padding: 10px; width: 98%; font-size: 16px; height: 50px;111        line-height: 30px; overflow: hidden; position: relative;">上传蒙版 Upload mask</button>112    </div>113    <div class="myDiv" id="tools">114        <input type="range" id="brushSizeSlider" style="width: 100%" value="40" min="1" max="150" step="1" >115    </div>116    <br>117    <br>118    <div class="myDiv" id="myImg1">119        <canvas id="canvas"></canvas>120        <br>121        <img id="outputImg" ></img>122    </div>123    <div class="overlay" style="display: flex; flex-direction: row; align-items: flex-start;">124        <label style="margin-bottom: 10px;">125            <input type="radio" name="editMode" value="draw" checked> 画笔模式126        </label>127        <label style="margin-bottom: 10px;">128            <input type="radio" name="editMode" value="erase"> 擦除模式129        </label>130        <label>131            <input type="radio" name="editMode" value="select"> 不编辑132        </label>133    </div>134    <div id="circle" style="width: 20px; height: 20px; border-radius: 50%; border: 2px solid red;"></div>135    <!-- <script src="https://telegram.org/js/telegram-web-app.js"></script> -->136    <script>137    // Init TWA138    //Telegram.WebApp.ready();139    //Telegram.WebApp.expand();140    //Telegram.WebApp.enableClosingConfirmation()141    //Telegram.WebApp.HapticFeedback.impactOccurred("medium");142    // Event occurs whenever theme settings are changed in the user's Telegram app (including switching to night mode).143    //Telegram.WebApp.onEvent('themeChanged', function() {144    //    document.documentElement.className = Telegram.WebApp.colorScheme;145    //});146    function getQueryParameter(name) {147        const urlParams = new URLSearchParams(window.location.search);148        return urlParams.get(name);149    }150    async function uploadMask(base64String) {151        const response = await fetch('https://api.imgur.com/3/image', {152            method: 'POST',153            headers: {154                'Authorization': 'Client-ID 955c061744537ff',155                'Content-Type': 'application/json',156            },157            body: JSON.stringify({ image: base64String }),158        });159        const r = await response.json()160        return r.data.link;161    }162window.onerror = function (message, source, lineno, colno, error) {163    const errorData = {164        message: message,165        source: source,166        lineno: lineno,167        colno: colno,168        stack: error ? error.stack : null169    };170    console.error("JavaScript Error:", errorData);171    // 使用 Fetch API 上传错误信息172    fetch('https://u7leyomozktm-5527.shanghai-01.dayunet.com/log-error', {173        method: 'POST',174        headers: {175            'Content-Type': 'application/json'176        },177        body: JSON.stringify(errorData)178    });179};180window.onload = function() {181    var canvas = document.getElementById('canvas');182    var context = canvas.getContext('2d');183    var image = document.getElementById('outputImg');184    var imageMask = new Image();185    var maskData = null;186    var isDrawing = false;187    var brushSize = 40;188    var intervalHandel = null;189    var brushSizeSlider = document.getElementById('brushSizeSlider');190    var editModeRadios = document.getElementsByName('editMode');191    var selectedMode = "draw";192    var isRotate = false;193    function isMobile() {194        return (/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent));195    }196    for (var i = 0; i < editModeRadios.length; i++) {197        editModeRadios[i].addEventListener('change', function() {198            // 获取选中的编辑模式值199            selectedMode = this.value;200            drawImagesInterval(100);201        });202    }203    brushSizeSlider.addEventListener('input', function() {204        brushSize = parseInt(this.value);205        setCircleSize(brushSize);206        if (isMobile()){207            var canvasRect = canvas.getBoundingClientRect();208            var scaleX = canvas.width / canvasRect.width;209            showCircle(175 + window.scrollX, 200 + window.scrollY, scaleX);210        }211    });212    function resizeImage(img,s,resizedImage) {213        var maxWidth = s; // 最大宽度214        var maxHeight = s; // 最大高度215        var width = img.width;216        var height = img.height;217        if (width/height < 4/3 && width <= maxWidth && height <= maxHeight) {218            return false;219        }220        if (!isMobile() && width <= maxWidth && height <= maxHeight) {221            return false;222        }223        if (width > maxWidth || height > maxHeight || width/height >= 4/3) {224            var ratio = Math.max(maxWidth / width, maxHeight / height);225            if (width <= maxWidth && height <= maxHeight){226                ratio = 1;227            }228            width = Math.floor(width * ratio);229            height = Math.floor(height * ratio);230            var tempCanvas = document.createElement('canvas');231            tempCanvas.width = width;232            tempCanvas.height = height;233            var ctx = tempCanvas.getContext('2d');234            isRotate = false;235            if (width/height >= 4/3 && isMobile()){236                tempCanvas.height = width;237                tempCanvas.width = height;238                ctx.clearRect(0, 0, tempCanvas.width, tempCanvas.height);239                ctx.save();240                ctx.translate(tempCanvas.width / 2, tempCanvas.height / 2);241                ctx.rotate(Math.PI / 2);242                ctx.drawImage(img, -img.width / 2, -img.height / 2);243                ctx.restore();244                isRotate = true;245            }246            else {247                ctx.drawImage(img, 0, 0, width, height);248            }249            resizedImage.src = tempCanvas.toDataURL();250            return true;251        }252        return false;253    }254 255    function drawImages() {256        context.clearRect(0, 0, canvas.width, canvas.height);257        context.putImageData(maskData,0,0);258        if (selectedMode == "select") {259            return;260        }261        context.globalAlpha = 0.75; // 设置透明度为0.5262        context.drawImage(image, 0, 0);263        //context.drawImage(imageMask, 0, 0);264        context.globalAlpha = 1; // 恢复透明度为1265    }266    function drawImagesInterval(t) {267        if (intervalHandel != null){268            drawImagesTimeOut(100);269            window.clearInterval(intervalHandel);270            intervalHandel = null;271        }272        intervalHandel = window.setInterval(function() {drawImages();}, t);273    }274    window.addEventListener('scroll', function(event) {275        var scrollTop = window.pageYOffset || document.documentElement.scrollTop;276        var overlay = document.querySelector(".overlay");277        overlay.style.top = (scrollTop + 82) + "px";278    });279    function stopDrawImagesInterval() {280        if (intervalHandel != null){281                drawImagesTimeOut(100);282                window.clearInterval(intervalHandel);283                intervalHandel = null;284        }285    }286    function drawImagesTimeOut(t) {287        window.setTimeout(function() {drawImages();}, t);288    }289    function getImageDataB(img) {290        context.clearRect(0, 0, canvas.width, canvas.height);291        var width = image.width;292        var height = image.height;293        canvas.width = width;294        canvas.height = height;295        context.drawImage(img, 0, 0);296        var imageData = context.getImageData(0, 0, width, height);297        return imageData;298    }299    function getImageData(img) {300        var tempCanvas = document.createElement('canvas');301        tempCanvas.width = canvas.width;302        tempCanvas.height = canvas.height;303        var tempContext = tempCanvas.getContext('2d');304        var width = image.width;305        var height = image.height;306        tempCanvas.width = width;307        tempCanvas.height = height;308        tempContext.drawImage(img, 0, 0);309        var imageData = tempContext.getImageData(0, 0, width, height);310        return imageData;311    }312    function createMaskImageData(width, height) {313        // 创建一个新的ImageData对象314        var imageData = new ImageData(width, height);315        // 获取像素数据316        var data = imageData.data;317        // 将每个像素设置为黑色318        for (var i = 0; i < data.length; i += 4) {319                data[i] = 0;         // 设置红色通道320                data[i + 1] = 0; // 设置绿色通道321                data[i + 2] = 0; // 设置蓝色通道322                data[i + 3] = 255; // 设置透明度通道(不透明)323        }324        return imageData;325    }326    function getImageDataUrl(imageData) {327        var tempCanvas = document.createElement('canvas');328        tempCanvas.width = canvas.width;329        tempCanvas.height = canvas.height;330        var tempContext = tempCanvas.getContext('2d');331        tempContext.putImageData(imageData, 0, 0);332        return tempCanvas.toDataURL();333    }334    async function loadImageFromUrl0(imageUrl) {335        const dataUrl = await convertImageUrlToDataUrl(imageUrl);336        await loadImageFromUrl(dataUrl);337    }338    async function loadImageFromUrl(dataUrl) {339        image.crossOrigin='anonymous';340        image.onload = function() {341                var resizedImage = new Image();342                resizedImage.onload = _ok;343                function _ok(event){344                    image = resizedImage;345                    canvas.width = resizedImage.width;346                    canvas.height = resizedImage.height;347                    maskData = createMaskImageData(image.width,image.height);348                    imageMask.src = getImageDataUrl(maskData);349                    drawImagesTimeOut(100);350                }351                if (!resizeImage(image,512,resizedImage)) {352                    canvas.width = image.width;353                    canvas.height = image.height;354                    maskData = createMaskImageData(image.width,image.height);355                    imageMask.src = getImageDataUrl(maskData);356                    drawImagesTimeOut(100);357                }358        }359        image.src = dataUrl;360    }361    /*362 363    function handleImageLoad(image) {364        var resizedImage = new Image();365        resizedImage.onload = function() {366            image = resizedImage;367            canvas.width = resizedImage.width;368            canvas.height = resizedImage.height;369            maskData = createMaskImageData(image.width, image.height);370            imageMask.src = getImageDataUrl(maskData);371            drawImagesTimeOut(100);372        }373 374        if (!resizeImage(image, 512, resizedImage)) {375            canvas.width = image.width;376            canvas.height = image.height;377            maskData = createMaskImageData(image.width, image.height);378            imageMask.src = getImageDataUrl(maskData);379            drawImagesTimeOut(100);380        }381    }382    // 监听文件选择383    function handleFile(file) {384        var reader = new FileReader();385        reader.onload = function(event) {386            var image = new Image();387            image.onload = function() {388                handleImageLoad(image);389            }390            image.src = event.target.result;391        }392        reader.readAsDataURL(file);393    }394    */395    function handleFile(file) {396        var reader = new FileReader();397        reader.onload = function(event) {398            image.onload = function() {399                var resizedImage = new Image();400                resizedImage.onload = _ok;401                function _ok(event){402                    image = resizedImage;403                    canvas.width = resizedImage.width;404                    canvas.height = resizedImage.height;405                    maskData = createMaskImageData(image.width,image.height);406                    imageMask.src = getImageDataUrl(maskData);407                    drawImagesTimeOut(100);408                }409                if (!resizeImage(image,512,resizedImage)) {410                    canvas.width = image.width;411                    canvas.height = image.height;412                    maskData = createMaskImageData(image.width,image.height);413                    imageMask.src = getImageDataUrl(maskData);414                    drawImagesTimeOut(100);415                }416            }417            image.src = event.target.result;418            console.log(image.src);419        }420        reader.readAsDataURL(file);421    }422    423    // 上传图片424    document.getElementById("upload").addEventListener('change', function(e) {425        var file = e.target.files[0];426        handleFile(file);427    });428 429    // 添加拖拽文件事件监听430    document.addEventListener('dragover', function(e) {431        e.preventDefault();432    });433    document.addEventListener('drop', function(e) {434        e.preventDefault();435        // 获取拖拽事件中的文件对象436        var file = e.dataTransfer.files[0];437        // 执行与文件上传按钮相同的操作438        handleFile(file);439    });440 441    function inRect(x,y,rect){442        return (443            x >= rect.left &&444            x <= rect.right &&445            y >= rect.top &&446            y <= rect.bottom447        );448    }449    function calcCanvasOffset(e,canvas) {450        var canvasRect = canvas.getBoundingClientRect();451        var scaleX = canvas.width / canvasRect.width;452        var scaleY = canvas.height / canvasRect.height;453        var offsetX = (e.clientX - canvasRect.left) * scaleX;454        var offsetY = (e.clientY - canvasRect.top) * scaleY;455        return [offsetX,offsetY,scaleX,scaleY];456    }457    // 开始绘制458    function onTouchDown(e) {459        if (selectedMode == "select") {460            return;461        }462        var canvasRect = canvas.getBoundingClientRect();463        var [offsetX,offsetY,scaleX,scaleY] = calcCanvasOffset(e,canvas);464        //console.log([offsetX,offsetY,scaleX,scaleY]);465        if (!inRect(e.clientX,e.clientY,canvasRect)){466            return;467        }468        if (draw(offsetX, offsetY)) {469            isDrawing = true;470            drawImagesInterval(100);471        }472    }473    document.addEventListener('touchstart', function(event) {474        var touch = event.touches[0];475        onTouchDown(touch);476    });477    document.addEventListener('mousedown',function(event){478        onTouchDown(event);479    } );480    // 结束绘制481    document.addEventListener('mouseup', function() {482        isDrawing = false;483        stopDrawImagesInterval();484    });485    // 绘制中486    function onMove(e) {487        var [offsetX,offsetY,scaleX,scaleY] = calcCanvasOffset(e,canvas);488        if (/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)) {489            showCircle(e.clientX + window.scrollX, e.clientY + window.scrollY, scaleX);490        } else {491            showCircle(e.clientX + window.scrollX, e.clientY + window.scrollY, scaleX);492        }493        var canvasRect = canvas.getBoundingClientRect();494        if (isDrawing) {495            //console.log('onMove1');496            if (!inRect(e.clientX,e.clientY,canvasRect)){497                return;498            }499            draw(offsetX, offsetY);500        }501    }502    canvas.addEventListener('touchmove', function(event) {503        if (selectedMode == "select") {504            return;505        }506        event.preventDefault();507        var touch = event.touches[0];508        onMove(touch);509    }, { passive: false });510    if (!isMobile()) {511        document.addEventListener('mousemove', function(event){512            onMove(event);513        });514    }515 516 517    // 绘制函数518    function draw(x, y) {519        if (selectedMode == "selected") {520                return false;521        }522        if (maskData == null) {523                return false;524        }525        var data = maskData.data;526        var brushRadius = brushSize / 2;527 528        for (var i = -brushRadius; i <= brushRadius; i++) {529            for (var j = -brushRadius; j <= brushRadius; j++) {530                var pixelX = Math.round(x + i);531                var pixelY = Math.round(y + j);532 533                if (pixelX < 0 || pixelX >= canvas.width || pixelY < 0 || pixelY >= canvas.height) {534                    continue;535                }536                var distance = Math.sqrt((pixelX - x) * (pixelX - x) + (pixelY - y) * (pixelY - y));537                if (distance > brushRadius) {538                    continue;539                }540                var index = (pixelY * canvas.width + pixelX) * 4;541                if (selectedMode == "draw"){542                    data[index] = 255;    // 设置红色通道为最大值,即白色543                    data[index + 1] = 255;    // 设置绿色通道为最大值,即白色544                    data[index + 2] = 255;545                }546                else {547                    data[index] = 0;    // 设置红色通道为最大值,即白色548                    data[index + 1] = 0;    // 设置绿色通道为最大值,即白色549                    data[index + 2] = 0;550                }551                552                //data[index + 3] = 128;553            }554        }555        //imageMask.src = getImageDataUrl(maskData);556        return true;557    }558    function generateRandomFileName() {559        var characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';560        var length = 10; // 文件名长度561        var fileName = '';562        for (var i = 0; i < length; i++) {563            var randomIndex = Math.floor(Math.random() * characters.length);564            fileName += characters.charAt(randomIndex);565        }566        return fileName;567    }568    function rotateImageData(imageData) {569      const { width, height } = imageData;570      const rotatedData = new Uint8ClampedArray(width * height * 4);571 572      for (let y = 0; y < height; y++) {573        for (let x = 0; x < width; x++) {574          const srcIndex = (x + y * width) * 4;575          const destIndex = ((width - x - 1) * height + y) * 4;576 577          rotatedData[destIndex] = imageData.data[srcIndex];578          rotatedData[destIndex + 1] = imageData.data[srcIndex + 1];579          rotatedData[destIndex + 2] = imageData.data[srcIndex + 2];580          rotatedData[destIndex + 3] = imageData.data[srcIndex + 3];581        }582      }583 584      return new ImageData(rotatedData, height, width);585    }586    587    function openImageInNewTab(dataUrl) {588        const newTab = window.open();589        newTab.document.write('<html><body style="margin: 0;"><img src="' + dataUrl + '"></body></html>');590        newTab.document.close();591    }592    function saveImageAsFile(dataUrl, filename) {593      // 将 Data URL 转换为 Blob 对象594      const blob = dataURLToBlob(dataUrl);595 596      // 创建一个链接元素597      const link = document.createElement('a');598      link.href = URL.createObjectURL(blob);599      link.download = filename;600 601      // 模拟点击下载链接602      link.click();603 604      // 释放 URL 对象605      URL.revokeObjectURL(link.href);606    }607 608    function dataURLToBlob(dataUrl) {609      console.log(dataUrl);610      const commaIndex = dataUrl.indexOf(',');611      const mime = dataUrl.substring(5, commaIndex);612      const base64Data = dataUrl.substring(commaIndex + 1);613      const byteCharacters = atob(base64Data);614      const byteNumbers = new Array(byteCharacters.length);615 616      for (let i = 0; i < byteCharacters.length; i++) {617        byteNumbers[i] = byteCharacters.charCodeAt(i);618      }619 620      const byteArray = new Uint8Array(byteNumbers);621 622      return new Blob([byteArray], { type: mime });623    }624    625    document.getElementById('saveToClipboard').addEventListener('click',async function() {626        var data = maskData.data;627        var tempCanvas = document.createElement('canvas');628        var ctx = tempCanvas.getContext('2d');629        if (isRotate == true){630            var rData = rotateImageData(maskData);631            tempCanvas.height = maskData.width;632            tempCanvas.width = maskData.height;633            ctx.putImageData(rData, 0, 0);634        }635        else {636            tempCanvas.width = canvas.width;637            tempCanvas.height = canvas.height;638            ctx.putImageData(maskData, 0, 0);639        }640        //await navigator.clipboard.writeText(tempCanvas.toDataURL("image/jpeg", 0.9));641        const response = await fetch(tempCanvas.toDataURL("image/png"));642        const blob = await response.blob();643        const item = new ClipboardItem({ [blob.type]: blob });644        await navigator.clipboard.write([item]);645        646        const img = document.getElementById('outputImg');647        img.src = tempCanvas.toDataURL("image/jpeg");648        const base64String = img.src.split(',')[1];649        const response2 = await fetch(650        'https://u7leyomozktm-5527.shanghai-01.dayunet.com/uploadVPMask/' + getQueryParameter('id'),{651        //'https://api.imgur.com/3/image', {652            method: 'POST',653            headers: {654                'Authorization': 'Client-ID 955c061744537ff',655                'Content-Type': 'application/json',656            },657            body: JSON.stringify({ image: base64String }),658        });659        /*const r = await response2.json();660        img.src = r.data.link;661        //Telegram.WebApp.sendData("" + Telegram.WebApp.initDataUnsafe.user.id + ";" + r.data.link);662        const script = document.createElement('script');663        script.src = "https://telegram.org/js/telegram-widget.js?22";664        script.setAttribute('data-telegram-share-url', r.data.link);665        script.async = true;666        */667        const myImg1 = document.getElementById('myImg1');668        const firstChild = myImg1.firstChild;669        let sendback = document.createElement('a');670        sendback.href = 'https://t.me/ainudevideo_bot?start=mask_ok';// + r.data.link;671        sendback.textContent = 'sendback';672        sendback.click();673        sendback.innerHTML = "如果点击按钮没有反应,请点这个链接 If there is no response when clicking the button, please click on this link";674        myImg1.insertBefore(sendback, firstChild);675        //Telegram.WebApp.close();676    });677 678    // 保存蒙版679    document.getElementById('save').addEventListener('click', function() {680        var data = maskData.data;681        var tempCanvas = document.createElement('canvas');682        var ctx = tempCanvas.getContext('2d');683        if (isRotate == true){684            var rData = rotateImageData(maskData);685            tempCanvas.height = maskData.width;686            tempCanvas.width = maskData.height;687            ctx.putImageData(rData, 0, 0);688        }689        else {690            tempCanvas.width = canvas.width;691            tempCanvas.height = canvas.height;692            ctx.putImageData(maskData, 0, 0);693        }694        var link = document.createElement('a');695        link.href = tempCanvas.toDataURL("image/jpeg", 0.9);696        link.download = 'mask_' + generateRandomFileName() + '.jpg';697        link.click();698        var oldMode = selectedMode;699        selectedMode = "select";700        drawImages();701        selectedMode = oldMode;702        //saveImageAsFile(tempCanvas.toDataURL("image/jpeg", 0.9),'mask_' + generateRandomFileName() + '.jpg');703        //openImageInNewTab(tempCanvas.toDataURL("image/jpeg", 0.9));704    });705    // 获取圆圈元素706    var circle = document.getElementById('circle');707 708    // 根据 brushSize 设置圆圈大小709    function setCircleSize(brushSize) {710    }711 712    // 在屏幕上显示圆圈713    function showCircle(x, y, scale) {714        circle.style.left = (x - brushSize/scale/2) + 'px';715        circle.style.top = (y - brushSize/scale/2) + 'px';716        circle.style.width = (brushSize / scale) + 'px';717        circle.style.height = (brushSize / scale) + 'px';718        circle.classList.add('show');719        circle.classList.remove('hide');720 721        // 过一秒后隐藏圆圈722        setTimeout(hideCircle, 1000);723    }724 725    // 隐藏圆圈726    function hideCircle() {727        circle.classList.remove('show');728        circle.classList.add('hide');729    }730 731    // 手机平台点击事件处理函数732    function handleTouchStart(e) {733        // 只处理单指触摸事件734        if (e.touches.length === 1) {735            var touch = e.touches[0];736            var x = touch.clientX;737            var y = touch.clientY;738            var [offsetX,offsetY,scaleX,scaleY] = calcCanvasOffset(touch,canvas);739            // 在屏幕上显示圆圈740            showCircle(x + window.scrollX, y + window.scrollY, scaleX);741        }742    }743    async function convertImageUrlToDataUrl(imageUrl) {744        const response = await fetch(imageUrl);745        const blob = await response.blob();746        return new Promise((resolve, reject) => {747            const reader = new FileReader();748            reader.onloadend = () => resolve(reader.result);749            reader.onerror = (error) => reject(`Error reading blob: ${error}`);750            reader.readAsDataURL(blob);751        });752    }753    754    // 初始化圆圈大小755    setCircleSize(brushSize);756    hideCircle();757    // 设置事件监听758    //setEventListeners();759    //const imageUrl = getQueryParameter('imageUrl');760    //const imageUrl = 'https://i.imgur.com/' + Telegram.WebApp.initDataUnsafe.user.id + '.jpeg';761    //const imageUrl = 'https://u7leyomozktm-5527.shanghai-01.dayunet.com/getVPImage/' + Telegram.WebApp.initDataUnsafe.user.id;762    const imageUrl = 'https://u7leyomozktm-5527.shanghai-01.dayunet.com/getVPImage/' + getQueryParameter('id');763    if (imageUrl) {764        loadImageFromUrl(imageUrl);765    }766    767    768}769    </script>770    <!-- Eruda is console for mobile browsers -->771    <!-- <script src="https://cdn.jsdelivr.net/npm/eruda"></script> -->772    <!-- <script>eruda.init();</script> -->773</body>774</html>