[FIX] web_editor, website: mitigate line between shapes issues

This commit mitigates an issue with shape elements sometimes having tiny
spacing on their top or bottom edge.

This issue is mainly on Chrome when the user has changed the page zoom.
When the page is zoomed the elements can have a width value with a
decimal part. Because of it, the size of the SVG background images are
not correctly rounded compared to their container and therefore leaves a
visible space.

Steps to reproduce the bug:

- On Chrome, add several shapes on a website page.
- Change the zoom of the page and change the window width.
- At some points, the gap will appear.

The least bad solution we found to fix this is to ensure that the width
of the shape elements is always as close to an integer as possible.

Reminder: several commits had attempted to fix this before ([1], [2],
[3], [4]). But that wasn't enough to stop it happening. Some shapes
still need to be fixed although that will likely be done in future
versions.

[1]: https://github.com/odoo/odoo/commit/c0f62593a4da37e8404dddc0a5762879a5ebbf7f
[2]: https://github.com/odoo/odoo/commit/ac82407b259eab929486bf0a333a48bc507efa60
[3]: https://github.com/odoo/odoo/commit/42b3ad10e0b32b7fc72f801e2c67d6baf938c566
[4]: https://github.com/odoo/odoo/commit/e386f318f5cff50901dba3db8a2587911ba02a6e

task-2824607
opw-3069213
opw-3057533

X-original-commit: 623db525e18931a4dd5794da78be840afc34991a
Part-of: odoo/odoo#108228
This commit is contained in:
Benjamin Vray
2022-12-18 23:16:57 +01:00
committed by qsm-odoo
parent 8850e98233
commit e13743ff2e
3 changed files with 101 additions and 2 deletions
@@ -6757,7 +6757,7 @@ registry.BackgroundShape = SnippetOptionWidget.extend({
const shapeContainer = target.querySelector(':scope > .o_we_shape');
if (shapeContainer) {
shapeContainer.remove();
this._removeShapeEl(shapeContainer);
}
if (newContainer) {
const preShapeLayerElement = this._getLastPreShapeLayerElement();
@@ -6855,6 +6855,13 @@ registry.BackgroundShape = SnippetOptionWidget.extend({
this.prevShape = target.dataset.oeShapeData;
}
},
/**
* @private
* @param {HTMLElement} shapeEl
*/
_removeShapeEl(shapeEl) {
shapeEl.remove();
},
/**
* Overwrites shape properties with the specified data.
*
@@ -1467,6 +1467,89 @@ registry.ImagesLazyLoading = publicWidget.Widget.extend({
},
});
/**
* @todo while this solution mitigates the issue, it is not fixing it entirely
* but mainly, we should find a better solution than a JS solution as soon as
* one is available and ideally without having to make ugly patches to the SVGs.
*
* Due to a bug on Chrome when using browser zoom, there is sometimes a gap
* between sections with shapes. This gap is due to a rounding issue when
* positioning the SVG background images. This code reduces the rounding error
* by ensuring that shape elements always have a width value as close to an
* integer as possible.
*
* Note: a gap also appears between some shapes without zoom. This is likely
* due to error in the shapes themselves. Many things were done to try and fix
* this, but the remaining errors will likely be fixed with a review of the
* shapes in future Odoo versions.
*
* /!\
* If a better solution for stable comes up, this widget behavior may be
* disabled, avoid depending on it if possible.
* /!\
*/
registry.ZoomedBackgroundShape = publicWidget.Widget.extend({
selector: '.o_we_shape',
disabledInEditableMode: false,
/**
* @override
*/
start() {
this._onBackgroundShapeResize();
this.throttledShapeResize = _.throttle(() => this._onBackgroundShapeResize(), 25);
window.addEventListener('resize', this.throttledShapeResize);
return this._super(...arguments);
},
/**
* @override
*/
destroy() {
this._updateShapePosition();
window.removeEventListener('resize', this.throttledShapeResize);
this._super(...arguments);
},
//--------------------------------------------------------------------------
// Private
//--------------------------------------------------------------------------
/**
* Updates the left and right offset of the shape.
*
* @private
* @param {string} offset
*/
_updateShapePosition(offset = '') {
this.el.style.left = offset;
this.el.style.right = offset;
},
//--------------------------------------------------------------------------
// Handlers
//--------------------------------------------------------------------------
/**
* @private
*/
_onBackgroundShapeResize() {
this._updateShapePosition();
// Get the decimal part of the shape element width.
let decimalPart = this.el.getBoundingClientRect().width % 1;
// Round to two decimal places.
decimalPart = Math.round((decimalPart + Number.EPSILON) * 100) / 100;
// If there is a decimal part. (e.g. Chrome + browser zoom enabled)
if (decimalPart > 0) {
// Compensate for the gap by giving an integer width value to the
// shape by changing its "right" and "left" positions.
let offset = (decimalPart < 0.5 ? decimalPart : decimalPart - 1) / 2;
// This never causes the horizontal scrollbar to appear because it
// only appears if the overflow to the right exceeds 0.333px.
this._updateShapePosition(offset + 'px');
}
},
});
return {
Widget: publicWidget.Widget,
Animation: Animation,
@@ -936,7 +936,16 @@ options.registry.BackgroundShape.include({
return el;
}
return _getLastPreFilterLayerElement(this.$target);
}
},
/**
* @override
*/
_removeShapeEl(shapeEl) {
this.trigger_up('widgets_stop_request', {
$target: $(shapeEl),
});
return this._super(...arguments);
},
});
options.registry.ReplaceMedia.include({