Conversation
|
感觉改之后很多地方没有足够的空间显示阴影,看着很奇怪。 |
|
/gemini review |
There was a problem hiding this comment.
Code Review
This pull request refactors the hover animation logic by moving it from RipplerContainer to JFXRippler, introducing a hoverOverlay rectangle and implementing mouse event handlers for background interpolation. The review feedback recommends using Animation or Timeline instead of Transition to prevent visual jumps during rapid mouse movements and suggests simplifying the interpolateBackground method for better efficiency.
| protected RippleGenerator rippler; | ||
| protected Pane ripplerPane; | ||
| protected Node control; | ||
| private Transition coverAnimation; |
| mouseEventHandler = event -> { | ||
| if (coverAnimation != null) { | ||
| coverAnimation.stop(); | ||
| coverAnimation = null; | ||
| } | ||
|
|
||
| if (event.getEventType() == MouseEvent.MOUSE_ENTERED) { | ||
| coverAnimation = new Transition() { | ||
| { | ||
| setCycleDuration(Motion.SHORT4); | ||
| setInterpolator(Motion.EASE_IN); | ||
| } | ||
|
|
||
| @Override | ||
| protected void interpolate(double frac) { | ||
| interpolateBackground(frac); | ||
| } | ||
| }; | ||
| } else { | ||
| coverAnimation = new Transition() { | ||
| { | ||
| setCycleDuration(Motion.SHORT4); | ||
| setInterpolator(Motion.EASE_OUT); | ||
| } | ||
|
|
||
| @Override | ||
| protected void interpolate(double frac) { | ||
| interpolateBackground(1 - frac); | ||
| } | ||
| }; | ||
| } | ||
|
|
||
| coverAnimation.play(); | ||
| }; |
There was a problem hiding this comment.
目前的动画实现方式在鼠标快速移入移出时会产生明显的跳变。这是因为每次事件都会创建一个新的 Transition,并且动画总是从固定的起始值(0 或 1)开始,而没有考虑当前的透明度状态。建议改用 Timeline 并直接对 hoverOverlay 的 opacityProperty 进行动画处理,这样 JavaFX 会自动从当前值开始平滑过渡,同时也能减少对象的频繁创建。
mouseEventHandler = event -> {
if (coverAnimation != null) {
coverAnimation.stop();
}
boolean isEntered = event.getEventType() == MouseEvent.MOUSE_ENTERED;
Color onSurface = Themes.getColorScheme().getOnSurface();
hoverOverlay.setFill(Color.color(onSurface.getRed(), onSurface.getGreen(), onSurface.getBlue(), 0.04));
coverAnimation = new Timeline(new KeyFrame(Motion.SHORT4,
new KeyValue(hoverOverlay.opacityProperty(), isEntered ? 1 : 0, isEntered ? Motion.EASE_IN : Motion.EASE_OUT)));
coverAnimation.play();
};| private void interpolateBackground(double frac) { | ||
| if (hoverOverlay == null) return; | ||
| if (frac < 0.01) { | ||
| hoverOverlay.setOpacity(0); | ||
| return; | ||
| } | ||
| Color onSurface = Themes.getColorScheme().getOnSurface(); | ||
| Color fillColor = Color.color(onSurface.getRed(), onSurface.getGreen(), onSurface.getBlue(), frac * 0.04); | ||
| hoverOverlay.setFill(fillColor); | ||
| hoverOverlay.setOpacity(1); | ||
| } |
There was a problem hiding this comment.
简化 interpolateBackground 方法。如果采用动画化 opacityProperty 的方案,此方法只需负责设置填充颜色和最终的透明度即可。这不仅使代码更简洁,也提高了渲染效率。
private void interpolateBackground(double frac) {
if (hoverOverlay == null) return;
Color onSurface = Themes.getColorScheme().getOnSurface();
hoverOverlay.setFill(Color.color(onSurface.getRed(), onSurface.getGreen(), onSurface.getBlue(), 0.04));
hoverOverlay.setOpacity(frac);
}
放在 JFXRippler 中实现 JFXButton 等 JFoenix 控件也能有悬停效果