diff --git a/inst/htmljs/animint.js b/inst/htmljs/animint.js
index 04c21430..bfcc4b07 100644
--- a/inst/htmljs/animint.js
+++ b/inst/htmljs/animint.js
@@ -1982,7 +1982,7 @@ var animint = function (to_select, json_file) {
// Once scales are updated, update the axis ticks if needed
if(draw_axes){
// Tick values are same as major grid lines
- update_axes(p_name, xyaxis, panel_i, grid_vals[1]);
+ update_axes(p_name, xyaxis, panel_i, grid_vals[1], v_name);
}
// Update major and minor grid lines
update_grids(p_name, xyaxis, panel_i, grid_vals, scales);
@@ -1994,7 +1994,7 @@ var animint = function (to_select, json_file) {
// Update the axis ticks etc. once plot is zoomed in/out
// currently called from update_scales.
- function update_axes(p_name, axes, panel_i, tick_vals){
+ function update_axes(p_name, axes, panel_i, tick_vals, v_name){
var orientation;
if(axes == "x"){
orientation = "bottom";
@@ -2010,9 +2010,13 @@ var animint = function (to_select, json_file) {
.tickValues(tick_vals);
// update existing axis
var xyaxis_sel = element.select("#"+viz_id+"_"+p_name).select("."+axes+"axis_"+panel_i);
+ var milliseconds = 0;
+ if(v_name && Selectors.hasOwnProperty(v_name) && Selectors[v_name].hasOwnProperty("duration")){
+ milliseconds = Selectors[v_name].duration;
+ }
var xyaxis_g = xyaxis_sel
.transition()
- .duration(1000)
+ .duration(milliseconds)
.call(xyaxis);
// Fix for issue #273: preserve axis text styling after update
apply_axis_text_styles(xyaxis_sel, axes, Plots[p_name]);
diff --git a/tests/testthat/test-renderer3-update-axes-duration.R b/tests/testthat/test-renderer3-update-axes-duration.R
new file mode 100644
index 00000000..fcfb0a18
--- /dev/null
+++ b/tests/testthat/test-renderer3-update-axes-duration.R
@@ -0,0 +1,38 @@
+acontext("update_axes respects selector duration - Issue #276")
+# Test that update_axes uses the selector's duration option instead of hardcoded 1000ms
+# This follows the same pattern as test-renderer3-update-axes.R
+mtcars$cyl <- as.factor(mtcars$cyl)
+viz_duration <- animint(
+ scatter = ggplot() +
+ geom_point(aes(mpg, disp, colour=cyl), data=mtcars) +
+ theme_animint(update_axes=c("x", "y")),
+ duration=list(cyl=2000),
+ selector.types=list(cyl="single")
+)
+info <- animint2HTML(viz_duration)
+
+# Get initial tick positions using same pattern as test-renderer3-update-axes.R
+rect_path <- "//svg[@id='plot_scatter']//g[contains(@class, '%saxis')]"
+x_axis_node <- getNodeSet(info$html, sprintf(rect_path, "x"))[[1]]
+y_axis_node <- getNodeSet(info$html, sprintf(rect_path, "y"))[[1]]
+original_tick_diff_x <- getTickDiff(x_axis_node, axis="x")
+original_tick_diff_y <- getTickDiff(y_axis_node, axis="y")
+
+# Click to change selector
+clickID("plot_scatter_cyl_variable_8")
+Sys.sleep(0.5)
+html_updated <- getHTML()
+
+# Get updated tick positions
+x_axis_node_updated <- getNodeSet(html_updated, sprintf(rect_path, "x"))[[1]]
+y_axis_node_updated <- getNodeSet(html_updated, sprintf(rect_path, "y"))[[1]]
+updated_tick_diff_x <- getTickDiff(x_axis_node_updated, axis="x")
+updated_tick_diff_y <- getTickDiff(y_axis_node_updated, axis="y")
+
+test_that("update_axes uses selector duration for transitions", {
+ # Verify ticks changed (confirms update_axes was called with correct duration)
+ # Tick spacing changes when filtering to different cyl values (4, 6, 8)
+ # because each subset has different mpg/disp ranges
+ expect_gt(abs(updated_tick_diff_x - original_tick_diff_x), 0)
+ expect_gt(abs(updated_tick_diff_y - original_tick_diff_y), 0)
+})