-
Notifications
You must be signed in to change notification settings - Fork 26
implementing geom_label_aligned #203
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
I have implemented the new geom - geom_aligned_boxes, which takes x, y, and label as required aesthetics, along with optional ones like fill, stroke, and color etc. On the JavaScript side, it dynamically measures the text size and draws a rectangle around it positioned by quadprog on renderer side, to form a label box. an example of the structure generated in the rendered HTML is as follows:
Although most of the initial implementation is complete, the positioning of these boxes using quadprog.js is not yet accurate. The elements are not restricted to the axis boundaries. I plan to refine the constraints in the quadratic programming setup to ensure correct and bounded placement. Once that is done, I will make the renderer tests for this geom. Please let me know if the current structure and approach are appropriate or if any modifications are required. |
I have improved the function for optimised positioning of the boxes that collided. For this, I referenced how the directlabels R package handles label positioning and collision avoidance , particularly this qp.labels and this source an example of this new geom is below ![]() |
I am still working on some edge cases for the positioning functions that uses quadratic programming. (like examples with horizontal alignment are not yet being positioned in the most optimal way) |
An example of how geom_aligned_boxes look is as follows : Screen.Recording.2025-06-15.at.12.08.29.AM.mov
|
Hi @tdhock , can you please review this PR when you get time? |
Got it! I have modified the grouping code to have the exact-position grouping mechanism now. |
I added an expectation about font-size that fails using the current code on the World Bank test case. Also there is a problem with the smooth transitions. When the geom appears, it flies from the upper left of the plot, but it should just appear instantly (no smooth transition). |
initial_font_sizes_num <- sapply(initial_text_nodes, function(node) { | ||
as.numeric(gsub("px", "", xmlGetAttr(node, "font-size"))) | ||
}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can you please use getStyleValue instead? (if it works? I think it should)
ts_size <- getStyleValue(info$html, '//g[@class="geom2_labelaligned_lifeExpectancyPlot"]//text', "font-size")
if (alignment == "vertical") { | ||
return d.optimizedPos - d.boxHeight / 2; | ||
} else { | ||
return d.scaledY - d.boxHeight * get_vjust(d); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
vjust is not supported anywhere else in the code -- please add test cases for values other than 0.5
var fontsize = d.size; | ||
var textSize = measureText(d.label, fontsize, d.angle, textStyle); | ||
d.boxWidth = textSize.width; | ||
d.boxHeight = textSize.height; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
#' @inheritParams geom_point | ||
#' @param label_r Radius of rounded corners. Defaults to 0.15 lines. | ||
#' @param alignment One of "vertical" (QP on Y axis) or "horizontal" (QP on X axis) | ||
#' @param min_distance Minimum distance between boxes in native units. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
expect_equal(as.numeric(attrs[["rx"]]), 5) | ||
expect_equal(as.numeric(attrs[["ry"]]), 5) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why is rx 5 if label_r=9 ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please change so that rx/ry are same as label_r, or justify this choice.
This is really excellent work! Please fix the few things I mentioned before I merge. We are almost done. |
test_that("label size is correct", { | ||
ts_size <- getStyleValue(info$html, '//g[@class="geom2_labelaligned_lifeExpectancyPlot"]//text', "font-size") | ||
expect_equal(ts_size, rep(5, nrow(label_data_line))) | ||
scatter_size <- getStyleValue(info$html, '//g[@class="geom4_labelaligned_worldbankAnim"]//text', "font-size") | ||
expect_equal(scatter_size, rep(10, nrow(label_data_line))) | ||
}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added this block to test font-size attribute.
resolving #174
This PR introduces a new geom, geom_aligned_boxes, as proposed in the issue. (name of the geom can be changed if needed)
Status: Initial implementation — still a work in progress and requires a lot of modifications and bug fixing. I am pushing the code made till now to seek guidance.
Current issue: While testing with examples, I noticed that the generated HTML renders:
<g class="geom1_alignedboxes_plot"><g class="PANEL1"></g></g>
The PANEL1 elements are empty, no boxes are being rendered. I suspect I may be missing a key step in correctly registering or drawing the new geom. Any guidance on what might be causing this?