Skip to content

Commit 23c6b89

Browse files
committed
Add inner exclusion cricle
1 parent 6bd7929 commit 23c6b89

1 file changed

Lines changed: 142 additions & 108 deletions

File tree

index.html

Lines changed: 142 additions & 108 deletions
Original file line numberDiff line numberDiff line change
@@ -27,16 +27,17 @@
2727
.controls {
2828
margin: 10px;
2929
}
30-
.circle {
30+
.circle, .inner-circle {
3131
position: absolute;
32-
border: 2px solid red;
3332
border-radius: 50%;
3433
background: transparent;
35-
cursor: grab;
34+
pointer-events: none;
3635
}
37-
textarea {
38-
width: 90%;
39-
margin: 10px;
36+
.circle {
37+
border: 2px solid red;
38+
}
39+
.inner-circle {
40+
border: 2px solid blue;
4041
}
4142
</style>
4243
</head>
@@ -45,9 +46,8 @@
4546
<div class="controls">
4647
<input type="file" id="fileInput">
4748
<label>m: <input type="number" id="rows" value="3" min="1"></label>
48-
<label>n: <input type="number" id="cols" value="4" min="1"></label>
49+
<label>n: <input type="number" id="cols" value="3" min="1"></label>
4950
<button onclick="createGrid()">Create Grid</button>
50-
<button onclick="exportCoords()">Export</button>
5151
<button onclick="showGrayLevels()">Mean Gray</button>
5252
</div>
5353

@@ -66,6 +66,7 @@
6666
let img = new Image();
6767
let circles = [];
6868
let radius = 20;
69+
let innerRadius = 15;
6970
let draggingCircle = null;
7071
let offsetX, offsetY;
7172

@@ -86,101 +87,178 @@
8687
}
8788

8889
function clearCircles() {
89-
circles.forEach(c => c.el.remove());
90+
circles.flat().forEach(c => {
91+
c.outer.el.remove();
92+
c.inner.el.remove();
93+
});
9094
circles = [];
9195
}
9296

9397
function createGrid() {
9498
clearCircles();
99+
drawImage();
95100
const m = parseInt(document.getElementById("rows").value);
96101
const n = parseInt(document.getElementById("cols").value);
97102
const spacingX = canvas.width / (n + 1);
98103
const spacingY = canvas.height / (m + 1);
104+
99105
for (let i = 0; i < m; i++) {
100106
circles.push([]);
101107
for (let j = 0; j < n; j++) {
102108
const x = (j + 1) * spacingX;
103109
const y = (i + 1) * spacingY;
104-
const el = document.createElement("div");
105-
el.className = "circle";
106-
el.style.width = el.style.height = radius * 2 + "px";
107-
el.style.left = (x - radius) + "px";
108-
el.style.top = (y - radius) + "px";
109-
makeDraggable(el);
110-
container.appendChild(el);
111-
circles[i].push({ x, y, el });
110+
111+
const outer = document.createElement("div");
112+
outer.className = "circle";
113+
outer.style.width = outer.style.height = radius * 2 + "px";
114+
outer.style.left = (x - radius) + "px";
115+
outer.style.top = (y - radius) + "px";
116+
outer.style.cursor = "grab";
117+
outer.style.pointerEvents = "auto";
118+
container.appendChild(outer);
119+
120+
const inner = document.createElement("div");
121+
inner.className = "inner-circle";
122+
inner.style.width = innerRadius * 2 + "px";
123+
inner.style.height = innerRadius * 2 + "px";
124+
inner.style.left = (x - innerRadius) + "px";
125+
inner.style.top = (y - innerRadius) + "px";
126+
container.appendChild(inner);
127+
128+
makeDraggable(outer, inner);
129+
130+
circles[i].push({ x, y, outer: { el: outer }, inner: inner });
112131
}
113132
}
114133
}
115134

116-
function makeDraggable(el) {
117-
el.onmousedown = (e) => {
118-
draggingCircle = el;
135+
function makeDraggable(outerEl, innerEl) {
136+
outerEl.onmousedown = (e) => {
137+
draggingCircle = outerEl;
119138
offsetX = e.offsetX;
120139
offsetY = e.offsetY;
121-
el.style.cursor = "grabbing";
140+
outerEl.style.cursor = "grabbing";
141+
122142
document.onmousemove = (e) => {
123143
const rect = container.getBoundingClientRect();
124-
el.style.left = (e.clientX - rect.left - offsetX) + "px";
125-
el.style.top = (e.clientY - rect.top - offsetY) + "px";
126-
updateCirclePosition(el);
144+
const newX = e.clientX - rect.left - offsetX;
145+
const newY = e.clientY - rect.top - offsetY;
146+
outerEl.style.left = newX + "px";
147+
outerEl.style.top = newY + "px";
148+
149+
const x = newX + radius;
150+
const y = newY + radius;
151+
152+
innerEl.style.left = (x - innerRadius) + "px";
153+
innerEl.style.top = (y - innerRadius) + "px";
154+
155+
console.log(e)
156+
updateCirclePosition(e.target);
127157
};
158+
128159
document.onmouseup = () => {
129160
document.onmousemove = null;
130161
draggingCircle = null;
131-
el.style.cursor = "grab";
162+
outerEl.style.cursor = "grab";
132163
};
133164
};
134165
}
135166

136167
function updateCirclePosition(el) {
137168
for (let i = 0; i < circles.length; i++) {
138169
for (let j = 0; j < circles[i].length; j++) {
139-
if (circles[i][j].el === el) {
170+
if (circles[i][j].outer.el === el) {
140171
circles[i][j].x = parseInt(el.style.left) + radius;
141172
circles[i][j].y = parseInt(el.style.top) + radius;
142173
}
143174
}
144175
}
145176
}
146177

178+
document.addEventListener("keydown", (e) => {
179+
const keys = ["ArrowUp", "ArrowDown", "ArrowLeft", "ArrowRight", "+", "-", "k", "l"];
180+
if (keys.includes(e.key)) {
181+
e.preventDefault();
182+
if (e.key === "ArrowUp") moveCircles(0, -5);
183+
if (e.key === "ArrowDown") moveCircles(0, 5);
184+
if (e.key === "ArrowLeft") moveCircles(-5, 0);
185+
if (e.key === "ArrowRight") moveCircles(5, 0);
186+
if (e.key === "+") resizeCircles(1.1);
187+
if (e.key === "-") resizeCircles(0.9);
188+
if (e.key === "k") resizeInnerCircles(1.1);
189+
if (e.key === "l") resizeInnerCircles(0.9);
190+
}
191+
});
192+
147193
function moveCircles(dx, dy) {
148194
circles.flat().forEach(c => {
149195
c.x += dx;
150196
c.y += dy;
151-
c.el.style.left = (c.x - radius) + "px";
152-
c.el.style.top = (c.y - radius) + "px";
197+
c.outer.el.style.left = (c.x - radius) + "px";
198+
c.outer.el.style.top = (c.y - radius) + "px";
199+
c.inner.style.left = (c.x - innerRadius) + "px";
200+
c.inner.style.top = (c.y - innerRadius) + "px";
153201
});
154202
}
155203

156204
function resizeCircles(factor) {
157-
radius = Math.round(radius*factor);
158-
console.log(radius)
205+
radius *= factor;
206+
innerRadius *= factor;
207+
radius = Math.round(radius);
208+
innerRadius = Math.round(innerRadius);
159209
circles.flat().forEach(c => {
160-
c.el.style.width = c.el.style.height = radius * 2 + "px";
161-
c.el.style.left = (c.x - radius) + "px";
162-
c.el.style.top = (c.y - radius) + "px";
210+
c.outer.el.style.width = c.outer.el.style.height = radius * 2 + "px";
211+
c.outer.el.style.left = (c.x - radius) + "px";
212+
c.outer.el.style.top = (c.y - radius) + "px";
213+
c.inner.style.width = c.inner.style.height = innerRadius * 2 + "px";
214+
c.inner.style.left = (c.x - innerRadius) + "px";
215+
c.inner.style.top = (c.y - innerRadius) + "px";
163216
});
164217
}
165218

166-
function exportCoords() {
167-
let m = circles.length;
168-
let n = (m > 0) ? circles[0].length : 0;
169-
let result = "coords = [\n";
170-
for (let i = 0; i < m; i++) {
171-
result += " [";
172-
for (let j = 0; j < n; j++) {
173-
let x = Math.round(circles[i][j].x);
174-
let y = Math.round(circles[i][j].y);
175-
result += `[${x}, ${y}]${j < n - 1 ? ", " : ""}`;
219+
function resizeInnerCircles(factor) {
220+
innerRadius *= factor;
221+
circles.flat().forEach(c => {
222+
c.inner.style.width = c.inner.style.height = innerRadius * 2 + "px";
223+
c.inner.style.left = (c.x - innerRadius) + "px";
224+
c.inner.style.top = (c.y - innerRadius) + "px";
225+
});
226+
}
227+
228+
document.getElementById("fileInput").onchange = (e) => {
229+
loadImageFromFile(e.target.files[0]);
230+
};
231+
232+
function handleDrop(e) {
233+
e.preventDefault();
234+
const file = e.dataTransfer.files[0];
235+
if (file) loadImageFromFile(file);
236+
}
237+
238+
container.addEventListener("dragover", (e) => e.preventDefault());
239+
container.addEventListener("drop", handleDrop);
240+
241+
document.addEventListener("paste", (e) => {
242+
const items = e.clipboardData.items;
243+
for (let i = 0; i < items.length; i++) {
244+
if (items[i].type.indexOf("image") !== -1) {
245+
const blob = items[i].getAsFile();
246+
loadImageFromFile(blob);
176247
}
177-
result += `]${i < m - 1 ? ",\n" : ""}`;
178248
}
179-
result += "\n]";
180-
console.log(result);
181-
navigator.clipboard.writeText(result)
182-
.then(() => alert("Copied coordinates to clipboard!"))
183-
.catch(err => alert("Failed to copy: " + err));
249+
});
250+
251+
function loadImageFromFile(file) {
252+
const reader = new FileReader();
253+
reader.onload = (e) => {
254+
img.onload = () => {
255+
resizeCanvasToImage();
256+
drawImage();
257+
clearCircles();
258+
};
259+
img.src = e.target.result;
260+
};
261+
reader.readAsDataURL(file);
184262
}
185263

186264
function getMeanGrayAt(x, y, radius) {
@@ -197,19 +275,21 @@
197275
const dx = i - radius;
198276
const dy = j - radius;
199277
if (dx * dx + dy * dy <= radius * radius) {
200-
const idx = (j * radius * 2 + i) * 4;
201-
202-
const r = data[idx];
203-
const g = data[idx + 1];
204-
const b = data[idx + 2];
205-
const gray = 0.299 * r + 0.587 * g + 0.114 * b;
206-
sum += gray;
207-
count++;
208-
209-
// Color this pixel red
210-
//data[idx] = 255;
211-
//data[idx + 1] = 0;
212-
//data[idx + 2] = 0;
278+
if (dx * dx + dy * dy >= innerRadius * innerRadius) {
279+
const idx = (j * radius * 2 + i) * 4;
280+
281+
const r = data[idx];
282+
const g = data[idx + 1];
283+
const b = data[idx + 2];
284+
const gray = 0.299 * r + 0.587 * g + 0.114 * b;
285+
sum += gray;
286+
count++;
287+
288+
// Color this pixel red
289+
//data[idx] = 255;
290+
//data[idx + 1] = 0;
291+
//data[idx + 2] = 0;
292+
}
213293
}
214294
}
215295
}
@@ -220,7 +300,6 @@
220300
return count > 0 ? +(sum / count).toFixed(1) : 0;
221301
}
222302

223-
224303
function showGrayLevels() {
225304
let m = circles.length;
226305
let n = (m > 0) ? circles[0].length : 0;
@@ -238,51 +317,6 @@
238317
result += "\n]";
239318
document.getElementById("grayOutput").value = result;
240319
}
241-
242-
document.addEventListener("keydown", (e) => {
243-
if (["ArrowUp", "ArrowDown", "ArrowLeft", "ArrowRight", "+", "-"].includes(e.key)) {
244-
e.preventDefault();
245-
if (e.key === "ArrowUp") moveCircles(0, -5);
246-
if (e.key === "ArrowDown") moveCircles(0, 5);
247-
if (e.key === "ArrowLeft") moveCircles(-5, 0);
248-
if (e.key === "ArrowRight") moveCircles(5, 0);
249-
if (e.key === "+") resizeCircles(1.1);
250-
if (e.key === "-") resizeCircles(0.9);
251-
}
252-
});
253-
254-
document.getElementById("fileInput").onchange = (e) => {
255-
loadImageFromFile(e.target.files[0]);
256-
};
257-
258-
function handleDrop(e) {
259-
e.preventDefault();
260-
const file = e.dataTransfer.files[0];
261-
if (file) loadImageFromFile(file);
262-
}
263-
264-
document.addEventListener("paste", (e) => {
265-
const items = e.clipboardData.items;
266-
for (let i = 0; i < items.length; i++) {
267-
if (items[i].type.indexOf("image") !== -1) {
268-
const blob = items[i].getAsFile();
269-
loadImageFromFile(blob);
270-
}
271-
}
272-
});
273-
274-
function loadImageFromFile(file) {
275-
const reader = new FileReader();
276-
reader.onload = (e) => {
277-
img.onload = () => {
278-
resizeCanvasToImage();
279-
drawImage();
280-
clearCircles();
281-
};
282-
img.src = e.target.result;
283-
};
284-
reader.readAsDataURL(file);
285-
}
286320
</script>
287321

288322
</body>

0 commit comments

Comments
 (0)