Draggable Canvas & Items With Redux

by Peter Jang

HTML

<script src="https://unpkg.com/redux@latest/dist/redux.min.js"></script>
<body>
  <canvas></canvas>
</body>

CSS

canvas {
  background: lightgray;
}

JavaScript

var canvas = document.querySelector("canvas");
var ctx = canvas.getContext("2d");

var initialState = {
  canvas: { x: 0, y: 0 },
  items: [
    { id: 1, x: 10, y: 10, width: 50, height: 50, color: 'red' },
    { id: 2, x: 30, y: 30, width: 50, height: 50, color: 'blue' }
  ],
  xDragging: null,
  yDragging: null,
  draggingItemId: null
};

var reducer = function(state, action) {
  if (typeof state === 'undefined') {
    return initialState;
  }
  switch (action.type) {
    case 'TRANSLATE_CANVAS_START':
      return {
        canvas: state.canvas,
        items: state.items,
        xDragging: action.xDragging,
        yDragging: action.yDragging,
        draggingItemId: null
      };
    case 'TRANSLATE_CANVAS':
      return {
        canvas: {
          x: state.canvas.x + action.xDragging - state.xDragging,
          y: state.canvas.y + action.yDragging - state.yDragging
        },
        items: state.items,
        xDragging: action.xDragging,
        yDragging: action.yDragging,
        draggingItemId: null
      };
    case 'TRANSLATE_CANVAS_END':
      return {
        canvas: state.canvas,
        items: state.items,
        xDragging: null,
        yDragging: null,
        draggingItemId: null
      };
    case 'TRANSLATE_ITEM_START':
      return {
        canvas: state.canvas,
        items: state.items,
        xDragging: action.xDragging,
        yDragging: action.yDragging,
        draggingItemId: action.id
      };
    case 'TRANSLATE_ITEM':
      var newItems = state.items.map(function(item) {
        if (item.id === state.draggingItemId) {
          return {
            id: item.id,
            x: item.x + action.xDragging - state.xDragging,
            y: item.y + action.yDragging - state.yDragging,
            width: item.width,
            height: item.height,
            color: item.color
          };
        } else {
          return item;
        }
      });
      return {
        canvas: state.canvas,
        items: newItems,
       ...