nicehero/ManualMask
1
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>