如何将setUserCallbacks()回调应用到newSubscene3d()生成的非首个子场景?
解决rgl中子场景无法接收setUserCallbacks事件的问题
你遇到的问题是:通过newSubscene3d()创建的子场景无法响应setUserCallbacks()设置的鼠标回调,只有第一个主场景能触发事件,比如示例里左下角的子场景区域点击无反应。下面提供两种可行的解决方法:
方法一:给每个子场景单独注册回调
setUserCallbacks()默认只作用于你指定的单个subscene(示例中是rootSubscene$id),因此需要遍历所有子场景,分别为它们设置回调。
修改你的index.Rmd代码如下:
sys.source("ex.R", envir = knit_global()) func1() # 获取当前场景的所有子场景ID full_scene <- scene3d(minimal = FALSE) all_subscene_ids <- full_scene$subscenes$id # 遍历每个子场景,设置回调 for (sub_id in all_subscene_ids) { full_scene <- setUserCallbacks("left", begin = "alert('AAA')", update = "alert('BBB')", end = "alert('CCC')", scene = full_scene, subscene = sub_id, applyToScene = TRUE, applyToDev = FALSE) } rglwidget(full_scene)
方法二:创建顶层覆盖场景统一处理事件
如果子场景较多或需要统一的事件逻辑,可以创建一个覆盖整个视口的透明顶层子场景,让它接收所有鼠标事件,再根据坐标判断触发对应子场景的逻辑。
步骤1:修改ex.R添加顶层场景
在func1()函数末尾添加:
# 创建覆盖整个视口的顶层子场景 func1.scene.top <- newSubscene3d(newviewport = c(0, 0, 500, 500)) useSubscene3d(func1.scene.top) # 不渲染任何内容,保持透明
步骤2:在index.Rmd中给顶层场景设置回调
sys.source("ex.R", envir = knit_global()) func1() scene <- setUserCallbacks("left", begin = "function(x, y) { // 判断鼠标是否在子场景2的视口范围内(0,0,200,200) if (x >= 0 && x <= 200 && y >= 0 && y <= 200) { alert('子场景2触发AAA'); } else { alert('主场景触发AAA'); } }", update = "function(x, y) { if (x >= 0 && x <= 200 && y >= 0 && y <= 200) { alert('子场景2触发BBB'); } else { alert('主场景触发BBB'); } }", end = "alert('CCC')", scene = scene3d(minimal = FALSE), subscene = func1.scene.top, applyToScene = TRUE, applyToDev = FALSE) rglwidget(scene)
注意事项
- 你原代码中
ex.R里的rgl.setMouseCallbacks()是针对本地RGL窗口的回调,在WebGL输出(rglwidget)中无效,需要用setUserCallbacks()来设置Web端的回调逻辑。
内容的提问来源于stack exchange,提问作者大根おろし
相关产品推荐
相关产品推荐

