Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 18 additions & 1 deletion packages/plugin-selector/src/selector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,20 @@ interface HightLightRect {
transformHandler: (...args: any) => any;
}

let TRANSFORM_CHANGE_STR = [
'widthChange',
'heightChange',
'scaleXChange',
'scaleYChange',
'skewXChange',
'skewYChange',
'rotationChange',
'offsetXChange',
'offsetYChange',
'transformsEnabledChange',
'strokeWidthChange',
];

export class Selector {
public app: App;
public selected: Map<number | string, KonvaNode>;
Expand Down Expand Up @@ -179,6 +193,7 @@ export class Selector {
private setHightRect(...nodes: KonvaNode[]) {
this.hightLightRects = nodes.reduce((hightRects, node) => {
const rect = new Konva.Rect({
name: `${node._id}_height_rect`,
stroke: this.hightLightConfig.stroke,
strokeWidth: this.hightLightConfig.strokeWidth,
dash: this.hightLightConfig.dash,
Expand All @@ -191,7 +206,9 @@ export class Selector {
const transformHandler = () =>
requestAnimationFrame(() => this.calculateNodeRect(node, rect, this.hightLightConfig.padding ?? 0));

node.on('dragmove transform xChange yChange', transformHandler);
node.on('absoluteTransformChange', transformHandler);

node.on(TRANSFORM_CHANGE_STR.join(' '), transformHandler);

hightRects.set(node.id(), {
rect,
Expand Down
58 changes: 27 additions & 31 deletions packages/tools/src/text/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,47 +60,43 @@ export const createTextarea = (app: App, textNode: Konva.Text, onUpdated: () =>
textNode.show();
}

function setTextareaWidth(newWidth: number) {
newWidth = Math.max(textarea.value.length * textNode.fontSize(), newWidth);

//TODO: The platform detection should be a generic function.
const isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
const isFirefox = navigator.userAgent.toLowerCase().indexOf('firefox') > -1;
if (isSafari || isFirefox) {
newWidth = Math.ceil(newWidth);
}

const isEdge = document.DOCUMENT_NODE || /Edge/.test(navigator.userAgent);
if (isEdge) {
newWidth += 1;
}
textarea.style.width = newWidth + 'px';
}

textarea.addEventListener('keydown', function (e: KeyboardEvent) {
e.stopPropagation();
if (e.key === 'Enter' && !e.shiftKey) {
if (textarea.value.trim().length >= 1) {
textNode.text(textarea.value);
} else {
app.remove(textNode);
}
removeTextarea();
onUpdated();
}
if (e.key === 'Escape') {
removeTextarea();
}
const scale = textNode.getAbsoluteScale().x;
setTextareaWidth(textNode.width() * scale - textNode.padding() * 2 + 20);
textarea.style.height = 'auto';
textarea.style.height = textarea.scrollHeight + textNode.fontSize() + 'px';
});

textarea.addEventListener('input', () => {
let text = textarea.value.replace(/\n/g, '<br/>'); // 将换行符替换为<br/>标签,以便正确测量宽度
let tempDiv = document.createElement('div');
tempDiv.innerHTML = text;
tempDiv.style.position = 'absolute';
tempDiv.style.visibility = 'hidden';
tempDiv.style.whiteSpace = 'pre-wrap'; // 保持文本的换行
document.body.appendChild(tempDiv);
const newWidth = tempDiv.offsetWidth + 10;
textarea.style.width = newWidth * textNode.scaleX() + 'px'; // 设置宽度为文本实际宽度
document.body.removeChild(tempDiv);

let lineHeight = parseFloat(getComputedStyle(textarea).lineHeight);
let rows = textarea.value.split('\n').length;
textarea.style.height = 'auto'; // 重置高度以便重新计算
const newHeight = lineHeight * rows;
textarea.style.height = newHeight + 'px';
textNode.width(newWidth);
textNode.height(newHeight / textNode.scaleY());
});

function handleOutsideClick(e: MouseEvent) {
if (e.target !== textarea) {
textNode.text(textarea.value);
if (textarea.value.trim().length >= 1) {
textNode.text(textarea.value);
} else {
app.remove(textNode);
}
removeTextarea();
onUpdated();
}
}
setTimeout(() => {
Expand Down
4 changes: 1 addition & 3 deletions packages/utils/src/base-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@ import { EventArgs, EventBus } from './event';

type Method = (...args: any[]) => any;

export interface Middleware {
(args: any[], next: Method): any;
}
export type Middleware = (args: any[], next: Method) => any;

export class BaseService<T extends EventArgs = EventArgs> extends EventBus<T> {
constructor() {
Expand Down
4 changes: 1 addition & 3 deletions packages/utils/src/files.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,9 +106,7 @@ export const isXmlDocument = (file: File): boolean => {
return /^(?:application|text)\/(?:xml|xhtml\+xml)$/.test(file.type);
};

export interface FileHandler {
(fileRender: FileReader): void;
}
export type FileHandler = (fileRender: FileReader) => void;

export const readeFile = <T extends string | ArrayBuffer | null>(fileHandler: FileHandler): Promise<T> => {
const reader = new FileReader();
Expand Down
106 changes: 106 additions & 0 deletions packages/utils/src/func.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
export interface ThrottleWrapper {
(...args: any[]): void;
cancel: () => void;
}

export type DebounceWrapper = (...args: any[]) => void;

export const emptyFn = (): any => undefined;

/**
* 阻塞函数
*
* @param ms
* @returns
*/
export const sleep = (ms: number): Promise<void> =>
new Promise((resolve) => {
const timer = setTimeout(() => {
clearTimeout(timer);
resolve();
}, ms);
});

/**
* 函数柯里化
*
* @param fun
* @returns
*/
export function curryFunction(fun: Function): Function {
return function curried(this: any, ...args: any[]) {
if (args.length >= fun.length) {
return fun.apply(this, args);
} else {
return function (this: any, ...args1: any[]) {
return curried.apply(this, args.concat(args1));
};
}
};
}

/**
* 函数节流
*
* @param callback
* @param delay
* @returns
*/
export function throttle(callback: Function, delay: number): ThrottleWrapper {
let lastExec: number = 0;
let timerId: any = undefined;
let canceled: boolean = false;

const wrapper: ThrottleWrapper = function (this: any, ...args: any[]) {
if (canceled) {
return;
}
const elapsed = Date.now() - lastExec;

const exec = () => {
lastExec = Date.now();
callback.apply(this, args);
};

if (timerId) {
clearTimeout(timerId);
timerId = undefined;
}

if (elapsed > delay) {
exec();
} else {
timerId = setTimeout(exec, delay - elapsed);
}
};

wrapper.cancel = () => {
timerId && clearTimeout(timerId);
lastExec = 0;
timerId = undefined;
canceled = true;
};

return wrapper;
}

/**
* 函数防抖
*
* @param callback
* @param delay
* @returns
*/
export function debounce(callback: Function, delay: number): DebounceWrapper {
let timerId: any = undefined;
return function (this: any, ...args: any[]) {
if (!timerId) {
callback.apply(this, args);
} else {
clearTimeout(timerId);
}
timerId = setTimeout(() => {
timerId = undefined;
}, delay);
};
}
4 changes: 4 additions & 0 deletions packages/utils/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ export * from './string';

export * from './uid';

export * from './os';

export * from './func';

export const toLine = (name: string = '') => name.replace(/\B([A-Z])/g, '-$1').toLowerCase();

export function replacePropertyWithValue(obj: Record<string | number | symbol, any>, value: any, newValue: any) {
Expand Down
Loading