Gisle Aune
6 years ago
commit
450ff89f59
12 changed files with 5239 additions and 0 deletions
-
2.gitignore
-
17dev-server/client.css
-
8dev-server/client.js
-
15dev-server/index.html
-
13dev-server/server.js
-
4920package-lock.json
-
31package.json
-
27readme.md
-
160src/board/board.js
-
7src/board/layer.js
-
5src/index.js
-
34webpack.config.js
@ -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/"); |
|||
}); |
4920
package-lock.json
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -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"), |
|||
}, |
|||
]; |
Write
Preview
Loading…
Cancel
Save
Reference in new issue