Browse Source

First commit.

master
Gisle Aune 5 years ago
commit
450ff89f59
  1. 2
      .gitignore
  2. 17
      dev-server/client.css
  3. 8
      dev-server/client.js
  4. 15
      dev-server/index.html
  5. 13
      dev-server/server.js
  6. 4920
      package-lock.json
  7. 31
      package.json
  8. 27
      readme.md
  9. 160
      src/board/board.js
  10. 7
      src/board/layer.js
  11. 5
      src/index.js
  12. 34
      webpack.config.js

2
.gitignore

@ -0,0 +1,2 @@
dist/
node_modules/

17
dev-server/client.css

@ -0,0 +1,17 @@
div#container {
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
margin: 0;
padding: 0;
overflow: hidden;
}
body, html {
margin: 0;
padding: 0;
}

8
dev-server/client.js

@ -0,0 +1,8 @@
console.log("API:", mappBoard);
document.addEventListener("DOMContentLoaded", function() {
var board = new mappBoard.Board("container");
window.addEventListener('resize', () => board.resize(window.innerWidth, window.innerHeight), false);
board.resize(window.innerWidth, window.innerHeight);
});

15
dev-server/index.html

@ -0,0 +1,15 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Mapp Test Setup</title>
<link rel="stylesheet" href="/client.css" />
<script src="/dist/mapp-board-umd.js"></script>
<script src="/client.js"></script>
</head>
<body>
<div id="container"></div>
</body>
</html>

13
dev-server/server.js

@ -0,0 +1,13 @@
const express = require("express");
const path = require("path");
const app = express();
app.get("/", express.static(path.join(__dirname, "./index.html")));
app.use("/dist", express.static(path.join(__dirname, "../dist")));
app.use(express.static(path.join(__dirname, "./")));
app.listen(8030, () => {
console.log("Listening to http://localhost:8030/");
});

4920
package-lock.json
File diff suppressed because it is too large
View File

31
package.json

@ -0,0 +1,31 @@
{
"name": "mapp-board",
"version": "0.1.0",
"description": "A canvas battle map like thing.",
"main": "dist/mapp-board-cjs.js",
"module": "src/index.js",
"scripts": {
"dev": "node ./dev-server/server.js",
"build-prod": "NODE_ENV=production webpack .",
"build": "webpack .",
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [
"map",
"mapp",
"battlemat",
"rp",
"rpg"
],
"author": "Gisle",
"license": "ISC",
"devDependencies": {
"@types/fabric": "^1.5.48",
"express": "^4.16.4",
"webpack": "^4.28.2",
"webpack-cli": "^3.1.2"
},
"dependencies": {
"fabric": "^2.4.6"
}
}

27
readme.md

@ -0,0 +1,27 @@
# mapp-board
**Mapp board is in early, early development. Contribution and issues are welcome, but it's a long way from being ready for any actual production use.**
This is a module for a canvas-based board to help you make a mapping tool for your role-playing website. It has no API, and must be controlled through settings and events.
## Using
```javascript
const mappBoard = require("mapp-board"); // Import as pre-ES6 node module
import * as mappBoard from "mapp-board"; // Import as ES6 module
// Omit both if you import as <script> tag.
document.addEventListener("DOMContentLoaded", function() {
var board = new mappBoard.Board("container");
window.addEventListener('resize', function() {
board.resize(window.innerWidth, window.innerHeight);
}, false);
board.resize(window.innerWidth, window.innerHeight);
});
```
It's an exercise to the reader to wrap it in React, angular, vue, marko or whatever library you use.
## Develop

160
src/board/board.js

@ -0,0 +1,160 @@
import { fabric } from "fabric";
fabric.perfLimitSizeTotal = 134217728;
fabric.maxCacheSideLimit = 65536;
export default class Board {
constructor(id) {
this.id = id;
this.state = {a: 32};
this.containerElement = document.getElementById(id);
if (this.containerElement == null) {
throw new Error(`Container ${this.id} not found`)
}
this.canvasElement = document.createElement("canvas");
this.containerElement.appendChild(this.canvasElement);
this.canvas = new fabric.Canvas(this.canvasElement, {backgroundColor: "#555"});
this.gridGroup = new fabric.Group();
this.canvas.add(this.gridGroup);
this.gridOptions = {
enabled: true,
size: 64,
hightlightInterval: 8,
lineColor: "#444",
highlightColor: "#333",
};
this.setupPanning();
}
destroy() {
this.canvasElement.remove();
}
resize(width, height) {
this.canvas.setHeight(height);
this.canvas.setWidth(width);
this.redrawGrid();
this.moveGrid();
this.canvas.renderAll();
}
redrawGrid() {
const {enabled, size, hightlightInterval, lineColor, highlightColor} = this.gridOptions;
for (const obj of this.gridGroup.getObjects().slice()) {
this.gridGroup.remove(obj);
}
if (!enabled) {
return;
}
const wCount = Math.ceil((this.canvas.getWidth() / this.canvas.getZoom()) / size) + (hightlightInterval * 2);
const hCount = Math.ceil((this.canvas.getHeight() / this.canvas.getZoom()) / size) + (hightlightInterval * 2);
const width2 = wCount * (size);
const height2 = hCount * (size);
this.gridGroup.set("left", 0);
this.gridGroup.set("top", 0);
this.gridGroup.set("width", width2);
this.gridGroup.set("height", height2);
this.gridGroup.set("selectable", false);
this.gridGroup.set("hoverCursor", "default");
for (let i = 0; i <= wCount; ++i) {
let x = i * size;
let line = new fabric.Line([x, 0, x, height2], {stroke: lineColor, strokeWidth: 2, selectable: false});
if (i % hightlightInterval == 0) {
line.set("stroke", highlightColor);
}
this.gridGroup.addWithUpdate(line);
}
for (let i = 0; i <= hCount; ++i) {
let y = i * size;
let line = new fabric.Line([0, y, width2, y], {stroke: lineColor, strokeWidth: 2, selectable: false});
if (i % hightlightInterval == 0) {
line.set("stroke", highlightColor);
}
this.gridGroup.addWithUpdate(line);
}
}
moveGrid() {
const size = this.gridOptions.size * this.gridOptions.hightlightInterval;
const [x, y] = this.canvas.viewportTransform.slice(4).map(n => -n);
const xOffset = (x % size) + size;
const yOffset = (y % size) + size;
this.gridGroup.set("left", x - xOffset);
this.gridGroup.set("top", y - yOffset);
this.gridGroup.setCoords();
console.log(this.gridGroup);
}
setupPanning() {
const parent = this;
this.canvas.on('mouse:wheel', ({e}) => {
if (e.shiftKey === false) {
return;
}
let delta = e.deltaY;
let zoom = this.canvas.getZoom();
zoom = zoom - delta/1000;
if (zoom > 5) {
zoom = 5;
}
if (zoom < 0.25) {
zoom = 0.25;
}
this.canvas.setZoom(zoom);
this.redrawGrid();
this.moveGrid();
e.preventDefault();
e.stopPropagation();
})
this.canvas.on('mouse:down', function(opt) {
var evt = opt.e;
if (evt.shiftKey === true) {
this.isDragging = true;
this.selection = false;
this.lastPosX = evt.clientX;
this.lastPosY = evt.clientY;
}
});
this.canvas.on('mouse:move', function(opt) {
if (this.isDragging) {
var e = opt.e;
this.viewportTransform[4] += e.clientX - this.lastPosX;
this.viewportTransform[5] += e.clientY - this.lastPosY;
this.requestRenderAll();
this.lastPosX = e.clientX;
this.lastPosY = e.clientY;
parent.moveGrid();
}
});
this.canvas.on('mouse:up', function(opt) {
this.isDragging = false;
this.selection = true;
});
}
}

7
src/board/layer.js

@ -0,0 +1,7 @@
import { fabric } from "fabric";
export default class Layer {
constructor() {
this.group = new fabric.Group([], {});
}
}

5
src/index.js

@ -0,0 +1,5 @@
import Board from "./board/board";
export {
Board,
}

34
webpack.config.js

@ -0,0 +1,34 @@
var path = require("path");
var mode = process.env.NODE_ENV || "development";
module.exports = [
// CJS (Node.JS, React, etc...)
{
entry: "./src/index.js",
mode: mode,
output: {
path: path.resolve(__dirname, "dist"),
filename: "mapp-board-cjs.js",
library: "",
libraryTarget: "commonjs",
},
watch: (mode === "development"),
externals: {
fabric: 'fabric',
},
},
// UMD (Browser)
{
entry: "./src/index.js",
mode: mode,
output: {
path: path.resolve(__dirname, "dist"),
filename: "mapp-board-umd.js",
library: "mappBoard",
libraryTarget: "umd",
},
watch: (mode === "development"),
},
];
Loading…
Cancel
Save