[FIX] web_editor: improve perfs of background animations on Chrome

Prior to this commit, animations on SVG shapes could use a lot of CPU
and make the page stutter on some website + machine combo.

This does not seem to be an "Odoo Only" issue as browsers seem to
struggle to optimise SVG movements and end up consuming a decent amount
of CPU depending on the machine, the size of the SVG and its position
(behind or on top of other elements).

This commit applies a new class which will warn the browser that the
element is animated. Depending on the browser, some optimisations are
done.
On Chrome and Safari, a new layer is created which simplifies the
rendering of the page and sometimes takes advantage of hardware
acceleration.
On Firefox, no optimisation is done yet. This might change in an update
which would take advantage of the CSS Property.

The documentation says to only use `will-change` when an element is
about to change. This is the case however, as most of the shape's
animations are looping. Which is why it's applied to every shape that is
animated.

This optimisation only applies to background shapes with this commit.

Performance improvements observed by (at)rdeodoo on his machine:
- SVG: 200% CPU
- SVG + fix (will-change): 55% CPU
(additional infos available in the PR)

To note: one way to easily see the improvement is on the "Layers" tab of
the Chrome devtools. Before this commit, the entire #wrapwrap is
repainted every time the shape changes (so 60 times per second since
that is the framerate the browser aims for). With this commit, the
#wrapwrap and the shape are contained in their own layers so the
#wrapwrap is only painted once.

Other solutions were considered but not used at this time:
- Reducing the frame rate of the animations. This is not currently
possible because browsers do not offer any way of doing that.
- Removing bits of the shape can reduce its CPU consumption, but
whenever a transform animation is present, the CPU usage remains high.

task-3142001

closes odoo/odoo#114252

X-original-commit: 03418be1c67e71a22f6d2ce79675280f889b663c
Signed-off-by: Benoit Socias (bso) <bso@odoo.com>
This commit is contained in:
Arthur Detroux (ard)
2023-03-02 21:56:48 +01:00
parent 225d9925dc
commit ce3f689b2f
2 changed files with 13 additions and 2 deletions
@@ -6833,7 +6833,12 @@ registry.BackgroundShape = SnippetOptionWidget.extend({
*/
shape(previewMode, widgetValue, params) {
this._handlePreviewState(previewMode, () => {
return {shape: widgetValue, colors: this._getImplicitColors(widgetValue, this._getShapeData().colors), flip: []};
return {
shape: widgetValue,
colors: this._getImplicitColors(widgetValue, this._getShapeData().colors),
flip: [],
animated: params.animated,
};
});
},
/**
@@ -7015,7 +7020,7 @@ registry.BackgroundShape = SnippetOptionWidget.extend({
// Updates/removes the shape container as needed and gives it the
// correct background shape
const json = target.dataset.oeShapeData;
const {shape, colors, flip = []} = json ? JSON.parse(json) : {};
const {shape, colors, flip = [], animated = 'false'} = json ? JSON.parse(json) : {};
let shapeContainer = target.querySelector(':scope > .o_we_shape');
if (!shape) {
return this._insertShapeContainer(null);
@@ -7027,6 +7032,8 @@ registry.BackgroundShape = SnippetOptionWidget.extend({
// Compat: remove old flip classes as flipping is now done inside the svg
shapeContainer.classList.remove('o_we_flip_x', 'o_we_flip_y');
shapeContainer.classList.toggle('o_we_animated', animated === 'true');
if (colors || flip.length) {
// Custom colors/flip, overwrite shape that is set by the class
$(shapeContainer).css('background-image', `url("${this._getShapeSrc()}")`);
@@ -976,6 +976,10 @@ section, .oe_img_bg, [data-oe-shape-data] {
.o_we_shape {
@extend %o-we-background-layer;
&.o_we_animated {
will-change: transform;
}
// Default map to use to map shape file colors to color combination
// background colors.
$default-color-to-cc-bg-map: (