nicehero commited on
Commit
d815c4a
·
1 Parent(s): 819f80a

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +516 -17
index.html CHANGED
@@ -1,19 +1,518 @@
1
  <!DOCTYPE html>
2
  <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
19
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  <!DOCTYPE html>
2
  <html>
3
+ <head>
4
+ <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
5
+ <title>蒙版王</title>
6
+ <style>
7
+ /* 适用于手机的样式 */
8
+ @media (max-width: 767px) {
9
+ body {
10
+ width: 350;
11
+ margin: 0 auto; /* 水平居中 */
12
+ }
13
+ #canvas {
14
+ border: 1px solid #000;
15
+ width: 100%;
16
+ height: auto;
17
+ }
18
+ html, body {
19
+ overflow-x: hidden;
20
+ }
21
+ #uploadButton{
22
+ width: 80%;
23
+ }
24
+ #save{
25
+ width: 20%;
26
+ }
27
+ .myDiv {
28
+ width: 98%;
29
+ display: flex;
30
+ flex-direction: row;
31
+ justify-content: flex-start;
32
+ margin: 0px 1%;
33
+ }
34
+ .overlay {
35
+ left: 20px;
36
+ }
37
+ }
38
+ /* 适用于电脑的样式 */
39
+ @media (min-width: 768px) {
40
+ #canvas {
41
+ border: 1px solid #000;
42
+ width: auto;
43
+ height: auto;
44
+ }
45
+ .myDiv {
46
+ display: flex;
47
+ flex-direction: row;
48
+ justify-content: center;
49
+ margin: 0 100px;
50
+ width: 512px;
51
+ }
52
+ .overlay {
53
+ left: 100px;
54
+ }
55
+ }
56
+ #circle {
57
+ position: absolute;
58
+ width: 10px;
59
+ height: 10px;
60
+ border-radius: 50%;
61
+ border: 2px solid red;
62
+ background-color: transparent;
63
+ transition: opacity 1s;
64
+ pointer-events: none;
65
+ }
66
+ .show {
67
+ opacity: 1;
68
+ }
69
+ .hide {
70
+ opacity: 0;
71
+ }
72
+ .overlay {
73
+ position: absolute;
74
+ top: 82px;
75
+ z-index: 10;
76
+ /* 设置悬浮控件的样式和尺寸 */
77
+ /* 可以使用 z-index 属性来控制层叠顺序 */
78
+ }
79
+ </style>
80
+ </head>
81
+ <body>
82
+ <div class="myDiv">
83
+ <button id="uploadButton" style="box-sizing: border-box; padding: 10px; font-size: 16px; height: 50px; line-height: 30px; overflow: hidden; position: relative;">
84
+ 选择图片
85
+ <input type="file" id="upload" accept="image/*" style="position: absolute; top: 0; left: 0; width: 98%; height: 100%; opacity: 0; cursor: pointer;">
86
+ </button>
87
+ <button id="save" style="height: 50px;">保存蒙版</button>
88
+ </div>
89
+ <div class="myDiv">
90
+ <input type="range" id="brushSizeSlider" style="width: 100%" value="40" min="1" max="150" step="1" >
91
+ </div>
92
+ <br>
93
+ <br>
94
+ <div class="myDiv">
95
+ <canvas id="canvas"></canvas>
96
+ </div>
97
+ <div class="overlay" style="display: flex; flex-direction: row; align-items: flex-start;">
98
+ <label style="margin-bottom: 10px;">
99
+ <input type="radio" name="editMode" value="draw" checked> 画笔模式
100
+ </label>
101
+ <label style="margin-bottom: 10px;">
102
+ <input type="radio" name="editMode" value="erase"> 擦除模式
103
+ </label>
104
+ <label>
105
+ <input type="radio" name="editMode" value="select"> 不编辑
106
+ </label>
107
+ </div>
108
+ <div id="circle" style="width: 20px; height: 20px; border-radius: 50%; border: 2px solid red;"></div>
109
+ <script>
110
+ window.onload = function() {
111
+ var canvas = document.getElementById('canvas');
112
+ var context = canvas.getContext('2d');
113
+ var image = new Image();
114
+ var imageMask = new Image();
115
+ var maskData = null;
116
+ var isDrawing = false;
117
+ var brushSize = 40;
118
+ var intervalHandel = null;
119
+ var brushSizeSlider = document.getElementById('brushSizeSlider');
120
+ var editModeRadios = document.getElementsByName('editMode');
121
+ var selectedMode = "draw";
122
+ var isRotate = false;
123
+ function isMobile() {
124
+ return (/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent));
125
+ }
126
+ for (var i = 0; i < editModeRadios.length; i++) {
127
+ editModeRadios[i].addEventListener('change', function() {
128
+ // 获取选中的编辑模式值
129
+ selectedMode = this.value;
130
+ });
131
+ }
132
+ brushSizeSlider.addEventListener('input', function() {
133
+ brushSize = parseInt(this.value);
134
+ setCircleSize(brushSize);
135
+ if (isMobile()){
136
+ var canvasRect = canvas.getBoundingClientRect();
137
+ var scaleX = canvas.width / canvasRect.width;
138
+ showCircle(175 + window.scrollX, 200 + window.scrollY, scaleX);
139
+ }
140
+ });
141
+ function resizeImage(img,s,resizedImage) {
142
+ var maxWidth = s; // 最大宽度
143
+ var maxHeight = s; // 最大高度
144
+ var width = img.width;
145
+ var height = img.height;
146
+ if (width/height < 4/3 && width <= maxWidth && height <= maxHeight) {
147
+ return false;
148
+ }
149
+ if (!isMobile() && width <= maxWidth && height <= maxHeight) {
150
+ return false;
151
+ }
152
+ if (width > maxWidth || height > maxHeight || width/height >= 4/3) {
153
+ var ratio = Math.max(maxWidth / width, maxHeight / height);
154
+ if (width <= maxWidth && height <= maxHeight){
155
+ ratio = 1;
156
+ }
157
+ width = Math.floor(width * ratio);
158
+ height = Math.floor(height * ratio);
159
+ var tempCanvas = document.createElement('canvas');
160
+ tempCanvas.width = width;
161
+ tempCanvas.height = height;
162
+ var ctx = tempCanvas.getContext('2d');
163
+ isRotate = false;
164
+ if (width/height >= 4/3 && isMobile()){
165
+ tempCanvas.height = width;
166
+ tempCanvas.width = height;
167
+ ctx.clearRect(0, 0, tempCanvas.width, tempCanvas.height);
168
+ ctx.save();
169
+ ctx.translate(tempCanvas.width / 2, tempCanvas.height / 2);
170
+ ctx.rotate(Math.PI / 2);
171
+ ctx.drawImage(img, -img.width / 2, -img.height / 2);
172
+ ctx.restore();
173
+ isRotate = true;
174
+ }
175
+ else {
176
+ ctx.drawImage(img, 0, 0, width, height);
177
+ }
178
+ resizedImage.src = tempCanvas.toDataURL();
179
+ return true;
180
+ }
181
+ return false;
182
+ }
183
+
184
+ function drawImages() {
185
+ context.clearRect(0, 0, canvas.width, canvas.height);
186
+ context.putImageData(maskData,0,0);
187
+ context.globalAlpha = 0.75; // 设置透明度为0.5
188
+ context.drawImage(image, 0, 0);
189
+ //context.drawImage(imageMask, 0, 0);
190
+ context.globalAlpha = 1; // 恢复透明度为1
191
+ }
192
+ function drawImagesInterval(t) {
193
+ if (intervalHandel != null){
194
+ drawImagesTimeOut(100);
195
+ window.clearInterval(intervalHandel);
196
+ intervalHandel = null;
197
+ }
198
+ intervalHandel = window.setInterval(function() {drawImages();}, t);
199
+ }
200
+ window.addEventListener('scroll', function(event) {
201
+ var scrollTop = window.pageYOffset || document.documentElement.scrollTop;
202
+ var overlay = document.querySelector(".overlay");
203
+ overlay.style.top = (scrollTop + 82) + "px";
204
+ });
205
+ function stopDrawImagesInterval() {
206
+ if (intervalHandel != null){
207
+ drawImagesTimeOut(100);
208
+ window.clearInterval(intervalHandel);
209
+ intervalHandel = null;
210
+ }
211
+ }
212
+ function drawImagesTimeOut(t) {
213
+ window.setTimeout(function() {drawImages();}, t);
214
+ }
215
+ function getImageDataB(img) {
216
+ context.clearRect(0, 0, canvas.width, canvas.height);
217
+ var width = image.width;
218
+ var height = image.height;
219
+ canvas.width = width;
220
+ canvas.height = height;
221
+ context.drawImage(img, 0, 0);
222
+ var imageData = context.getImageData(0, 0, width, height);
223
+ return imageData;
224
+ }
225
+ function getImageData(img) {
226
+ var tempCanvas = document.createElement('canvas');
227
+ tempCanvas.width = canvas.width;
228
+ tempCanvas.height = canvas.height;
229
+ var tempContext = tempCanvas.getContext('2d');
230
+ var width = image.width;
231
+ var height = image.height;
232
+ tempCanvas.width = width;
233
+ tempCanvas.height = height;
234
+ tempContext.drawImage(img, 0, 0);
235
+ var imageData = tempContext.getImageData(0, 0, width, height);
236
+ return imageData;
237
+ }
238
+ function createMaskImageData(width, height) {
239
+ // 创建一个新的ImageData对象
240
+ var imageData = new ImageData(width, height);
241
+ // 获取像素数据
242
+ var data = imageData.data;
243
+ // 将每个像素设置为黑色
244
+ for (var i = 0; i < data.length; i += 4) {
245
+ data[i] = 0; // 设置红色通道
246
+ data[i + 1] = 0; // 设置绿色通道
247
+ data[i + 2] = 0; // 设置蓝色通道
248
+ data[i + 3] = 255; // 设置透明度通道(不透明)
249
+ }
250
+ return imageData;
251
+ }
252
+ function getImageDataUrl(imageData) {
253
+ var tempCanvas = document.createElement('canvas');
254
+ tempCanvas.width = canvas.width;
255
+ tempCanvas.height = canvas.height;
256
+ var tempContext = tempCanvas.getContext('2d');
257
+ tempContext.putImageData(imageData, 0, 0);
258
+ return tempCanvas.toDataURL();
259
+ }
260
+ function handleFile(file) {
261
+ var reader = new FileReader();
262
+ reader.onload = function(event) {
263
+ image.onload = function() {
264
+ var resizedImage = new Image();
265
+ resizedImage.onload = _ok;
266
+ function _ok(event){
267
+ image = resizedImage;
268
+ canvas.width = resizedImage.width;
269
+ canvas.height = resizedImage.height;
270
+ maskData = createMaskImageData(image.width,image.height);
271
+ imageMask.src = getImageDataUrl(maskData);
272
+ drawImagesTimeOut(100);
273
+ }
274
+ if (!resizeImage(image,512,resizedImage)) {
275
+ canvas.width = image.width;
276
+ canvas.height = image.height;
277
+ maskData = createMaskImageData(image.width,image.height);
278
+ imageMask.src = getImageDataUrl(maskData);
279
+ drawImagesTimeOut(100);
280
+ }
281
+ }
282
+ image.src = event.target.result;
283
+ }
284
+ reader.readAsDataURL(file);
285
+ }
286
+ // 上传图片
287
+ document.getElementById("upload").addEventListener('change', function(e) {
288
+ var file = e.target.files[0];
289
+ handleFile(file);
290
+ });
291
+
292
+ // 添加拖拽文件事件监听
293
+ document.addEventListener('dragover', function(e) {
294
+ e.preventDefault();
295
+ });
296
+ document.addEventListener('drop', function(e) {
297
+ e.preventDefault();
298
+ // 获取拖拽事件中的文件对象
299
+ var file = e.dataTransfer.files[0];
300
+ // 执行与文件上传按钮相同的操作
301
+ handleFile(file);
302
+ });
303
+
304
+ function inRect(x,y,rect){
305
+ return (
306
+ x >= rect.left &&
307
+ x <= rect.right &&
308
+ y >= rect.top &&
309
+ y <= rect.bottom
310
+ );
311
+ }
312
+ function calcCanvasOffset(e,canvas) {
313
+ var canvasRect = canvas.getBoundingClientRect();
314
+ var scaleX = canvas.width / canvasRect.width;
315
+ var scaleY = canvas.height / canvasRect.height;
316
+ var offsetX = (e.clientX - canvasRect.left) * scaleX;
317
+ var offsetY = (e.clientY - canvasRect.top) * scaleY;
318
+ return [offsetX,offsetY,scaleX,scaleY];
319
+ }
320
+ // 开始绘制
321
+ function onTouchDown(e) {
322
+ if (selectedMode == "select") {
323
+ return;
324
+ }
325
+ var canvasRect = canvas.getBoundingClientRect();
326
+ var [offsetX,offsetY,scaleX,scaleY] = calcCanvasOffset(e,canvas);
327
+ //console.log([offsetX,offsetY,scaleX,scaleY]);
328
+ if (!inRect(e.clientX,e.clientY,canvasRect)){
329
+ return;
330
+ }
331
+ if (draw(offsetX, offsetY)) {
332
+ isDrawing = true;
333
+ drawImagesInterval(100);
334
+ }
335
+ }
336
+ document.addEventListener('touchstart', function(event) {
337
+ var touch = event.touches[0];
338
+ onTouchDown(touch);
339
+ });
340
+ document.addEventListener('mousedown',function(event){
341
+ onTouchDown(event);
342
+ } );
343
+ // 结束绘制
344
+ document.addEventListener('mouseup', function() {
345
+ isDrawing = false;
346
+ stopDrawImagesInterval();
347
+ });
348
+ // 绘制中
349
+ function onMove(e) {
350
+ var [offsetX,offsetY,scaleX,scaleY] = calcCanvasOffset(e,canvas);
351
+ if (/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)) {
352
+ showCircle(e.clientX + window.scrollX, e.clientY + window.scrollY, scaleX);
353
+ } else {
354
+ showCircle(e.clientX + window.scrollX, e.clientY + window.scrollY, scaleX);
355
+ }
356
+ var canvasRect = canvas.getBoundingClientRect();
357
+ if (isDrawing) {
358
+ //console.log('onMove1');
359
+ if (!inRect(e.clientX,e.clientY,canvasRect)){
360
+ return;
361
+ }
362
+ draw(offsetX, offsetY);
363
+ }
364
+ }
365
+ canvas.addEventListener('touchmove', function(event) {
366
+ if (selectedMode == "select") {
367
+ return;
368
+ }
369
+ event.preventDefault();
370
+ var touch = event.touches[0];
371
+ onMove(touch);
372
+ }, { passive: false });
373
+ if (!isMobile()) {
374
+ document.addEventListener('mousemove', function(event){
375
+ onMove(event);
376
+ });
377
+ }
378
+
379
+
380
+ // 绘制函数
381
+ function draw(x, y) {
382
+ if (selectedMode == "selected") {
383
+ return false;
384
+ }
385
+ if (maskData == null) {
386
+ return false;
387
+ }
388
+ var data = maskData.data;
389
+ var brushRadius = brushSize / 2;
390
+
391
+ for (var i = -brushRadius; i <= brushRadius; i++) {
392
+ for (var j = -brushRadius; j <= brushRadius; j++) {
393
+ var pixelX = Math.round(x + i);
394
+ var pixelY = Math.round(y + j);
395
+
396
+ if (pixelX < 0 || pixelX >= canvas.width || pixelY < 0 || pixelY >= canvas.height) {
397
+ continue;
398
+ }
399
+ var distance = Math.sqrt((pixelX - x) * (pixelX - x) + (pixelY - y) * (pixelY - y));
400
+ if (distance > brushRadius) {
401
+ continue;
402
+ }
403
+ var index = (pixelY * canvas.width + pixelX) * 4;
404
+ if (selectedMode == "draw"){
405
+ data[index] = 255; // 设置红色通道为最大值,即白色
406
+ data[index + 1] = 255; // 设置绿色通道为最大值,即白色
407
+ data[index + 2] = 255;
408
+ }
409
+ else {
410
+ data[index] = 0; // 设置红色通道为最大值,即白色
411
+ data[index + 1] = 0; // 设置绿色通道为最大值,即白色
412
+ data[index + 2] = 0;
413
+ }
414
+
415
+ //data[index + 3] = 128;
416
+ }
417
+ }
418
+ //imageMask.src = getImageDataUrl(maskData);
419
+ return true;
420
+ }
421
+ function generateRandomFileName() {
422
+ var characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
423
+ var length = 10; // 文件名长度
424
+ var fileName = '';
425
+ for (var i = 0; i < length; i++) {
426
+ var randomIndex = Math.floor(Math.random() * characters.length);
427
+ fileName += characters.charAt(randomIndex);
428
+ }
429
+ return fileName;
430
+ }
431
+ function rotateImageData(imageData) {
432
+ const { width, height } = imageData;
433
+ const rotatedData = new Uint8ClampedArray(width * height * 4);
434
+
435
+ for (let y = 0; y < height; y++) {
436
+ for (let x = 0; x < width; x++) {
437
+ const srcIndex = (x + y * width) * 4;
438
+ const destIndex = ((width - x - 1) * height + y) * 4;
439
+
440
+ rotatedData[destIndex] = imageData.data[srcIndex];
441
+ rotatedData[destIndex + 1] = imageData.data[srcIndex + 1];
442
+ rotatedData[destIndex + 2] = imageData.data[srcIndex + 2];
443
+ rotatedData[destIndex + 3] = imageData.data[srcIndex + 3];
444
+ }
445
+ }
446
+
447
+ return new ImageData(rotatedData, height, width);
448
+ }
449
+ // 保存蒙版
450
+ document.getElementById('save').addEventListener('click', function() {
451
+ var data = maskData.data;
452
+ var tempCanvas = document.createElement('canvas');
453
+ var ctx = tempCanvas.getContext('2d');
454
+ if (isRotate == true){
455
+ var rData = rotateImageData(maskData);
456
+ tempCanvas.height = maskData.width;
457
+ tempCanvas.width = maskData.height;
458
+ ctx.putImageData(rData, 0, 0);
459
+ }
460
+ else {
461
+ tempCanvas.width = canvas.width;
462
+ tempCanvas.height = canvas.height;
463
+ ctx.putImageData(maskData, 0, 0);
464
+ }
465
+ var link = document.createElement('a');
466
+ link.href = tempCanvas.toDataURL("image/jpeg", 0.9);
467
+ link.download = 'mask_' + generateRandomFileName() + '.jpg';
468
+ link.click();
469
+ });
470
+ // 获取圆圈元素
471
+ var circle = document.getElementById('circle');
472
+
473
+ // 根据 brushSize 设置圆圈大小
474
+ function setCircleSize(brushSize) {
475
+ }
476
+
477
+ // 在屏幕上显示圆圈
478
+ function showCircle(x, y, scale) {
479
+ circle.style.left = (x - brushSize/scale/2) + 'px';
480
+ circle.style.top = (y - brushSize/scale/2) + 'px';
481
+ circle.style.width = (brushSize / scale) + 'px';
482
+ circle.style.height = (brushSize / scale) + 'px';
483
+ circle.classList.add('show');
484
+ circle.classList.remove('hide');
485
+
486
+ // 过一秒后隐藏圆圈
487
+ setTimeout(hideCircle, 1000);
488
+ }
489
+
490
+ // 隐藏圆圈
491
+ function hideCircle() {
492
+ circle.classList.remove('show');
493
+ circle.classList.add('hide');
494
+ }
495
+
496
+ // 手机平台点击事件处理函数
497
+ function handleTouchStart(e) {
498
+ // 只处理单指触摸事件
499
+ if (e.touches.length === 1) {
500
+ var touch = e.touches[0];
501
+ var x = touch.clientX;
502
+ var y = touch.clientY;
503
+ var [offsetX,offsetY,scaleX,scaleY] = calcCanvasOffset(touch,canvas);
504
+ // 在屏幕上显示圆圈
505
+ showCircle(x + window.scrollX, y + window.scrollY, scaleX);
506
+ }
507
+ }
508
+
509
+
510
+ // 初始化圆圈大小
511
+ setCircleSize(brushSize);
512
+ hideCircle();
513
+ // 设置事件监听
514
+ //setEventListeners();
515
+ }
516
+ </script>
517
+ </body>
518
+ </html>