mirror of
https://github.com/projectstorm/react-diagrams.git
synced 2025-08-26 07:51:10 +08:00
adds support for touch events, enabling touch dragging the canvas
This commit is contained in:
@ -1,4 +1,4 @@
|
||||
import { MouseEvent } from 'react';
|
||||
import { MouseEvent, TouchEvent } from 'react';
|
||||
import {
|
||||
SelectingState,
|
||||
State,
|
||||
@ -45,6 +45,16 @@ export class DefaultState extends State<DiagramEngine> {
|
||||
})
|
||||
);
|
||||
|
||||
// touch drags the canvas
|
||||
this.registerAction(
|
||||
new Action({
|
||||
type: InputType.TOUCH_START,
|
||||
fire: (event: ActionEvent<TouchEvent>) => {
|
||||
this.transitionWithEvent(new DragCanvasState(), event);
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
this.registerAction(
|
||||
new Action({
|
||||
type: InputType.MOUSE_UP,
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { MouseEvent, KeyboardEvent, WheelEvent, SyntheticEvent } from 'react';
|
||||
import { MouseEvent, KeyboardEvent, WheelEvent, TouchEvent, SyntheticEvent } from 'react';
|
||||
import { Toolkit } from '../Toolkit';
|
||||
import { CanvasEngine } from '../CanvasEngine';
|
||||
import { BaseModel } from '../core-models/BaseModel';
|
||||
@ -9,7 +9,10 @@ export enum InputType {
|
||||
MOUSE_MOVE = 'mouse-move',
|
||||
MOUSE_WHEEL = 'mouse-wheel',
|
||||
KEY_DOWN = 'key-down',
|
||||
KEY_UP = 'key-up'
|
||||
KEY_UP = 'key-up',
|
||||
TOUCH_START = 'touch-start',
|
||||
TOUCH_END = 'touch-end',
|
||||
TOUCH_MOVE = 'touch-move'
|
||||
}
|
||||
|
||||
export interface Mapping {
|
||||
@ -19,6 +22,9 @@ export interface Mapping {
|
||||
[InputType.MOUSE_WHEEL]: WheelEvent;
|
||||
[InputType.KEY_DOWN]: KeyboardEvent;
|
||||
[InputType.KEY_UP]: KeyboardEvent;
|
||||
[InputType.TOUCH_START]: TouchEvent;
|
||||
[InputType.TOUCH_END]: TouchEvent;
|
||||
[InputType.TOUCH_MOVE]: TouchEvent;
|
||||
}
|
||||
|
||||
export interface ActionEvent<Event extends SyntheticEvent = SyntheticEvent, Model extends BaseModel = BaseModel> {
|
||||
|
@ -63,7 +63,14 @@ export class ActionEventBus {
|
||||
return this.getActionsForType(InputType.MOUSE_MOVE);
|
||||
} else if (event.type === 'wheel') {
|
||||
return this.getActionsForType(InputType.MOUSE_WHEEL);
|
||||
} else if (event.type === 'touchstart') {
|
||||
return this.getActionsForType(InputType.TOUCH_START);
|
||||
} else if (event.type === 'touchend') {
|
||||
return this.getActionsForType(InputType.TOUCH_END);
|
||||
} else if (event.type === 'touchmove') {
|
||||
return this.getActionsForType(InputType.TOUCH_MOVE);
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
|
@ -7,7 +7,7 @@ export interface AbstractDisplacementStateEvent {
|
||||
displacementY: number;
|
||||
virtualDisplacementX: number;
|
||||
virtualDisplacementY: number;
|
||||
event: React.MouseEvent;
|
||||
event: React.MouseEvent | React.TouchEvent;
|
||||
}
|
||||
|
||||
export abstract class AbstractDisplacementState<E extends CanvasEngine = CanvasEngine> extends State<E> {
|
||||
@ -63,6 +63,45 @@ export abstract class AbstractDisplacementState<E extends CanvasEngine = CanvasE
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
this.registerAction(
|
||||
new Action({
|
||||
type: InputType.TOUCH_START,
|
||||
fire: (actionEvent: ActionEvent<React.TouchEvent>) => {
|
||||
const touch = actionEvent.event.touches[0];
|
||||
this.initialX = touch.clientX;
|
||||
this.initialY = touch.clientY;
|
||||
const rel = this.engine.getRelativePoint(touch.clientX, touch.clientY);
|
||||
this.initialXRelative = rel.x;
|
||||
this.initialYRelative = rel.y;
|
||||
}
|
||||
})
|
||||
);
|
||||
this.registerAction(
|
||||
new Action({
|
||||
type: InputType.TOUCH_MOVE,
|
||||
fire: (actionEvent: ActionEvent<React.TouchEvent>) => {
|
||||
const { event } = actionEvent;
|
||||
const touch = event.touches[0];
|
||||
this.fireMouseMoved({
|
||||
displacementX: touch.clientX - this.initialX,
|
||||
displacementY: touch.clientY - this.initialY,
|
||||
virtualDisplacementX: (touch.clientX - this.initialX) / (this.engine.getModel().getZoomLevel() / 100.0),
|
||||
virtualDisplacementY: (touch.clientY - this.initialY) / (this.engine.getModel().getZoomLevel() / 100.0),
|
||||
event: event
|
||||
});
|
||||
}
|
||||
})
|
||||
);
|
||||
this.registerAction(
|
||||
new Action({
|
||||
type: InputType.TOUCH_END,
|
||||
fire: (event: ActionEvent<React.TouchEvent>) => {
|
||||
// when the mouse if up, we eject this state
|
||||
this.eject();
|
||||
}
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
abstract fireMouseMoved(event: AbstractDisplacementStateEvent);
|
||||
|
@ -90,6 +90,15 @@ export class CanvasWidget extends React.Component<DiagramProps> {
|
||||
}}
|
||||
onMouseMove={(event) => {
|
||||
this.props.engine.getActionEventBus().fireAction({ event });
|
||||
}}
|
||||
onTouchStart={(event) => {
|
||||
this.props.engine.getActionEventBus().fireAction({ event });
|
||||
}}
|
||||
onTouchEnd={(event) => {
|
||||
this.props.engine.getActionEventBus().fireAction({ event });
|
||||
}}
|
||||
onTouchMove={(event) => {
|
||||
this.props.engine.getActionEventBus().fireAction({ event });
|
||||
}}>
|
||||
{model.getLayers().map((layer) => {
|
||||
return (
|
||||
|
@ -16,6 +16,9 @@ namespace S {
|
||||
export class SelectionBoxWidget extends React.Component<SelectionBoxWidgetProps> {
|
||||
render() {
|
||||
const { rect } = this.props;
|
||||
|
||||
if (!rect) return;
|
||||
|
||||
return (
|
||||
<S.Container
|
||||
style={{
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { State } from '../core-state/State';
|
||||
import { Action, ActionEvent, InputType } from '../core-actions/Action';
|
||||
import { MouseEvent } from 'react';
|
||||
import { MouseEvent, TouchEvent } from 'react';
|
||||
import { DragCanvasState } from './DragCanvasState';
|
||||
import { SelectingState } from './SelectingState';
|
||||
import { MoveItemsState } from './MoveItemsState';
|
||||
@ -28,5 +28,15 @@ export class DefaultState extends State {
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
// touch drags the canvas
|
||||
this.registerAction(
|
||||
new Action({
|
||||
type: InputType.TOUCH_START,
|
||||
fire: (event: ActionEvent<TouchEvent>) => {
|
||||
this.transitionWithEvent(new DragCanvasState(), event);
|
||||
}
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,8 @@
|
||||
import { MouseEvent, TouchEvent } from 'react';
|
||||
import { AbstractDisplacementState, AbstractDisplacementStateEvent } from '../core-state/AbstractDisplacementState';
|
||||
import { State } from '../core-state/State';
|
||||
import { SelectionLayerModel } from '../entities/selection/SelectionLayerModel';
|
||||
import { Rectangle } from '@projectstorm/geometry';
|
||||
import { Point, Rectangle } from '@projectstorm/geometry';
|
||||
import { ModelGeometryInterface } from '../core/ModelGeometryInterface';
|
||||
|
||||
export class SelectionBoxState extends AbstractDisplacementState {
|
||||
@ -26,7 +27,13 @@ export class SelectionBoxState extends AbstractDisplacementState {
|
||||
}
|
||||
|
||||
getBoxDimensions(event: AbstractDisplacementStateEvent): ClientRect {
|
||||
const rel = this.engine.getRelativePoint(event.event.clientX, event.event.clientY);
|
||||
let rel: Point;
|
||||
if (event.event instanceof MouseEvent) {
|
||||
rel = this.engine.getRelativePoint(event.event.clientX, event.event.clientY);
|
||||
} else if (event.event instanceof TouchEvent) {
|
||||
const touch = event.event.touches[0];
|
||||
rel = this.engine.getRelativePoint(touch.clientX, touch.clientY);
|
||||
}
|
||||
|
||||
return {
|
||||
left: rel.x > this.initialXRelative ? this.initialXRelative : rel.x,
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { MouseEvent } from 'react';
|
||||
import { MouseEvent, TouchEvent } from 'react';
|
||||
import {
|
||||
SelectingState,
|
||||
State,
|
||||
@ -48,5 +48,15 @@ export class DefaultDiagramState extends State<DiagramEngine> {
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
// touch drags the canvas
|
||||
this.registerAction(
|
||||
new Action({
|
||||
type: InputType.TOUCH_START,
|
||||
fire: (event: ActionEvent<TouchEvent>) => {
|
||||
this.transitionWithEvent(this.dragCanvas, event);
|
||||
}
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user