feat: @idraw/core implement select area

This commit is contained in:
chenshenhai 2021-06-27 14:36:21 +08:00
parent 83ecc22a7e
commit 50191464b7
8 changed files with 105 additions and 24 deletions

View file

@ -209,6 +209,10 @@ class Context implements TypeContext {
this._ctx.textBaseline = baseline;
}
setGlobalAlpha(alpha: number): void {
this._ctx.globalAlpha = alpha;
}
private _doSize(num: number) {
return this._opts.devicePixelRatio * num;
}
@ -224,6 +228,7 @@ class Context implements TypeContext {
const _y = (y - scrollY) / scale;
return this._doSize(_y);
}
}

View file

@ -30,6 +30,7 @@ enum Mode {
NULL = 'null',
SELECT_ELEMENT = 'select-element',
SELECT_ELEMENT_WRAPPER_DOT = 'select-element-wrapper-dot',
SELECT_AREA = 'select-area',
}
enum CursorStatus {
@ -264,18 +265,25 @@ class Core {
const [uuid, direction] = this[_helper].isPointInElementWrapperDot(point);
if (uuid && direction) {
// Controll Element-Wrapper
this[_mode] = Mode.SELECT_ELEMENT_WRAPPER_DOT;
this[_selectedDotDirection] = direction;
this[_selectedUUID] = uuid;
} else {
const [index, uuid] = this[_element].isPointInElement(point, this[_data]);
this.selectElement(index, { useMode: true });
if (typeof uuid === 'string' && this[_coreEvent].has('screenSelectElement')) {
this[_coreEvent].trigger(
'screenSelectElement',
{ index, uuid, element: deepClone(this[_data].elements?.[index])}
);
this[_emitChangeScreen]();
if (index >= 0) {
// Controll Element
this.selectElement(index, { useMode: true });
if (typeof uuid === 'string' && this[_coreEvent].has('screenSelectElement')) {
this[_coreEvent].trigger(
'screenSelectElement',
{ index, uuid, element: deepClone(this[_data].elements?.[index])}
);
this[_emitChangeScreen]();
}
} else {
// Controll Area
this[_mode] = Mode.SELECT_AREA;
}
}
this.draw();
@ -284,6 +292,7 @@ class Core {
private [_handleMoveStart](point: TypePoint): void {
this[_prevPoint] = point;
const uuid = this[_selectedUUID];
if (typeof uuid === 'string' && this[_coreEvent].has('screenMoveElementStart')) {
this[_coreEvent].trigger('screenMoveElementStart', {
index: this[_element].getElementIndex(this[_data], uuid),
@ -291,11 +300,12 @@ class Core {
x: point.x,
y: point.y
});
} else if (this[_mode] === Mode.SELECT_AREA) {
this[_helper].startSelectArea(point);
}
}
private [_handleMove](point: TypePoint): void {
if (typeof this[_selectedUUID] === 'string') {
if (this[_mode] === Mode.SELECT_ELEMENT) {
this[_dragElement](this[_selectedUUID] as string, point, this[_prevPoint]);
@ -305,6 +315,9 @@ class Core {
this[_transfromElement](this[_selectedUUID] as string, point, this[_prevPoint], this[_selectedDotDirection] as TypeHelperWrapperDotDirection);
this[_cursorStatus] = CursorStatus.DRAGGING;
}
} else if (this[_mode] === Mode.SELECT_AREA) {
this[_helper].changeSelectArea(point);
this.draw();
}
this[_prevPoint] = point;
}
@ -334,10 +347,13 @@ class Core {
}
this[_emitChangeData]();
}
} else if (this[_mode] === Mode.SELECT_AREA) {
this[_helper].clearSelectedArea();
}
this[_selectedUUID] = null;
this[_prevPoint] = null;
this[_cursorStatus] = CursorStatus.NULL;
this[_mode] = Mode.NULL;
}
private [_handleHover](point: TypePoint): void {

View file

@ -11,6 +11,7 @@ const { istype, color } = util;
export function clearContext(ctx: TypeContext) {
ctx.setFillStyle('rgb(0 0 0 / 0%)');
ctx.setStrokeStyle('rgb(0 0 0 / 0%)');
ctx.setLineDash([]);
}
export function drawBgColor(ctx: TypeContext, color: string) {

View file

@ -14,6 +14,7 @@ import { drawSVG } from './svg';
import { drawText } from './text';
import {
drawElementWrapper,
drawAreaWrapper,
// drawDisplayContextScrollWrapper,
} from './wrapper';
@ -32,6 +33,9 @@ export function drawContext(
if (typeof data.bgColor === 'string' && isColorStr(data.bgColor)) {
drawBgColor(ctx, data.bgColor);
}
drawAreaWrapper(ctx, helperConfig);
if (!(data.elements.length > 0)) {
return;
}

View file

@ -57,14 +57,25 @@ export function drawElementWrapper(ctx: TypeContext, config: TypeHelperConfig) {
}
// export function drawDisplayContextScrollWrapper(displayCtx: TypeContext, config: TypeHelperConfig) {
// // console.log('config?.displayContextScrollWrapper = ', config?.displayContextScrollWrapper);
// // if (!config?.displayContextScrollWrapper) {
// // return;
// // }
// // draw scroll x-line
// // draw scroll y-line
// }
export function drawAreaWrapper(ctx: TypeContext, config: TypeHelperConfig) {
if (!config?.selectedAreaWrapper) {
return;
}
const wrapper = config.selectedAreaWrapper;
if (wrapper && wrapper.w > 0 && wrapper.h > 0) {
clearContext(ctx);
// draw wrapper's box
ctx.beginPath();
ctx.setLineDash([]);
ctx.setLineWidth(wrapper.lineWidth);
ctx.setStrokeStyle(wrapper.color);
ctx.moveTo(wrapper.x, wrapper.y);
ctx.lineTo(wrapper.x + wrapper.w, wrapper.y);
ctx.lineTo(wrapper.x + wrapper.w, wrapper.y + wrapper.h);
ctx.lineTo(wrapper.x, wrapper.y + wrapper.h);
ctx.lineTo(wrapper.x, wrapper.y);
ctx.stroke();
ctx.closePath();
}
}

View file

@ -17,12 +17,17 @@ import { rotateContext, } from './transform';
const { deepClone } = util.data;
const areaLineWidth = 2;
const areaColor = '#2ab6f1';
export class Helper implements TypeHelper {
private _helperConfig: TypeHelperConfig;
private _coreConfig: TypeConfigStrict;
private _ctx: TypeContext;
private _board: Board;
private _areaStart: TypePoint = { x: 0, y: 0};
private _areaEnd: TypePoint = { x: 0, y: 0};
constructor(board: Board, config: TypeConfigStrict) {
this._board = board;
@ -89,6 +94,37 @@ export class Helper implements TypeHelper {
return [uuid, direction];
}
startSelectArea(p: TypePoint) {
this._areaStart = p;
}
changeSelectArea(p: TypePoint) {
this._areaEnd = p;
this._calcSelectedArea();
}
clearSelectedArea() {
this._areaStart = {x: 0, y: 0};
this._areaStart = {x: 0, y: 0};
this._calcSelectedArea();
}
private _calcSelectedArea() {
const start = this._areaStart;
const end = this._areaEnd;
this._helperConfig.selectedAreaWrapper = {
x: Math.min(start.x, end.x),
y: Math.min(start.y, end.y),
w: Math.abs(end.x - start.x),
h: Math.abs(end.y - start.y),
startPoint: {x: start.x, y: start.y},
endPoint: {x: end.x, y: end.y},
lineWidth: areaLineWidth,
color: areaColor,
}
}
private _updateElementIndex(data: TypeData) {
this._helperConfig.elementIndexMap = {};
data.elements.forEach((elem: TypeElement<keyof TypeElemDesc>, i) => {

View file

@ -45,7 +45,8 @@ interface TypeContext {
drawImage(image: CanvasImageSource, dx: number, dy: number, dw: number, dh: number): void;
drawImage(image: CanvasImageSource, sx: number, sy: number, sw: number, sh: number, dx: number, dy: number, dw: number, dh: number): void;
createPattern(image: CanvasImageSource, repetition: string | null): CanvasPattern | null
createPattern(image: CanvasImageSource, repetition: string | null): CanvasPattern | null;
setGlobalAlpha(alpha: number): void;
}
export {

View file

@ -5,6 +5,16 @@ import { TypePoint } from './board';
type TypeHelperConfig = {
elementIndexMap: {[key: string]: number},
selectedAreaWrapper?: {
x: number;
y: number;
w: number;
h: number;
startPoint: TypePoint;
endPoint: TypePoint;
lineWidth: number;
color: string;
};
selectedElementWrapper?: {
uuid: string;
dotSize: number;
@ -19,10 +29,6 @@ type TypeHelperConfig = {
left: TypePoint,
rotate: TypePoint,
},
// limit: {
// minWidth: number;
// minHeight: number;
// },
lineDash: number[];
lineWidth: number;
color: string;
@ -39,6 +45,7 @@ type TypeHelperConfig = {
}
}
type TypeHelperUpdateOpts = {
width: number;
height: number;