Early work on Mapp, will move to Github or Gitlab if something becomes of it.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

160 lines
4.1 KiB

5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
  1. import { fabric } from "fabric";
  2. fabric.perfLimitSizeTotal = 134217728;
  3. fabric.maxCacheSideLimit = 65536;
  4. export default class Board {
  5. constructor(id, {grid} = {grid: {}}) {
  6. this.id = id;
  7. this.state = {};
  8. this.containerElement = document.getElementById(id);
  9. if (this.containerElement == null) {
  10. throw new Error(`Container "${this.id}" not found`)
  11. }
  12. this.canvasElement = document.createElement("canvas");
  13. this.containerElement.appendChild(this.canvasElement);
  14. this.canvas = new fabric.Canvas(this.canvasElement, {backgroundColor: "#555"});
  15. this.gridGroup = new fabric.Group();
  16. this.canvas.add(this.gridGroup);
  17. this.gridOptions = {
  18. ...(grid || {}),
  19. enabled: true,
  20. size: 64,
  21. hightlightInterval: 8,
  22. lineColor: "#444",
  23. highlightColor: "#333",
  24. };
  25. this.setupPanning();
  26. }
  27. destroy() {
  28. this.canvasElement.remove();
  29. }
  30. resize(width, height) {
  31. this.canvas.setHeight(height);
  32. this.canvas.setWidth(width);
  33. this.redrawGrid();
  34. this.moveGrid();
  35. this.canvas.renderAll();
  36. }
  37. redrawGrid() {
  38. const {enabled, size, hightlightInterval, lineColor, highlightColor} = this.gridOptions;
  39. for (const obj of this.gridGroup.getObjects().slice()) {
  40. this.gridGroup.remove(obj);
  41. }
  42. if (!enabled) {
  43. return;
  44. }
  45. const wCount = Math.ceil((this.canvas.getWidth() / this.canvas.getZoom()) / size) + (hightlightInterval * 2);
  46. const hCount = Math.ceil((this.canvas.getHeight() / this.canvas.getZoom()) / size) + (hightlightInterval * 2);
  47. const width = wCount * (size);
  48. const height = hCount * (size);
  49. this.gridGroup.set("left", 0);
  50. this.gridGroup.set("top", 0);
  51. this.gridGroup.set("width", width);
  52. this.gridGroup.set("height", height);
  53. this.gridGroup.set("selectable", false);
  54. this.gridGroup.set("hoverCursor", "default");
  55. for (let i = 0; i <= wCount; ++i) {
  56. let x = i * size;
  57. let line = new fabric.Line([x, 0, x, height], {stroke: lineColor, strokeWidth: 2, selectable: false});
  58. if (i % hightlightInterval == 0) {
  59. line.set("stroke", highlightColor);
  60. }
  61. this.gridGroup.addWithUpdate(line);
  62. }
  63. for (let i = 0; i <= hCount; ++i) {
  64. let y = i * size;
  65. let line = new fabric.Line([0, y, width, y], {stroke: lineColor, strokeWidth: 2, selectable: false});
  66. if (i % hightlightInterval == 0) {
  67. line.set("stroke", highlightColor);
  68. }
  69. this.gridGroup.addWithUpdate(line);
  70. }
  71. }
  72. moveGrid() {
  73. const size = this.gridOptions.size * this.gridOptions.hightlightInterval;
  74. const [x, y] = this.canvas.viewportTransform.slice(4).map(n => -n);
  75. const xOffset = (x % size) + size;
  76. const yOffset = (y % size) + size;
  77. this.gridGroup.set("left", x - xOffset);
  78. this.gridGroup.set("top", y - yOffset);
  79. this.gridGroup.setCoords();
  80. }
  81. setupPanning() {
  82. const parent = this;
  83. this.canvas.on('mouse:wheel', ({e}) => {
  84. return; // TODO: Fix bugs with the grid when zoomed in/out.
  85. if (e.shiftKey === false) {
  86. return;
  87. }
  88. let delta = e.deltaY;
  89. let zoom = this.canvas.getZoom();
  90. zoom = zoom - delta/1000;
  91. if (zoom > 5) {
  92. zoom = 5;
  93. }
  94. if (zoom < 0.25) {
  95. zoom = 0.25;
  96. }
  97. this.canvas.setZoom(zoom);
  98. this.redrawGrid();
  99. this.moveGrid();
  100. e.preventDefault();
  101. e.stopPropagation();
  102. });
  103. this.canvas.on('mouse:down', function(opt) {
  104. var evt = opt.e;
  105. if (evt.shiftKey === true) {
  106. this.isDragging = true;
  107. this.selection = false;
  108. this.lastPosX = evt.clientX;
  109. this.lastPosY = evt.clientY;
  110. }
  111. });
  112. this.canvas.on('mouse:move', function(opt) {
  113. if (this.isDragging) {
  114. var e = opt.e;
  115. this.viewportTransform[4] += e.clientX - this.lastPosX;
  116. this.viewportTransform[5] += e.clientY - this.lastPosY;
  117. this.requestRenderAll();
  118. this.lastPosX = e.clientX;
  119. this.lastPosY = e.clientY;
  120. parent.moveGrid();
  121. }
  122. });
  123. this.canvas.on('mouse:up', function(opt) {
  124. this.isDragging = false;
  125. this.selection = true;
  126. });
  127. }
  128. }