tien_nemo

css drag drop

1 +
2 +body {
3 + font-family: sans-serif; background: #f5f5f5;
4 +}
5 +
6 +#app {
7 + display: flex; gap: 20px; padding: 20px;
8 +}
9 +
10 +.left-panel {
11 + width: 500px; background: #fff; padding: 15px;
12 + border-radius: 8px; box-shadow: 0 0 5px rgba(0,0,0,0.1);
13 +}
14 +
15 +.form-group {
16 + margin-bottom: 15px;
17 +}
18 +
19 +.form-group label {
20 + font-weight: bold; display: block; margin-bottom: 5px;
21 +}
22 +
23 +.form-group input {
24 + width: 100%;
25 + padding: 6px;
26 + border: 1px solid #ccc;
27 + border-radius: 4px;
28 +}
29 +
30 +.right-panel {
31 + flex: 1;
32 + position: relative;
33 + background: #eee;
34 + border-radius: 8px;
35 + overflow: hidden;
36 + user-select: none;
37 +}
38 +
39 +.pdf-container {
40 + position: relative; display: inline-block;
41 +}
42 +
43 +.bbox {
44 + position: absolute;
45 + border: 2px solid #ff5252;
46 + /*background-color: rgba(255, 82, 82, 0.2);*/
47 + cursor: pointer;
48 +}
49 +
50 +.bbox.active {
51 + border-color: #199601 !important;
52 + background-color: rgba(25, 150, 1, 0.4) !important;
53 +}
54 +
55 +@keyframes focusPulse {
56 + 0% { transform: scale(1); }
57 + 50% { transform: scale(1.05); }
58 + 100% { transform: scale(1); }
59 +}
60 +
61 +select {
62 + position: absolute;
63 + z-index: 10;
64 + background: #fff;
65 + border: 1px solid #ccc;
66 +}
67 +
68 +.select-box {
69 + position: absolute;
70 + /*border: 2px dashed #2196F3;*/
71 + background-color: rgba(33, 150, 243, 0.2);
72 + pointer-events: none;
73 + z-index: 5;
74 +}
75 +
76 +.delete-btn {
77 + position: absolute;
78 + top: 50%;
79 + right: -40px;
80 + transform: translateY(-50%);
81 + color: #ff4d4d;
82 + border: none;
83 + border-radius: 50%;
84 + cursor: pointer;
85 + font-size: 20px;
86 + padding: 3px 6px;
87 + z-index: 20;
88 + background: white;
89 +}
90 +
91 +
92 +.edge {
93 + position: absolute;
94 + z-index: 25;
95 +
96 +}
97 +
98 +.edge.top, .edge.bottom {
99 + height: 8px;
100 + cursor: ns-resize;;
101 +}
102 +.edge.left, .edge.right {
103 + width: 8px;
104 + cursor: ew-resize;
105 +}
106 +
107 +.edge.top {
108 + top: -4px;
109 + left: 0;
110 + right: 0;
111 +}
112 +
113 +.edge.bottom {
114 + bottom: -4px;
115 + left: 0;
116 + right: 0;
117 +}
118 +
119 +.edge.left {
120 + top: 0;
121 + bottom: 0;
122 + left: -4px;
123 +}
124 +
125 +.edge.right {
126 + top: 0;
127 + bottom: 0;
128 + right: -4px;
129 +}
130 +
131 +.corner {
132 + position: absolute;
133 + width: 14px;
134 + height: 14px;
135 + background: transparent;
136 + border: 2px solid transparent; /* mặc định trong suốt, chỉ tô 2 cạnh */
137 + z-index: 30;
138 + opacity: .95;
139 + transition: border-width .08s ease, transform .08s ease, opacity .08s ease;
140 + pointer-events: auto; /* bắt sự kiện kéo resize */
141 +}
142 +
143 +
144 +/* Mỗi góc hiện 2 cạnh + bo tròn đúng góc */
145 +.corner.nw {
146 + top: -8px; left: -8px;
147 + /*border-left-color: var(--corner-color);*/
148 + /*border-top-color: var(--corner-color);*/
149 + border-top-left-radius: 6px;
150 + cursor: nwse-resize;
151 +}
152 +
153 +.corner.ne {
154 + top: -8px; right: -8px;
155 + /*border-right-color: var(--corner-color);*/
156 + /*border-top-color: var(--corner-color);*/
157 + border-top-right-radius: 6px;
158 + cursor: nesw-resize;
159 +}
160 +
161 +.corner.sw {
162 + bottom: -8px; left: -8px;
163 + /*border-left-color: var(--corner-color);*/
164 + /*border-bottom-color: var(--corner-color);*/
165 + border-bottom-left-radius: 6px;
166 + cursor: nesw-resize;
167 +}
168 +
169 +.corner.se {
170 + bottom: -8px; right: -8px;
171 + /*border-right-color: var(--corner-color);*/
172 + /*border-bottom-color: var(--corner-color);*/
173 + border-bottom-right-radius: 6px;
174 + cursor: nwse-resize;
175 +}
176 +
177 +/* Hiệu ứng khi hover – dày hơn, rõ hơn */
178 +.corner:hover {
179 + border-width: 3px;
180 + opacity: 1;
181 + transform: scale(1.02);
182 +}
1 -<html lang="en"><head> 1 +<html lang="en">
2 +<head>
2 <meta charset="UTF-8"> 3 <meta charset="UTF-8">
3 <title>OCR Mapping with Manual Select Tool</title> 4 <title>OCR Mapping with Manual Select Tool</title>
4 <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script> 5 <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
5 - <style> 6 + <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/all.min.css" rel="stylesheet">
6 - body { font-family: sans-serif; background: #f5f5f5; } 7 + <link rel="stylesheet" href="{{ asset('css/ocr.css') }}">
7 - #app { display: flex; gap: 20px; padding: 20px; }
8 - .left-panel {
9 - width: 500px; background: #fff; padding: 15px;
10 - border-radius: 8px; box-shadow: 0 0 5px rgba(0,0,0,0.1);
11 - }
12 - .form-group { margin-bottom: 15px; }
13 - .form-group label { font-weight: bold; display: block; margin-bottom: 5px; }
14 - .form-group input { width: 100%; padding: 6px; border: 1px solid #ccc; border-radius: 4px; }
15 - .right-panel { flex: 1; position: relative; background: #eee; border-radius: 8px; overflow: hidden; user-select: none; }
16 - .pdf-container { position: relative; display: inline-block; }
17 - .bbox {
18 - position: absolute;
19 - border: 2px solid #ff5252;
20 - /*background-color: rgba(255, 82, 82, 0.2);*/
21 - cursor: pointer;
22 - }
23 - .bbox.active {
24 - border-color: #199601 !important;
25 - background-color: rgba(25, 150, 1, 0.4) !important;
26 - }
27 -
28 - @keyframes focusPulse {
29 - 0% { transform: scale(1); }
30 - 50% { transform: scale(1.05); }
31 - 100% { transform: scale(1); }
32 - }
33 - select {
34 - position: absolute;
35 - z-index: 10;
36 - background: #fff;
37 - border: 1px solid #ccc;
38 - }
39 - .select-box {
40 - position: absolute;
41 - /*border: 2px dashed #2196F3;*/
42 - background-color: rgba(33, 150, 243, 0.2);
43 - pointer-events: none;
44 - z-index: 5;
45 - }
46 - .delete-btn {
47 - position: absolute;
48 - bottom: -10px;
49 - right: -10px;
50 - background: #ff4d4d;
51 - color: #fff;
52 - border: none;
53 - border-radius: 50%;
54 - cursor: pointer;
55 - font-size: 14px;
56 - padding: 3px 6px;
57 - z-index: 20;
58 - }
59 - </style>
60 -
61 </head> 8 </head>
62 <body> 9 <body>
63 <meta name="csrf-token" content="{{ csrf_token() }}"> 10 <meta name="csrf-token" content="{{ csrf_token() }}">
...@@ -90,9 +37,21 @@ ...@@ -90,9 +37,21 @@
90 :style="getBoxStyle(item, index)" 37 :style="getBoxStyle(item, index)"
91 @click="onBoxClick(index)"> 38 @click="onBoxClick(index)">
92 39
40 + <div class="edge top" data-handle="top"></div>
41 + <div class="edge right" data-handle="right"></div>
42 + <div class="edge bottom" data-handle="bottom"></div>
43 + <div class="edge left" data-handle="left"></div>
44 + <!-- 4 góc -->
45 + <div class="corner nw" data-handle="nw"></div>
46 + <div class="corner ne" data-handle="ne"></div>
47 + <div class="corner sw" data-handle="sw"></div>
48 + <div class="corner se" data-handle="se"></div>
49 +
93 <button v-if="item.isManual && item.showDelete" 50 <button v-if="item.isManual && item.showDelete"
94 class="delete-btn" 51 class="delete-btn"
95 - @click.stop="deleteBox(index)">🗑</button> 52 + @click.stop="deleteBox(index)">
53 + <i class="fa-solid fa-delete-left"></i>
54 + </button>
96 </div> 55 </div>
97 56
98 57
......