phpsmarter
3/28/2018 - 12:20 AM

hoc-svg-typescrpt

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'));