react svg con
const {
withStateHandlers,
} = Recompose;
console.clear();
const CANVAS_WIDTH = 640;
const CANVAS_HEIGHT = 480;
const CIRCLE_RADIUS = 48;
////////////////////////////////////////
//
// Drag Snap
//
interface DraggableState {
isDown: boolean;
posX: number;
posY: number;
screenX: number;
screenY: number;
}
interface DraggableHandler {
onMouseDown: (e: MouseEvent) => DraggableState;
onMouseUp: (e: MouseEvent) => DraggableState;
onMouseMove: (e: MouseEvent) => DraggableState;
}
interface DraggableProps {
initX: number;
initY: number;
color: string;
}
const DraggableCircleBase: React.StatelessComponent<DraggableState & DraggableHandler & DraggableProps> =
({posX, posY, color, onMouseDown, onMouseMove, onMouseUp}) => (
<circle
cx={posX}
cy={posY}
r={CIRCLE_RADIUS}
stroke={color}
fill={'light' + color}
strokeWidth="3"
onMouseDown={onMouseDown}
onMouseMove={onMouseMove}
onMouseUp={onMouseUp}
/>
);
const enhanceWithDraggable = withStateHandlers<DragSnapState, DragSnapHandler, DraggableProps>(
({ initX, initY }) => ({
isDown: false,
posX: initX,
posY: initY,
screenX: 0,
screenY: 0
}), {
onMouseDown: (state: DraggableState) => (e: MouseEvent) => {
return {
...state,
isDown: true,
screenX: e.screenX,
screenY: e.screenY
}
},
onMouseMove: (state: DraggableState) => (e: MouseEvent) => {
if (!state.isDown) {
return { ...state }
}
const shiftX = e.screenX - state.screenX;
const shiftY = e.screenY - state.screenY;
return {
...state,
posX: state.posX + shiftX,
posY: state.posY + shiftY,
screenX: e.screenX,
screenY: e.screenY,
};
},
onMouseUp: (state: DraggableState, props: DraggableProps) => (e: MouseEvent) => {
return { ...state, isDown: false, screenX: 0, screenY: 0 }
},
}
);
const DraggableCircle = enhanceWithDraggable(DraggableCircleBase);
const SVGDrag: React.StatelessComponent<React.Props<{}>> = () => (
<div>
<div>
<svg style={{ width: CANVAS_WIDTH + 'px', height: CANVAS_HEIGHT + 'px', border: '1px solid silver' }}>
<DraggableCircle initX={CANVAS_WIDTH * .25} initY={CANVAS_HEIGHT / 2} color="blue" />
<DraggableCircle initX={CANVAS_WIDTH * .5} initY={CANVAS_HEIGHT / 2} color="pink" />
<DraggableCircle initX={CANVAS_WIDTH * .75} initY={CANVAS_HEIGHT / 2} color="green" />
</svg>
</div>
</div>
);
// render both components
ReactDOM.render(
(<div>
<h2>React SVG drag example</h2>
<SVGDrag />
</div>),
document.querySelector('#root'));