First commit.
This commit is contained in:
@@ -0,0 +1,2 @@
|
|||||||
|
dist/
|
||||||
|
node_modules/
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -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);
|
||||||
|
});
|
||||||
@@ -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>
|
||||||
@@ -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/");
|
||||||
|
});
|
||||||
Generated
+4920
File diff suppressed because it is too large
Load Diff
@@ -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"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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
|
||||||
|
|
||||||
@@ -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;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
import { fabric } from "fabric";
|
||||||
|
|
||||||
|
export default class Layer {
|
||||||
|
constructor() {
|
||||||
|
this.group = new fabric.Group([], {});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
import Board from "./board/board";
|
||||||
|
|
||||||
|
export {
|
||||||
|
Board,
|
||||||
|
}
|
||||||
@@ -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"),
|
||||||
|
},
|
||||||
|
];
|
||||||
Reference in New Issue
Block a user