Skip to content

Commit 366bdeb

Browse files
committed
progress
1 parent 1c3286a commit 366bdeb

3 files changed

Lines changed: 27 additions & 44 deletions

File tree

drawdata/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ class ScatterWidget(anywidget.AnyWidget):
1414
data = traitlets.List([]).tag(sync=True)
1515
brushsize = traitlets.Int(40).tag(sync=True)
1616
width = traitlets.Int(800).tag(sync=True)
17-
height = traitlets.Int(500).tag(sync=True)
17+
height = traitlets.Int(400).tag(sync=True)
1818

1919
@property
2020
def data_as_pandas(self):

drawdata/static/scatter_widget.js

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9536,8 +9536,9 @@ var d3 = __toESM(require_d3_v7());
95369536
function render({ model, el }) {
95379537
const colors = ["#1f77b4", "#ff7f0e", "#2ca02c", "#d62728"];
95389538
const color_map = { "#1f77b4": "a", "#ff7f0e": "b", "#2ca02c": "c", "#d62728": "d" };
9539-
const height = model.get("height") || 500;
9539+
const height = model.get("height") || 400;
95409540
const width = model.get("width") || 800;
9541+
const brushScale = width / 800;
95419542
let container = document.createElement("div");
95429543
container.className = "dd-scatter-container";
95439544
if (window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)").matches) {
@@ -9660,7 +9661,7 @@ function render({ model, el }) {
96609661
svg_container.className = "dd-scatter-svg-container";
96619662
container.appendChild(svg_container);
96629663
const aspectRatio = width / height;
9663-
let svg = d3.select(svg_container).append("svg").attr("preserveAspectRatio", "xMidYMid meet").attr("viewBox", `0 0 ${width} ${height}`).attr("width", "100%").attr("height", "auto").attr("aria-label", "Scatter plot drawing area").attr("role", "img").style("aspect-ratio", aspectRatio);
9664+
let svg = d3.select(svg_container).append("svg").attr("preserveAspectRatio", "xMidYMid meet").attr("viewBox", `0 0 ${width} ${height}`).attr("width", "100%").attr("height", "auto").attr("aria-label", "Scatter plot drawing area").attr("role", "img").style("aspect-ratio", aspectRatio).style("max-width", `${width}px`);
96649665
let batch = 0;
96659666
let isDragging = false;
96669667
svg.attr("class", "dd-scatter-svg").call(d3.drag().on("start", drag_start).on("drag", dragged).on("end", drag_end)).on("click", mouseclick).on("mousemove", mousemove);
@@ -9672,16 +9673,14 @@ function render({ model, el }) {
96729673
for (let i = 0; i <= height; i += 100) {
96739674
grid.append("line").attr("x1", 0).attr("y1", i).attr("x2", width).attr("y2", i).attr("stroke", "var(--dd-border-color, #e5e7eb)").attr("stroke-width", i % 200 === 0 ? 0.75 : 0.5).attr("opacity", i % 200 === 0 ? 0.4 : 0.2);
96749675
}
9675-
svg.append("text").attr("x", width / 2).attr("y", height - 10).attr("text-anchor", "middle").attr("fill", "var(--dd-text-color, #111827)").attr("opacity", 0.5).attr("font-size", "12px").text("X");
9676-
svg.append("text").attr("transform", "rotate(-90)").attr("x", -height / 2).attr("y", 15).attr("text-anchor", "middle").attr("fill", "var(--dd-text-color, #111827)").attr("opacity", 0.5).attr("font-size", "12px").text("Y");
96779676
}
96789677
createGrid();
96799678
function redraw_from_scratch() {
96809679
svg.selectAll("circle.drawn").remove();
96819680
if (!data)
96829681
return;
96839682
data.forEach(function(d) {
9684-
svg.append("circle").attr("cx", d.x).attr("cy", height - d.y).attr("r", 5).style("fill", d.color).style("stroke", "white").style("stroke-width", 1.5).style("opacity", 0.85).attr("class", `batch_${d.batch || 0} drawn`);
9683+
svg.append("circle").attr("cx", d.x).attr("cy", height - d.y).attr("r", 3).style("fill", d.color).style("stroke", "white").style("stroke-width", 1).style("opacity", 0.85).attr("class", `batch_${d.batch || 0} drawn`);
96859684
});
96869685
}
96879686
redraw_from_scratch();
@@ -9690,7 +9689,7 @@ function render({ model, el }) {
96909689
redraw_from_scratch();
96919690
});
96929691
model.on("change:brushsize", function() {
9693-
circle_brush.attr("r", size_input.value);
9692+
circle_brush.attr("r", size_input.value * brushScale);
96949693
size_value.innerText = size_input.value;
96959694
});
96969695
model.on("change:width", function() {
@@ -9711,7 +9710,7 @@ function render({ model, el }) {
97119710
redraw_from_scratch();
97129711
}
97139712
}
9714-
let circle_brush = svg.append("circle").attr("cx", width / 2).attr("cy", height / 2).attr("r", model.get("brushsize")).style("fill", selectedColor).style("fill-opacity", 0.3).style("stroke", selectedColor).style("stroke-width", 2).style("stroke-opacity", 0.9).attr("class", "brush-indicator");
9713+
let circle_brush = svg.append("circle").attr("cx", width / 2).attr("cy", height / 2).attr("r", model.get("brushsize") * brushScale).style("fill", selectedColor).style("fill-opacity", 0.3).style("stroke", selectedColor).style("stroke-width", 2).style("stroke-opacity", 0.9).attr("class", "brush-indicator");
97159714
function drag_start(event) {
97169715
isDragging = false;
97179716
}
@@ -9722,7 +9721,7 @@ function render({ model, el }) {
97229721
function mouseclick(event) {
97239722
if (!isDragging) {
97249723
const [x, y] = d3.pointer(event, svg.node());
9725-
let size = parseInt(size_input.value, 10);
9724+
let size = parseInt(size_input.value, 10) * brushScale;
97269725
let new_x = x + (Math.random() - 0.5) * size;
97279726
let new_y = y + (Math.random() - 0.5) * size;
97289727
add_point(new_x, new_y);
@@ -9734,11 +9733,11 @@ function render({ model, el }) {
97349733
}
97359734
function resize_brush() {
97369735
model.set("brushsize", Number(size_input.value));
9737-
circle_brush.attr("r", size_input.value);
9736+
circle_brush.attr("r", size_input.value * brushScale);
97389737
}
97399738
function add_point(new_x, new_y) {
97409739
let label = color_map[selectedColor];
9741-
svg.append("circle").attr("cx", new_x).attr("cy", new_y).attr("r", 5).style("fill", selectedColor).style("stroke", "white").style("stroke-width", 1.5).style("opacity", 0.85).attr("class", `batch_${batch} drawn`);
9740+
svg.append("circle").attr("cx", new_x).attr("cy", new_y).attr("r", 3).style("fill", selectedColor).style("stroke", "white").style("stroke-width", 1).style("opacity", 0.85).attr("class", `batch_${batch} drawn`);
97429741
if (!data)
97439742
data = [];
97449743
data.push({
@@ -9762,7 +9761,7 @@ function render({ model, el }) {
97629761
function dragged(event) {
97639762
isDragging = true;
97649763
const [x, y] = d3.pointer(event, svg.node());
9765-
let size = parseInt(size_input.value, 10);
9764+
let size = parseInt(size_input.value, 10) * brushScale;
97669765
let new_x = x + (Math.random() - 0.5) * size;
97679766
let new_y = y + (Math.random() - 0.5) * size;
97689767
add_point(new_x, new_y);

js/scatter_widget.js

Lines changed: 16 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,11 @@ function render({ model, el }) {
66
const color_map = {"#1f77b4": "a", "#ff7f0e": "b", "#2ca02c": "c", "#d62728": "d"};
77

88
// Get dimensions with fallbacks
9-
const height = model.get("height") || 500;
9+
const height = model.get("height") || 400;
1010
const width = model.get("width") || 800;
11+
12+
// Scale factor for brush size relative to base 800px width
13+
const brushScale = width / 800;
1114

1215
// Create main container with appropriate class for styling
1316
let container = document.createElement("div");
@@ -178,7 +181,8 @@ function render({ model, el }) {
178181
.attr("height", "auto")
179182
.attr("aria-label", "Scatter plot drawing area")
180183
.attr("role", "img")
181-
.style("aspect-ratio", aspectRatio);
184+
.style("aspect-ratio", aspectRatio)
185+
.style("max-width", `${width}px`);
182186

183187
let batch = 0;
184188
let isDragging = false;
@@ -221,26 +225,6 @@ function render({ model, el }) {
221225
.attr("stroke-width", i % 200 === 0 ? 0.75 : 0.5)
222226
.attr("opacity", i % 200 === 0 ? 0.4 : 0.2);
223227
}
224-
225-
// Add subtle axis labels
226-
svg.append("text")
227-
.attr("x", width / 2)
228-
.attr("y", height - 10)
229-
.attr("text-anchor", "middle")
230-
.attr("fill", "var(--dd-text-color, #111827)")
231-
.attr("opacity", 0.5)
232-
.attr("font-size", "12px")
233-
.text("X");
234-
235-
svg.append("text")
236-
.attr("transform", "rotate(-90)")
237-
.attr("x", -height / 2)
238-
.attr("y", 15)
239-
.attr("text-anchor", "middle")
240-
.attr("fill", "var(--dd-text-color, #111827)")
241-
.attr("opacity", 0.5)
242-
.attr("font-size", "12px")
243-
.text("Y");
244228
}
245229

246230
createGrid();
@@ -255,10 +239,10 @@ function render({ model, el }) {
255239
svg.append("circle")
256240
.attr("cx", d.x)
257241
.attr("cy", height - d.y)
258-
.attr("r", 5)
242+
.attr("r", 3)
259243
.style("fill", d.color)
260244
.style("stroke", "white")
261-
.style("stroke-width", 1.5)
245+
.style("stroke-width", 1)
262246
.style("opacity", 0.85)
263247
.attr("class", `batch_${d.batch || 0} drawn`);
264248
});
@@ -273,8 +257,8 @@ function render({ model, el }) {
273257
redraw_from_scratch();
274258
});
275259

276-
model.on("change:brushsize", function() {
277-
circle_brush.attr("r", size_input.value);
260+
model.on("change:brushsize", function() {
261+
circle_brush.attr("r", size_input.value * brushScale);
278262
size_value.innerText = size_input.value;
279263
});
280264

@@ -311,7 +295,7 @@ function render({ model, el }) {
311295
.append("circle")
312296
.attr("cx", width / 2)
313297
.attr("cy", height / 2)
314-
.attr("r", model.get("brushsize"))
298+
.attr("r", model.get("brushsize") * brushScale)
315299
.style("fill", selectedColor)
316300
.style("fill-opacity", 0.3)
317301
.style("stroke", selectedColor)
@@ -333,7 +317,7 @@ function render({ model, el }) {
333317
if (!isDragging) {
334318
// Use d3.pointer for more reliable coordinate detection
335319
const [x, y] = d3.pointer(event, svg.node());
336-
let size = parseInt(size_input.value, 10);
320+
let size = parseInt(size_input.value, 10) * brushScale;
337321
let new_x = x + (Math.random() - 0.5) * size;
338322
let new_y = y + (Math.random() - 0.5) * size;
339323
add_point(new_x, new_y);
@@ -350,7 +334,7 @@ function render({ model, el }) {
350334
function resize_brush() {
351335
// We want the paintbrush to show the size param, hence this update
352336
model.set("brushsize", Number(size_input.value));
353-
circle_brush.attr("r", size_input.value);
337+
circle_brush.attr("r", size_input.value * brushScale);
354338
}
355339

356340
function add_point(new_x, new_y) {
@@ -359,10 +343,10 @@ function render({ model, el }) {
359343
.append("circle")
360344
.attr("cx", new_x)
361345
.attr("cy", new_y)
362-
.attr("r", 5)
346+
.attr("r", 3)
363347
.style("fill", selectedColor)
364348
.style("stroke", "white")
365-
.style("stroke-width", 1.5)
349+
.style("stroke-width", 1)
366350
.style("opacity", 0.85)
367351
.attr("class", `batch_${batch} drawn`);
368352

@@ -397,7 +381,7 @@ function render({ model, el }) {
397381
isDragging = true;
398382
// Use d3.pointer for more reliable coordinate detection
399383
const [x, y] = d3.pointer(event, svg.node());
400-
let size = parseInt(size_input.value, 10);
384+
let size = parseInt(size_input.value, 10) * brushScale;
401385
let new_x = x + (Math.random() - 0.5) * size;
402386
let new_y = y + (Math.random() - 0.5) * size;
403387
add_point(new_x, new_y);

0 commit comments

Comments
 (0)