Skip to content

Commit

Permalink
feat: refactor constraints
Browse files Browse the repository at this point in the history
  • Loading branch information
yanzhuoran committed Sep 10, 2024
1 parent 2d0372e commit 4cd5962
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 92 deletions.
108 changes: 21 additions & 87 deletions packages/semi-foundation/resizable/group/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { getItemDirection } from '../groupConstants';
import BaseFoundation, { DefaultAdapter } from '../../base/foundation';
import { ResizeStartCallback, ResizeCallback } from "../singleConstants";
import { getPixelSize } from '../groupConstants';
import { getPixelSize, judgeConstraint } from '../groupConstants';
export interface ResizeHandlerAdapter<P = Record<string, any>, S = Record<string, any>> extends DefaultAdapter<P, S> {
getHandler: () => HTMLElement;
getHandlerIndex: () => number;
Expand Down Expand Up @@ -108,89 +108,27 @@ export class ResizeGroupFoundation<P = Record<string, any>, S = Record<string, a
}
}

updateConstraints = () => {
// this item constaint last / next handler
let lastConstraints = new Map(), nextConstraints = new Map();
if (this.direction === 'horizontal') {
const parentWidth = this.groupRef.getBoundingClientRect().width;
for (let i = 0; i < this._adapter.getItemCount(); i++) {
const child = this._adapter.getItem(i);

let itemMin = this._adapter.getItemMin(i)
const minWidth = itemMin ? getPixelSize(itemMin, parentWidth) : 0;
const rect = child.getBoundingClientRect();
let { borderLeftWidth, borderRightWidth } = this.window.getComputedStyle(child);
let leftWidth = Number(borderLeftWidth.replace('px', ''));
let rightWidth = Number(borderRightWidth.replace('px', ''));
let borderWidth = leftWidth + rightWidth + this.itemMinSize;

let nextLeftConstraint = rect.left + minWidth + borderWidth, nextRightConstraint = undefined;
let lastRightConstraint = rect.right - minWidth - borderWidth, lastLeftConstraint = undefined;
let itemMax = this._adapter.getItemMax(i)
if (itemMax) {
const maxWidth = getPixelSize(itemMax, parentWidth);
nextRightConstraint = rect.left + maxWidth - borderWidth;
lastLeftConstraint = rect.right - maxWidth + borderWidth;
}

lastConstraints.set(i - 1, [lastLeftConstraint, lastRightConstraint]);
nextConstraints.set(i, [nextLeftConstraint, nextRightConstraint]);
}
} else {
const parentHeight = this.groupRef.getBoundingClientRect().height;
for (let i = 0; i < this._adapter.getItemCount(); i++) {
const child = this._adapter.getItem(i);

let itemMin = this._adapter.getItemMin(i)
const minHeight = itemMin ? getPixelSize(itemMin, parentHeight) : 0;
const rect = child.getBoundingClientRect();
let { borderTopWidth, borderBottomWidth } = this.window.getComputedStyle(child);
let topWidth = Number(borderTopWidth.replace('px', ''));
let bottomWidth = Number(borderBottomWidth.replace('px', ''));
let borderWidth = (topWidth + bottomWidth) + this.itemMinSize;

let nextTopConstraint = rect.top + minHeight + borderWidth, nextBottomConstraint = undefined;
let lastBottomConstraint = rect.bottom - minHeight - borderWidth, lastTopConstraint = undefined;
let itemMax = this._adapter.getItemMax(i)
if (itemMax) {
const maxHeight = getPixelSize(itemMax, parentHeight);
nextBottomConstraint = rect.top + maxHeight - borderWidth;
lastTopConstraint = rect.bottom - maxHeight + borderWidth;
}

lastConstraints.set(i - 1, [lastTopConstraint, lastBottomConstraint]);
nextConstraints.set(i, [nextTopConstraint, nextBottomConstraint]);

}
}

for (let i = 0; i < this._adapter.getHandlerCount(); i++) {
// lastBack and nextFront wont be undefined
let [lastFront, lastBack] = lastConstraints.get(i);
let [nextFront, nextBack] = nextConstraints.get(i);
let front = lastFront === undefined ? nextFront : Math.max(lastFront, nextFront);
let back = nextBack === undefined ? lastBack : Math.min(lastBack, nextBack);
this.constraintsMap.set(i, [front, back]);
}
}

onResizeStart = (handlerIndex: number, e: MouseEvent) => { // handler ref
let { clientX, clientY } = e;
let lastItem = this._adapter.getItem(handlerIndex), nextItem = this._adapter.getItem(handlerIndex + 1);
let handler = this._adapter.getHandler(handlerIndex);
let lastOffset: number, nextOffset: number;
if (this.direction === 'horizontal') {
this.itemMinSize = this._adapter.getHandler(handlerIndex).offsetWidth;

this.itemMinSize = handler.offsetWidth;
lastOffset = clientX - handler.offsetLeft;
nextOffset = handler.offsetLeft + handler.offsetWidth - clientX;
} else if (this.direction === 'vertical') {
this.itemMinSize = this._adapter.getHandler(handlerIndex).offsetHeight;
this.itemMinSize = handler.offsetHeight;
}
this.updateConstraints();
this.setState({
isResizing: true,
originalPosition: {
x: clientX,
y: clientY,
lastItemSize: this.direction === 'horizontal' ? lastItem.offsetWidth : lastItem.offsetHeight,
nextItemSize: this.direction === 'horizontal' ? nextItem.offsetWidth : nextItem.offsetHeight,
lastOffset,
nextOffset,
},
curHandler: handlerIndex,
curConstraint: this.constraintsMap.get(handlerIndex),
Expand All @@ -215,20 +153,9 @@ export class ResizeGroupFoundation<P = Record<string, any>, S = Record<string, a
return
}
const { curHandler, originalPosition, curConstraint } = state;
const { x: initX, y: initY, lastItemSize, nextItemSize } = originalPosition;
const { clientX, clientY } = e;

if (curConstraint) {
if (this.direction === 'horizontal') {
if (clientX <= curConstraint[0] || clientX >= curConstraint[1]) {
return
}
} else if (this.direction === 'vertical') {
if (clientY <= curConstraint[0] || clientY >= curConstraint[1]) {
return
}
}
}
let { x: initX, y: initY, lastItemSize, nextItemSize, lastOffset, nextOffset } = originalPosition;
console.log(lastItemSize, nextItemSize, lastOffset, nextOffset)
let { clientX, clientY } = e;

const props = this.getProps();
const { direction } = props;
Expand All @@ -237,8 +164,15 @@ export class ResizeGroupFoundation<P = Record<string, any>, S = Record<string, a
if (direction === 'horizontal') {
let delta = clientX - initX;
let parentWidth = this._adapter.getGroupRef().getBoundingClientRect().width;
lastItem.style.width = (lastItemSize + delta) / parentWidth * 100 + '%';
nextItem.style.width = (nextItemSize - delta) / parentWidth * 100 + '%';
let lastNewSize = lastItemSize + delta, nextNewSize = nextItemSize - delta;
let lastFlag = judgeConstraint(lastNewSize, lastItem.style.minWidth, lastItem.style.maxWidth, parentWidth),
nextFlag = judgeConstraint(nextNewSize, nextItem.style.minWidth, nextItem.style.maxWidth, parentWidth);
console.log(lastNewSize, lastItem.style.minWidth, lastItem.style.maxWidth, lastFlag,
nextNewSize ,nextItem.style.minWidth, nextItem.style.maxWidth, nextFlag);
if (lastFlag && nextFlag) {
lastItem.style.width = (lastItemSize + delta) / parentWidth * 100 + '%';
nextItem.style.width = (nextItemSize - delta) / parentWidth * 100 + '%';
}
} else if (direction === 'vertical') {
let delta = clientY - initY;
let parentHeight = this._adapter.getGroupRef().getBoundingClientRect().height;
Expand Down
12 changes: 12 additions & 0 deletions packages/semi-foundation/resizable/groupConstants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,16 @@ export const getPixelSize = (size: string, parentSize: number): number => {
}

return typeof size === 'undefined' ? size : Number(size);
}

export const judgeConstraint = (newSize: number, min: string, max: string, parentSize: number) => {
const minSize = getPixelSize(min, parentSize);
const maxSize = getPixelSize(max, parentSize);
if (newSize <= minSize) {
return false;
}
if (newSize >= maxSize) {
return false;
}
return true;
}
2 changes: 1 addition & 1 deletion packages/semi-ui/resizable/_story/resizable.stories.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,7 @@ export const Group_horizontal = () => {
<ResizeHandler></ResizeHandler>
<ResizeItem
style={{ backgroundColor: 'rgba(var(--semi-grey-1), 1)', border: 'black 5px solid' }}
defaultSize={'60px'}
defaultSize={'300px'}
onChange={() => { setText('resizing') }}
>
<div style={{ marginLeft: '20%' }}>
Expand Down
27 changes: 23 additions & 4 deletions packages/semi-ui/resizable/group/resizeGroup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ export interface ResizeGroupState {
y: number;
lastItemSize: number;
nextItemSize: number;
lastOffset: number;
nextOffset: number;
};
curHandler: number;
curConstraint: [number, number]
Expand All @@ -46,6 +48,8 @@ class ResizeGroup extends BaseComponent<ResizeGroupProps, ResizeGroupState> {
y: 0,
lastItemSize: 0,
nextItemSize: 0,
lastOffset: 0,
nextOffset: 0,
},
curHandler: null,
curConstraint: null
Expand Down Expand Up @@ -74,7 +78,21 @@ class ResizeGroup extends BaseComponent<ResizeGroupProps, ResizeGroupState> {
let totalSizePercent = 0;
let undefineLoc = []
let parentSize = this.props.direction === 'horizontal' ? this.groupRef.current.offsetWidth : this.groupRef.current.offsetHeight;
for (let i = 0; i < this.itemDefaultSizeList.length; i++) {
for (let i = 0; i < this.itemRefs.length; i++) {
const child = this.itemRefs[i].current;
let minSize = this.itemMinMap.get(i), maxSize = this.itemMaxMap.get(i);
let minSizePercent = minSize ? getPixelSize(minSize, parentSize) / parentSize * 100 : 0,
maxSizePercent = maxSize ? getPixelSize(maxSize, parentSize) / parentSize * 100 : 100;
if (minSizePercent > maxSizePercent) {
console.warn('min size bigger than max size');
}
if (this.props.direction === 'horizontal') {
child.style.minWidth = minSize ?? '0%';
child.style.maxWidth = maxSize ?? '100%';
} else {
child.style.minHeight = minSize ?? '0%';
child.style.maxHeight = maxSize ?? '100%';
}
if (this.itemDefaultSizeList[i]) {
let itemSizePercent: number;
if (this.itemDefaultSizeList[i].endsWith('%')) {
Expand All @@ -83,11 +101,12 @@ class ResizeGroup extends BaseComponent<ResizeGroupProps, ResizeGroupState> {
itemSizePercent = parseInt(this.itemDefaultSizeList[i].slice(0, -2)) / parentSize * 100;
}
totalSizePercent += itemSizePercent;
let minSizePercent = this.itemMinMap.get(i) ? getPixelSize(this.itemMinMap.get(i), parentSize) / parentSize * 100 : 0,
maxSizePercent = this.itemMaxMap.get(i) ? getPixelSize(this.itemMaxMap.get(i), parentSize) / parentSize * 100 : 100;


if (itemSizePercent < minSizePercent) {
console.warn('item size smaller than min size');
} else if (itemSizePercent > maxSizePercent) {
}
if (itemSizePercent > maxSizePercent) {
console.warn('item size bigger than max size');
}
} else {
Expand Down

0 comments on commit 4cd5962

Please sign in to comment.