Skip to content

Commit b3e61df

Browse files
authored
Fix resize for percentages (#6568)
1 parent e13f3c1 commit b3e61df

File tree

2 files changed

+48
-30
lines changed

2 files changed

+48
-30
lines changed

packages/core/src/commands/view/Resize.ts

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,11 @@ export interface ConvertPxToUnitProps {
6666
el: HTMLElement;
6767
valuePx: number;
6868
unit?: LiteralUnion<ConvertUnitsToPx, string>;
69+
elComputedStyle?: CSSStyleDeclaration;
70+
/**
71+
* If true, the conversion will be done as height (requred for % units).
72+
*/
73+
isHeight?: boolean;
6974
/**
7075
* @default 3
7176
*/
@@ -116,6 +121,7 @@ export default {
116121
const el = elOpts || componentView?.el || component.getEl()!;
117122
const resizeEventOpts = { component, el };
118123
let modelToStyle: StyleableModel;
124+
let elComputedStyle: CSSStyleDeclaration;
119125

120126
const toggleBodyClass = (method: string, e: any, opts: any) => {
121127
const docs = opts.docs;
@@ -133,26 +139,28 @@ export default {
133139
posFetcher: canvasView.getElementPos.bind(canvasView),
134140
mousePosFetcher: Canvas.getMouseRelativePos.bind(Canvas),
135141
docs: [document],
136-
onStart(ev, opts) {
142+
updateOnMove: true,
143+
skipUnitAdjustments: true,
144+
onStart: (ev, opts) => {
137145
onStart(ev, opts);
138146
const { el, config, resizer } = opts;
139147
const { keyHeight, keyWidth, currentUnit, keepAutoHeight, keepAutoWidth } = config;
140148
toggleBodyClass('add', ev, opts);
141149
modelToStyle = em.Styles.getModelToStyle(component);
142-
const computedStyle = getComputedStyle(el);
150+
elComputedStyle = getComputedStyle(el);
143151
const modelStyle = modelToStyle.getStyle();
144152
const rectStart = { ...resizer.startDim! };
145153

146154
let currentWidth = modelStyle[keyWidth!] as string;
147155
config.autoWidth = keepAutoWidth && currentWidth === 'auto';
148156
if (isNaN(parseFloat(currentWidth))) {
149-
currentWidth = computedStyle[keyWidth as any];
157+
currentWidth = elComputedStyle[keyWidth as any];
150158
}
151159

152160
let currentHeight = modelStyle[keyHeight!] as string;
153161
config.autoHeight = keepAutoHeight && currentHeight === 'auto';
154162
if (isNaN(parseFloat(currentHeight))) {
155-
currentHeight = computedStyle[keyHeight as any];
163+
currentHeight = elComputedStyle[keyHeight as any];
156164
}
157165

158166
const valueWidth = parseFloat(currentWidth);
@@ -188,8 +196,7 @@ export default {
188196
options.afterStart?.();
189197
},
190198

191-
// Update all positioned elements (eg. component toolbar)
192-
onMove(event, opts) {
199+
onMove: (event, opts) => {
193200
onMove(event, opts);
194201
const { resizer } = opts;
195202
const eventProps: ComponentResizeEventMoveProps = {
@@ -203,7 +210,7 @@ export default {
203210
editor.trigger(ComponentsEvents.resize, { ...eventProps, type: 'move' });
204211
},
205212

206-
onEnd(event, opts) {
213+
onEnd: (event, opts) => {
207214
onEnd(event, opts);
208215
toggleBodyClass('remove', event, opts);
209216
const { resizer } = opts;
@@ -238,6 +245,7 @@ export default {
238245
? 'auto'
239246
: this.convertPxToUnit({
240247
el,
248+
elComputedStyle,
241249
valuePx: width,
242250
unit: unitWidth,
243251
});
@@ -248,8 +256,10 @@ export default {
248256
? 'auto'
249257
: this.convertPxToUnit({
250258
el,
259+
elComputedStyle,
251260
valuePx: rect.h,
252261
unit: unitHeight,
262+
isHeight: true,
253263
});
254264
}
255265

@@ -274,7 +284,8 @@ export default {
274284
event,
275285
style,
276286
updateStyle,
277-
convertPxToUnit: (props: Omit<ConvertPxToUnitProps, 'el'>) => this.convertPxToUnit({ el, ...props }),
287+
convertPxToUnit: (props: Omit<ConvertPxToUnitProps, 'el'>) =>
288+
this.convertPxToUnit({ el, elComputedStyle, ...props }),
278289
delta: resizer.delta!,
279290
pointer: resizer.currentPos!,
280291
};
@@ -304,7 +315,7 @@ export default {
304315
},
305316

306317
convertPxToUnit(props: ConvertPxToUnitProps): string {
307-
const { el, valuePx, unit, dpi = 96, roundDecimals = 3 } = props;
318+
const { el, valuePx, unit, dpi = 96, roundDecimals = 3, isHeight, elComputedStyle } = props;
308319
const win = el.ownerDocument.defaultView;
309320
const winWidth = win?.innerWidth || 1;
310321
const winHeight = window.innerHeight || 1;
@@ -344,7 +355,11 @@ export default {
344355
break;
345356
}
346357
case ConvertUnitsToPx.perc: {
347-
const parentSize = el.parentElement?.offsetWidth || 1;
358+
const { parentElement, offsetParent } = el;
359+
const parentEl = elComputedStyle?.position === 'absolute' ? (offsetParent as HTMLElement) : parentElement;
360+
const parentWidth = parentEl?.offsetWidth || 1;
361+
const parentHeight = parentEl?.offsetHeight || 1;
362+
const parentSize = isHeight ? parentHeight : parentWidth;
348363
valueResult = (valuePx / parentSize) * 100;
349364
break;
350365
}

packages/core/src/utils/Resizer.ts

Lines changed: 23 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,12 @@ export interface ResizerOptions {
236236
*/
237237
updateOnMove?: boolean;
238238

239+
/**
240+
* By default, the resizer will try to perform adjustments on some units (eg. %), with this option
241+
* you can skip this behavior.
242+
*/
243+
skipUnitAdjustments?: boolean;
244+
239245
docs?: Document[];
240246
}
241247

@@ -694,11 +700,12 @@ export default class Resizer {
694700
const deltaY = data.delta!.y;
695701
const parentW = this.parentDim!.w;
696702
const parentH = this.parentDim!.h;
697-
const unitWidth = this.opts.unitWidth;
698-
const unitHeight = this.opts.unitHeight;
703+
const { unitWidth, unitHeight, skipUnitAdjustments } = opts;
699704
const parentRect = this.getParentRect();
700-
const startW = unitWidth === '%' ? (startDim.w / 100) * parentW : startDim.w;
701-
const startH = unitHeight === '%' ? (startDim.h / 100) * parentH : startDim.h;
705+
const isWidthPercent = unitWidth === '%' && !skipUnitAdjustments;
706+
const isHeightPercent = unitHeight === '%' && !skipUnitAdjustments;
707+
const startW = isWidthPercent ? (startDim.w / 100) * parentW : startDim.w;
708+
const startH = isHeightPercent ? (startDim.h / 100) * parentH : startDim.h;
702709

703710
const box: RectDim = {
704711
t: startDim.t - parentRect.top,
@@ -711,37 +718,33 @@ export default class Resizer {
711718

712719
var attr = data.handlerAttr!;
713720
if (~attr.indexOf('r')) {
714-
value =
715-
unitWidth === '%'
716-
? normalizeFloat(((startW + deltaX * step) / parentW) * 100, 0.01)
717-
: normalizeFloat(startW + deltaX * step, step);
721+
value = isWidthPercent
722+
? normalizeFloat(((startW + deltaX * step) / parentW) * 100, 0.01)
723+
: normalizeFloat(startW + deltaX * step, step);
718724
value = Math.max(minDim, value);
719725
maxDim && (value = Math.min(maxDim, value));
720726
box.w = value;
721727
}
722728
if (~attr.indexOf('b')) {
723-
value =
724-
unitHeight === '%'
725-
? normalizeFloat(((startH + deltaY * step) / parentH) * 100, 0.01)
726-
: normalizeFloat(startH + deltaY * step, step);
729+
value = isHeightPercent
730+
? normalizeFloat(((startH + deltaY * step) / parentH) * 100, 0.01)
731+
: normalizeFloat(startH + deltaY * step, step);
727732
value = Math.max(minDim, value);
728733
maxDim && (value = Math.min(maxDim, value));
729734
box.h = value;
730735
}
731736
if (~attr.indexOf('l')) {
732-
value =
733-
unitWidth === '%'
734-
? normalizeFloat(((startW - deltaX * step) / parentW) * 100, 0.01)
735-
: normalizeFloat(startW - deltaX * step, step);
737+
value = isWidthPercent
738+
? normalizeFloat(((startW - deltaX * step) / parentW) * 100, 0.01)
739+
: normalizeFloat(startW - deltaX * step, step);
736740
value = Math.max(minDim, value);
737741
maxDim && (value = Math.min(maxDim, value));
738742
box.w = value;
739743
}
740744
if (~attr.indexOf('t')) {
741-
value =
742-
unitHeight === '%'
743-
? normalizeFloat(((startH - deltaY * step) / parentH) * 100, 0.01)
744-
: normalizeFloat(startH - deltaY * step, step);
745+
value = isHeightPercent
746+
? normalizeFloat(((startH - deltaY * step) / parentH) * 100, 0.01)
747+
: normalizeFloat(startH - deltaY * step, step);
745748
value = Math.max(minDim, value);
746749
maxDim && (value = Math.min(maxDim, value));
747750
box.h = value;

0 commit comments

Comments
 (0)