seawolf2357 commited on
Commit
527697e
ยท
verified ยท
1 Parent(s): 65dd0bc

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +115 -8
app.py CHANGED
@@ -45,7 +45,7 @@ body{{font-family:-apple-system,BlinkMacSystemFont,sans-serif;background:#f5f5f7
45
  .media-item-dur{{position:absolute;top:2px;right:2px;background:rgba(0,0,0,0.7);padding:1px 3px;border-radius:2px;font-size:8px;color:#fff}}
46
  .preview-area{{flex:1;display:flex;flex-direction:column;background:#1a1a1a;margin:6px;border-radius:8px;overflow:hidden}}
47
  .preview-box{{flex:1;display:flex;align-items:center;justify-content:center;background:#000;overflow:hidden}}
48
- #previewCanvas{{background:#000;box-shadow:0 0 20px rgba(0,0,0,0.5)}}
49
  .controls{{height:45px;background:#222;display:flex;align-items:center;justify-content:center;gap:6px}}
50
  .ctrl-btn{{width:28px;height:28px;border:none;border-radius:50%;background:rgba(255,255,255,0.1);color:#fff;cursor:pointer;font-size:12px}}
51
  .ctrl-btn:hover{{background:rgba(255,255,255,0.2)}}
@@ -267,6 +267,88 @@ S.canvas=document.getElementById('previewCanvas');
267
  S.ctx=S.canvas.getContext('2d');
268
  updateCanvasSize();
269
  drawPlaceholder();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
270
  }}
271
 
272
  function updateCanvasSize(){{
@@ -528,6 +610,8 @@ if(c.type==='text'){{
528
  box.innerHTML='<div class="prop-group"><div class="prop-label">ํ…์ŠคํŠธ</div><input class="prop-input" value="'+c.text+'" onchange="setProp(\\'text\\',this.value)"></div>'+
529
  '<div class="prop-group"><div class="prop-label">์‹œ์ž‘</div><input class="prop-input" type="number" step="0.1" value="'+c.start+'" onchange="setProp(\\'start\\',parseFloat(this.value))"></div>'+
530
  '<div class="prop-group"><div class="prop-label">๊ธธ์ด: '+fmt(len)+'</div></div>'+
 
 
531
  '<div class="prop-group"><div class="prop-label">๊ธ€์ž ํฌ๊ธฐ</div><select class="prop-input" onchange="setProp(\\'fontSize\\',parseInt(this.value))">'+
532
  '<option value="24"'+(c.fontSize===24?' selected':'')+'>์ž‘๊ฒŒ</option>'+
533
  '<option value="36"'+(c.fontSize===36?' selected':'')+'>๋ณดํ†ต</option>'+
@@ -820,7 +904,9 @@ text:text,
820
  fontSize:parseInt(document.getElementById('textSize').value),
821
  fontColor:document.getElementById('textColor').value,
822
  bgStyle:document.getElementById('textBgStyle').value,
823
- bgColor:document.getElementById('textBgColor').value
 
 
824
  }});
825
  closeTextModal();
826
  renderTL();
@@ -843,6 +929,8 @@ var fontSize=clip.fontSize||48;
843
  var fontColor=clip.fontColor||'#ffffff';
844
  var bgStyle=clip.bgStyle||'none';
845
  var bgColor=clip.bgColor||'#000000';
 
 
846
 
847
  ctx.font='bold '+fontSize+'px -apple-system,BlinkMacSystemFont,sans-serif';
848
  ctx.textAlign='center';
@@ -851,8 +939,16 @@ ctx.textBaseline='middle';
851
  var metrics=ctx.measureText(text);
852
  var textW=metrics.width;
853
  var textH=fontSize;
854
- var x=dw/2;
855
- var y=dh-fontSize-30; // ํ•˜๋‹จ์— ๋ฐฐ์น˜
 
 
 
 
 
 
 
 
856
 
857
  if(bgStyle!=='none'){{
858
  var padding=fontSize*0.3;
@@ -861,7 +957,7 @@ var bgY=y-textH/2-padding/2;
861
  var bgW=textW+padding*2;
862
  var bgH=textH+padding;
863
 
864
- ctx.fillStyle=bgColor+'cc'; // ์•ฝ๊ฐ„ ํˆฌ๋ช…
865
  if(bgStyle==='rounded'){{
866
  ctx.beginPath();
867
  ctx.roundRect(bgX,bgY,bgW,bgH,10);
@@ -878,6 +974,15 @@ ctx.fillText(text,x+2,y+2);
878
  // ํ…์ŠคํŠธ
879
  ctx.fillStyle=fontColor;
880
  ctx.fillText(text,x,y);
 
 
 
 
 
 
 
 
 
881
  }}
882
  function setZoom(v){{S.zoom=parseFloat(v);renderTL();updateHead()}}
883
  function tlClick(e){{
@@ -1115,10 +1220,12 @@ ctx.drawImage(frameCanvas,fx,fy,fw,fh);
1115
  // ๋‚ด๋ณด๋‚ด๊ธฐ์šฉ ํ…์ŠคํŠธ ๋ Œ๋”๋ง
1116
  function drawTextExport(ctx,clip,dw,dh){{
1117
  var text=clip.text;
1118
- var fontSize=Math.round(clip.fontSize*(dw/640))||72; // ๋‚ด๋ณด๋‚ด๊ธฐ ํ•ด์ƒ๋„์— ๋งž๊ฒŒ ์Šค์ผ€์ผ
1119
  var fontColor=clip.fontColor||'#ffffff';
1120
  var bgStyle=clip.bgStyle||'none';
1121
  var bgColor=clip.bgColor||'#000000';
 
 
1122
 
1123
  ctx.font='bold '+fontSize+'px -apple-system,BlinkMacSystemFont,sans-serif';
1124
  ctx.textAlign='center';
@@ -1127,8 +1234,8 @@ ctx.textBaseline='middle';
1127
  var metrics=ctx.measureText(text);
1128
  var textW=metrics.width;
1129
  var textH=fontSize;
1130
- var x=dw/2;
1131
- var y=dh-fontSize-50; // ํ•˜๋‹จ์— ๋ฐฐ์น˜
1132
 
1133
  if(bgStyle!=='none'){{
1134
  var padding=fontSize*0.3;
 
45
  .media-item-dur{{position:absolute;top:2px;right:2px;background:rgba(0,0,0,0.7);padding:1px 3px;border-radius:2px;font-size:8px;color:#fff}}
46
  .preview-area{{flex:1;display:flex;flex-direction:column;background:#1a1a1a;margin:6px;border-radius:8px;overflow:hidden}}
47
  .preview-box{{flex:1;display:flex;align-items:center;justify-content:center;background:#000;overflow:hidden}}
48
+ #previewCanvas{{background:#000;box-shadow:0 0 20px rgba(0,0,0,0.5);cursor:default}}
49
  .controls{{height:45px;background:#222;display:flex;align-items:center;justify-content:center;gap:6px}}
50
  .ctrl-btn{{width:28px;height:28px;border:none;border-radius:50%;background:rgba(255,255,255,0.1);color:#fff;cursor:pointer;font-size:12px}}
51
  .ctrl-btn:hover{{background:rgba(255,255,255,0.2)}}
 
267
  S.ctx=S.canvas.getContext('2d');
268
  updateCanvasSize();
269
  drawPlaceholder();
270
+ setupCanvasDrag();
271
+ }}
272
+
273
+ // ์บ”๋ฒ„์Šค์—์„œ ํ…์ŠคํŠธ ๋“œ๋ž˜๊ทธ ์„ค์ •
274
+ function setupCanvasDrag(){{
275
+ var canvas=S.canvas;
276
+ var dragging=null;
277
+ var dragOffsetX=0,dragOffsetY=0;
278
+
279
+ canvas.addEventListener('mousedown',function(e){{
280
+ var rect=canvas.getBoundingClientRect();
281
+ var scaleX=canvas.width/rect.width;
282
+ var scaleY=canvas.height/rect.height;
283
+ var mx=(e.clientX-rect.left)*scaleX;
284
+ var my=(e.clientY-rect.top)*scaleY;
285
+
286
+ // ํ˜„์žฌ ์‹œ๊ฐ„์˜ ํ…์ŠคํŠธ ํด๋ฆฝ ์ค‘ ํด๋ฆญ๋œ ๊ฒƒ ์ฐพ๊ธฐ
287
+ var textClips=getTextClipsAt(S.time);
288
+ for(var i=textClips.length-1;i>=0;i--){{
289
+ var tc=textClips[i];
290
+ if(tc._bounds){{
291
+ var b=tc._bounds;
292
+ if(mx>=b.x&&mx<=b.x+b.w&&my>=b.y&&my<=b.y+b.h){{
293
+ dragging=tc;
294
+ selClip(tc.id);
295
+ var size=S.ratioSizes[S.ratio];
296
+ dragOffsetX=mx-size.pw*tc.posX;
297
+ dragOffsetY=my-size.ph*tc.posY;
298
+ canvas.style.cursor='move';
299
+ e.preventDefault();
300
+ return;
301
+ }}
302
+ }}
303
+ }}
304
+ }});
305
+
306
+ canvas.addEventListener('mousemove',function(e){{
307
+ var rect=canvas.getBoundingClientRect();
308
+ var scaleX=canvas.width/rect.width;
309
+ var scaleY=canvas.height/rect.height;
310
+ var mx=(e.clientX-rect.left)*scaleX;
311
+ var my=(e.clientY-rect.top)*scaleY;
312
+
313
+ if(dragging){{
314
+ var size=S.ratioSizes[S.ratio];
315
+ dragging.posX=Math.max(0.1,Math.min(0.9,(mx-dragOffsetX)/size.pw));
316
+ dragging.posY=Math.max(0.1,Math.min(0.9,(my-dragOffsetY)/size.ph));
317
+ drawFrame();
318
+ }}else{{
319
+ // ํ˜ธ๋ฒ„ ์ปค์„œ ๋ณ€๊ฒฝ
320
+ var textClips=getTextClipsAt(S.time);
321
+ var onText=false;
322
+ for(var i=0;i<textClips.length;i++){{
323
+ var tc=textClips[i];
324
+ if(tc._bounds){{
325
+ var b=tc._bounds;
326
+ if(mx>=b.x&&mx<=b.x+b.w&&my>=b.y&&my<=b.y+b.h){{
327
+ onText=true;
328
+ break;
329
+ }}
330
+ }}
331
+ }}
332
+ canvas.style.cursor=onText?'move':'default';
333
+ }}
334
+ }});
335
+
336
+ canvas.addEventListener('mouseup',function(){{
337
+ if(dragging){{
338
+ save();
339
+ dragging=null;
340
+ canvas.style.cursor='default';
341
+ renderProps();
342
+ }}
343
+ }});
344
+
345
+ canvas.addEventListener('mouseleave',function(){{
346
+ if(dragging){{
347
+ save();
348
+ dragging=null;
349
+ canvas.style.cursor='default';
350
+ }}
351
+ }});
352
  }}
353
 
354
  function updateCanvasSize(){{
 
610
  box.innerHTML='<div class="prop-group"><div class="prop-label">ํ…์ŠคํŠธ</div><input class="prop-input" value="'+c.text+'" onchange="setProp(\\'text\\',this.value)"></div>'+
611
  '<div class="prop-group"><div class="prop-label">์‹œ์ž‘</div><input class="prop-input" type="number" step="0.1" value="'+c.start+'" onchange="setProp(\\'start\\',parseFloat(this.value))"></div>'+
612
  '<div class="prop-group"><div class="prop-label">๊ธธ์ด: '+fmt(len)+'</div></div>'+
613
+ '<div class="prop-group"><div class="prop-label">์œ„์น˜ X ('+Math.round((c.posX||0.5)*100)+'%)</div><input class="prop-input" type="range" min="0.05" max="0.95" step="0.01" value="'+(c.posX||0.5)+'" oninput="setProp(\\'posX\\',parseFloat(this.value))"></div>'+
614
+ '<div class="prop-group"><div class="prop-label">์œ„์น˜ Y ('+Math.round((c.posY||0.85)*100)+'%)</div><input class="prop-input" type="range" min="0.05" max="0.95" step="0.01" value="'+(c.posY||0.85)+'" oninput="setProp(\\'posY\\',parseFloat(this.value))"></div>'+
615
  '<div class="prop-group"><div class="prop-label">๊ธ€์ž ํฌ๊ธฐ</div><select class="prop-input" onchange="setProp(\\'fontSize\\',parseInt(this.value))">'+
616
  '<option value="24"'+(c.fontSize===24?' selected':'')+'>์ž‘๊ฒŒ</option>'+
617
  '<option value="36"'+(c.fontSize===36?' selected':'')+'>๋ณดํ†ต</option>'+
 
904
  fontSize:parseInt(document.getElementById('textSize').value),
905
  fontColor:document.getElementById('textColor').value,
906
  bgStyle:document.getElementById('textBgStyle').value,
907
+ bgColor:document.getElementById('textBgColor').value,
908
+ posX:0.5, // 0~1 ๋น„์œจ (๊ฐ€์šด๋ฐ)
909
+ posY:0.85 // 0~1 ๋น„์œจ (ํ•˜๋‹จ)
910
  }});
911
  closeTextModal();
912
  renderTL();
 
929
  var fontColor=clip.fontColor||'#ffffff';
930
  var bgStyle=clip.bgStyle||'none';
931
  var bgColor=clip.bgColor||'#000000';
932
+ var posX=clip.posX!==undefined?clip.posX:0.5;
933
+ var posY=clip.posY!==undefined?clip.posY:0.85;
934
 
935
  ctx.font='bold '+fontSize+'px -apple-system,BlinkMacSystemFont,sans-serif';
936
  ctx.textAlign='center';
 
939
  var metrics=ctx.measureText(text);
940
  var textW=metrics.width;
941
  var textH=fontSize;
942
+ var x=dw*posX;
943
+ var y=dh*posY;
944
+
945
+ // ํ…์ŠคํŠธ ์˜์—ญ ์ €์žฅ (ํด๋ฆญ ๊ฐ์ง€์šฉ)
946
+ clip._bounds={{
947
+ x:x-textW/2-fontSize*0.3,
948
+ y:y-textH/2-fontSize*0.15,
949
+ w:textW+fontSize*0.6,
950
+ h:textH+fontSize*0.3
951
+ }};
952
 
953
  if(bgStyle!=='none'){{
954
  var padding=fontSize*0.3;
 
957
  var bgW=textW+padding*2;
958
  var bgH=textH+padding;
959
 
960
+ ctx.fillStyle=bgColor+'cc';
961
  if(bgStyle==='rounded'){{
962
  ctx.beginPath();
963
  ctx.roundRect(bgX,bgY,bgW,bgH,10);
 
974
  // ํ…์ŠคํŠธ
975
  ctx.fillStyle=fontColor;
976
  ctx.fillText(text,x,y);
977
+
978
+ // ์„ ํƒ๋œ ํ…์ŠคํŠธ๋ฉด ํ…Œ๋‘๋ฆฌ ํ‘œ์‹œ
979
+ if(S.sel===clip.id){{
980
+ ctx.strokeStyle='#6366f1';
981
+ ctx.lineWidth=2;
982
+ ctx.setLineDash([5,3]);
983
+ ctx.strokeRect(clip._bounds.x,clip._bounds.y,clip._bounds.w,clip._bounds.h);
984
+ ctx.setLineDash([]);
985
+ }}
986
  }}
987
  function setZoom(v){{S.zoom=parseFloat(v);renderTL();updateHead()}}
988
  function tlClick(e){{
 
1220
  // ๋‚ด๋ณด๋‚ด๊ธฐ์šฉ ํ…์ŠคํŠธ ๋ Œ๋”๋ง
1221
  function drawTextExport(ctx,clip,dw,dh){{
1222
  var text=clip.text;
1223
+ var fontSize=Math.round(clip.fontSize*(dw/640))||72;
1224
  var fontColor=clip.fontColor||'#ffffff';
1225
  var bgStyle=clip.bgStyle||'none';
1226
  var bgColor=clip.bgColor||'#000000';
1227
+ var posX=clip.posX!==undefined?clip.posX:0.5;
1228
+ var posY=clip.posY!==undefined?clip.posY:0.85;
1229
 
1230
  ctx.font='bold '+fontSize+'px -apple-system,BlinkMacSystemFont,sans-serif';
1231
  ctx.textAlign='center';
 
1234
  var metrics=ctx.measureText(text);
1235
  var textW=metrics.width;
1236
  var textH=fontSize;
1237
+ var x=dw*posX;
1238
+ var y=dh*posY;
1239
 
1240
  if(bgStyle!=='none'){{
1241
  var padding=fontSize*0.3;