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