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