gnome-shell/js/ui/ripples.js
Zander Brown 350cd296fa js: Stop using ClutterContainer API
These have been long deprecated over in clutter, and (via several
vtables) simply forward the call to the equivalent ClutterActor methods

Save ourselves the hassle and just use ClutterActor methods directly

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/3010>
2023-11-10 20:19:13 +00:00

111 lines
3.5 KiB
JavaScript

// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
import Clutter from 'gi://Clutter';
import St from 'gi://St';
// Shamelessly copied from the layout "hotcorner" ripples implementation
export class Ripples {
constructor(px, py, styleClass) {
this._x = 0;
this._y = 0;
this._px = px;
this._py = py;
this._ripple1 = new St.BoxLayout({
style_class: styleClass,
opacity: 0,
can_focus: false,
reactive: false,
visible: false,
});
this._ripple1.set_pivot_point(px, py);
this._ripple2 = new St.BoxLayout({
style_class: styleClass,
opacity: 0,
can_focus: false,
reactive: false,
visible: false,
});
this._ripple2.set_pivot_point(px, py);
this._ripple3 = new St.BoxLayout({
style_class: styleClass,
opacity: 0,
can_focus: false,
reactive: false,
visible: false,
});
this._ripple3.set_pivot_point(px, py);
}
destroy() {
this._ripple1.destroy();
this._ripple2.destroy();
this._ripple3.destroy();
}
_animRipple(ripple, delay, duration, startScale, startOpacity, finalScale) {
// We draw a ripple by using a source image and animating it scaling
// outwards and fading away. We want the ripples to move linearly
// or it looks unrealistic, but if the opacity of the ripple goes
// linearly to zero it fades away too quickly, so we use a separate
// tween to give a non-linear curve to the fade-away and make
// it more visible in the middle section.
ripple.x = this._x;
ripple.y = this._y;
ripple.visible = true;
ripple.opacity = 255 * Math.sqrt(startOpacity);
ripple.scale_x = ripple.scale_y = startScale;
ripple.set_translation(-this._px * ripple.width, -this._py * ripple.height, 0.0);
ripple.ease({
opacity: 0,
delay,
duration,
mode: Clutter.AnimationMode.EASE_IN_QUAD,
});
ripple.ease({
scale_x: finalScale,
scale_y: finalScale,
delay,
duration,
mode: Clutter.AnimationMode.LINEAR,
onComplete: () => (ripple.visible = false),
});
}
addTo(stage) {
if (this._stage !== undefined)
throw new Error('Ripples already added');
this._stage = stage;
this._stage.add_child(this._ripple1);
this._stage.add_child(this._ripple2);
this._stage.add_child(this._ripple3);
}
playAnimation(x, y) {
if (this._stage === undefined)
throw new Error('Ripples not added');
this._x = x;
this._y = y;
this._stage.set_child_above_sibling(this._ripple1, null);
this._stage.set_child_above_sibling(this._ripple2, this._ripple1);
this._stage.set_child_above_sibling(this._ripple3, this._ripple2);
// Show three concentric ripples expanding outwards; the exact
// parameters were found by trial and error, so don't look
// for them to make perfect sense mathematically
// delay time scale opacity => scale
this._animRipple(this._ripple1, 0, 830, 0.25, 1.0, 1.5);
this._animRipple(this._ripple2, 50, 1000, 0.0, 0.7, 1.25);
this._animRipple(this._ripple3, 350, 1000, 0.0, 0.3, 1);
}
}