Merge branch 'master' of gitea.iwm-tuebingen.de:IWMBrowser/iwmlib
This commit is contained in:
@@ -12,6 +12,7 @@ import Button from './button.js'
|
||||
import ButtonGroup from './buttongroup.js'
|
||||
import Scrollview from './scrollview.js'
|
||||
import Slider from './slider.js'
|
||||
import Stylus from './stylus.js'
|
||||
import Switch from './switch.js'
|
||||
import Popup from './popup.js'
|
||||
import PopupMenu from './popupmenu.js'
|
||||
@@ -44,6 +45,7 @@ window.Button = Button
|
||||
window.ButtonGroup = ButtonGroup
|
||||
window.Scrollview = Scrollview
|
||||
window.Slider = Slider
|
||||
window.Stylus = Stylus
|
||||
window.Switch = Switch
|
||||
window.Popup = Popup
|
||||
window.PopupMenu = PopupMenu
|
||||
|
||||
@@ -0,0 +1,149 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
|
||||
<title>PIXI Stylus</title>
|
||||
|
||||
<link rel="stylesheet" href="../3rdparty/highlight/styles/default.css">
|
||||
<link rel="stylesheet" href="../../css/doctest.css">
|
||||
|
||||
<script src="../3rdparty/highlight/highlight.pack.js"></script>
|
||||
|
||||
<script src="../../dist/iwmlib.3rdparty.js"></script>
|
||||
<script src="../../dist/iwmlib.js"></script>
|
||||
<script src="../../dist/iwmlib.pixi.js"></script>
|
||||
</head>
|
||||
|
||||
<body onload="Doctest.run()">
|
||||
<h1>Stylus</h1>
|
||||
<p>The Stylus class extends the PIXI.Graphics class and allows to draw into
|
||||
a graphics object. Select the pen tool in the following example app and draw into the canvas.
|
||||
</p>
|
||||
<canvas id="canvas" style="border: 1px solid gray; width: 640px; height: 480px;" class="interactive"></canvas>
|
||||
<p>
|
||||
What you should see: A blank sytlus canvas.
|
||||
</p>
|
||||
<script class="doctest">
|
||||
class StylusApp extends PIXIApp {
|
||||
|
||||
sceneFactory() {
|
||||
return new Stylus(this.renderer)
|
||||
}
|
||||
|
||||
setup() {
|
||||
let buttonColor = 0x666666
|
||||
super.setup()
|
||||
|
||||
this.tools = new ButtonGroup({
|
||||
type: 'checkbox',
|
||||
margin: 0,
|
||||
x: 16,
|
||||
y: 16,
|
||||
fill: buttonColor,
|
||||
buttons: [{
|
||||
icon: 'edit',
|
||||
iconColorActive: 0xFFFF00,
|
||||
action: (event, button) => this.toggleEditMode()
|
||||
},
|
||||
{
|
||||
icon: 'undo',
|
||||
action: (event, button) => this.undo(button)
|
||||
},
|
||||
{
|
||||
icon: 'redo',
|
||||
action: (event, button) => this.redo(button)
|
||||
},
|
||||
{
|
||||
icon: 'delete',
|
||||
action: (event, button) => this.clear(button)
|
||||
}
|
||||
]
|
||||
})
|
||||
this.scene.addChild(this.tools)
|
||||
|
||||
let defaults = {
|
||||
icon: 'brightness_1',
|
||||
action: (event, button) => this.selectColor(button),
|
||||
fillAlpha: 0,
|
||||
strokeAlpha: 0,
|
||||
fillActiveAlpha: 0,
|
||||
strokeActiveAlpha: 0
|
||||
}
|
||||
|
||||
this.palette = new ButtonGroup({
|
||||
type: "radio",
|
||||
x: 200,
|
||||
y: 16,
|
||||
margin: 0,
|
||||
strokeAlpha: 0,
|
||||
fill: buttonColor,
|
||||
buttons: [
|
||||
Object.assign({}, defaults, {
|
||||
iconColor: 0x111111,
|
||||
iconColorActive: 0x111111
|
||||
}), // tooltip: "Black",
|
||||
Object.assign({}, defaults, {
|
||||
iconColor: 0xFFFF00,
|
||||
iconColorActive: 0xFFFF00
|
||||
}), // tooltip: "Yellow",
|
||||
Object.assign({}, defaults, {
|
||||
iconColor: 0x00FF00,
|
||||
iconColorActive: 0x00FF00
|
||||
}), // tooltip: "Green",
|
||||
Object.assign({}, defaults, {
|
||||
iconColor: 0xFF00FF,
|
||||
iconColorActive: 0xFF00FF
|
||||
}) // tooltip: "Violet",
|
||||
]
|
||||
})
|
||||
this.scene.addChild(this.palette)
|
||||
this.scene.interactive = false
|
||||
}
|
||||
|
||||
toggleEditMode() {
|
||||
this.scene.interactive = !this.scene.interactive
|
||||
|
||||
console.log("this.scene.interactive")
|
||||
}
|
||||
|
||||
selectColor(button) {
|
||||
this.scene.color = button.opts.iconColor
|
||||
}
|
||||
|
||||
undo(button) {
|
||||
this.scene.undo()
|
||||
setTimeout(() => {
|
||||
button.active = false
|
||||
}, 200)
|
||||
}
|
||||
|
||||
redo(button) {
|
||||
this.scene.redo()
|
||||
setTimeout(() => {
|
||||
button.active = false
|
||||
}, 200)
|
||||
}
|
||||
|
||||
clear(button) {
|
||||
this.scene.clearAll()
|
||||
setTimeout(() => {
|
||||
button.active = false
|
||||
}, 200)
|
||||
}
|
||||
}
|
||||
|
||||
const app = new StylusApp({
|
||||
view: canvas,
|
||||
width: 640,
|
||||
height: 480,
|
||||
autoResize: false
|
||||
})
|
||||
window.app = app
|
||||
app.setup()
|
||||
app.run()
|
||||
|
||||
|
||||
</script>
|
||||
</body>
|
||||
Regular → Executable
+48
-24
@@ -1,3 +1,5 @@
|
||||
/* eslint-disable no-undef */
|
||||
/* eslint-disable no-console */
|
||||
import Events from '../events.js'
|
||||
import { Angle } from '../utils.js'
|
||||
|
||||
@@ -84,6 +86,7 @@ export default class Stylus extends PIXI.Graphics {
|
||||
captureEvents = true,
|
||||
acceptMouseEvents = true } = {}) {
|
||||
super()
|
||||
this.activePointers = 0
|
||||
this.wantedWidth = width
|
||||
this.wantedHeight = height
|
||||
this.backgroundAlpha = backgroundAlpha
|
||||
@@ -99,6 +102,7 @@ export default class Stylus extends PIXI.Graphics {
|
||||
this.undoCommandStack = []
|
||||
this.strokes = []
|
||||
this.stroke = []
|
||||
this.minStrokeLength = 4
|
||||
if (captureEvents)
|
||||
this.registerEventHandler(acceptMouseEvents)
|
||||
this.drawBackground()
|
||||
@@ -156,46 +160,65 @@ export default class Stylus extends PIXI.Graphics {
|
||||
}
|
||||
}
|
||||
|
||||
singlePointer() {
|
||||
return this.activePointers == 1
|
||||
}
|
||||
|
||||
registerEventHandler() {
|
||||
window.addEventListener('keydown', (e) => {
|
||||
switch (e.keyCode) {
|
||||
case 38: // up arrow
|
||||
this.tiltX += 5
|
||||
break
|
||||
case 40: // down arrow
|
||||
this.tiltX -= 5
|
||||
break
|
||||
case 37: // left arrow
|
||||
this.tiltY -= 5
|
||||
break
|
||||
case 39: // right arrow
|
||||
this.tiltY += 5
|
||||
break
|
||||
case 38: // up arrow
|
||||
this.tiltX += 5
|
||||
break
|
||||
case 40: // down arrow
|
||||
this.tiltX -= 5
|
||||
break
|
||||
case 37: // left arrow
|
||||
this.tiltY -= 5
|
||||
break
|
||||
case 39: // right arrow
|
||||
this.tiltY += 5
|
||||
break
|
||||
}
|
||||
if (this.debug) console.log("keydown", e.keyCode, this.tiltX, this.tiltY)
|
||||
if (this.debug) console.log('keydown', e.keyCode, this.tiltX, this.tiltY)
|
||||
})
|
||||
|
||||
this.on('pointerdown', (e) => {
|
||||
if (this.debug) console.log("pointerdown", e)
|
||||
if (this.eventInside(e))
|
||||
this.startStroke(this.toStroke(e))
|
||||
if (this.debug) console.log('pointerdown', e)
|
||||
if (this.eventInside(e)) {
|
||||
this.activePointers += 1
|
||||
if (this.singlePointer()) {
|
||||
this.startStroke(this.toStroke(e))
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
this.on('pointermove', (e) => {
|
||||
if (Events.isPointerDown(e.data.originalEvent) || this.isStylusPointer(e) || this.isStylusTouch(e)) {
|
||||
if (this.debug) console.log("pointermove", e, this.eventInside(e))
|
||||
if (this.eventInside(e))
|
||||
if (this.debug) console.log('pointermove', e, this.eventInside(e))
|
||||
if (this.eventInside(e) && this.singlePointer())
|
||||
this.moveStroke(this.toStroke(e))
|
||||
}
|
||||
})
|
||||
this.on('pointerup', (e) => {
|
||||
if (this.debug) console.log("pointerup", e)
|
||||
if (this.eventInside(e))
|
||||
this.endStroke(this.toStroke(e))
|
||||
if (this.eventInside(e)) {
|
||||
if (this.activePointers > 0) {
|
||||
this.activePointers -= 1
|
||||
this.endStroke(this.toStroke(e))
|
||||
}
|
||||
}
|
||||
if (this.debug) console.log('pointerup', this.activePointers)
|
||||
})
|
||||
this.on('pointerleave', (e) => {
|
||||
if (this.activePointers > 0) {
|
||||
this.activePointers -= 1
|
||||
}
|
||||
this.endStroke(this.toStroke(e))
|
||||
})
|
||||
this.on('pointercancel', (e) => {
|
||||
if (this.activePointers > 0) {
|
||||
this.activePointers -= 1
|
||||
}
|
||||
this.endStroke(this.toStroke(e))
|
||||
})
|
||||
}
|
||||
@@ -228,7 +251,7 @@ export default class Stylus extends PIXI.Graphics {
|
||||
for (let child of this.children) {
|
||||
let r = child.getBounds()
|
||||
if (r.contains(local.x, local.y)) {
|
||||
console.log("Child touched")
|
||||
console.log('Child touched')
|
||||
return false
|
||||
}
|
||||
}
|
||||
@@ -237,7 +260,7 @@ export default class Stylus extends PIXI.Graphics {
|
||||
if (local.y < 0 || local.y > this.wantedHeight)
|
||||
return false
|
||||
event.stopPropagation()
|
||||
if (this.debug) console.log("stopPropagation", event)
|
||||
// if (this.debug) console.log('stopPropagation', event)
|
||||
if (event.data.originalEvent.claimedByScatter) {
|
||||
return false
|
||||
}
|
||||
@@ -271,8 +294,9 @@ export default class Stylus extends PIXI.Graphics {
|
||||
this.redraw()
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
endStroke(info) {
|
||||
if (this.stroke.length > 1) {
|
||||
if (this.stroke.length >= this.minStrokeLength) {
|
||||
let cmd = new StrokeCommand(this.stroke)
|
||||
cmd.do(this)
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
|
||||
|
||||
https://mattdesl.svbtle.com/drawing-lines-is-hard
|
||||
http://perfectionkills.com/exploring-canvas-drawing-techniques/
|
||||
|
||||
|
||||
|
||||
https://github.com/mattdesl/polyline-normals
|
||||
|
||||
var path = [ [0, 122], [0, 190], [90, 190] ]
|
||||
|
||||
//get the normals as a closed loop
|
||||
var normals = getNormals(path, true)
|
||||
@@ -1,73 +0,0 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
|
||||
<!-- disable zooming -->
|
||||
<meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1" />
|
||||
<title>Stylus Functional Tests</title>
|
||||
<style media="screen">
|
||||
|
||||
html, body {
|
||||
margin:0;
|
||||
padding:0;
|
||||
|
||||
height:100%;
|
||||
width: 100%;
|
||||
/* See http://stackoverflow.com/questions/9280258/prevent-body-scrolling-but-allow-overlay-scrolling */
|
||||
position:fixed;
|
||||
overflow: hidden;
|
||||
font-size: 18px;
|
||||
background:gray;
|
||||
font-family:arial,sans-serif;
|
||||
color:#FFF;
|
||||
-webkit-user-select: none;
|
||||
-khtml-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
-webkit-overflow-scrolling: auto;
|
||||
user-select: none;
|
||||
touch-action: manipulation;
|
||||
}
|
||||
|
||||
.site {
|
||||
display: flex;
|
||||
min-height: 100%;
|
||||
flex-direction: column;
|
||||
}
|
||||
/*
|
||||
|
||||
.interactive {
|
||||
-ms-content-zooming: none;
|
||||
touch-action: none;
|
||||
}
|
||||
*/
|
||||
|
||||
main {
|
||||
flex-grow: 1;
|
||||
overflow: hidden;
|
||||
position:relative
|
||||
}
|
||||
|
||||
.container {
|
||||
position:absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
min-height: 100%;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script src=".././3rdparty/all.js"></script>
|
||||
<script src="../../lib/bootstrap.js"></script>
|
||||
</head>
|
||||
<body class="site" oncontextmenu="return false" >
|
||||
<main id="main" class="container">
|
||||
<canvas id="canvas" width="100%" height="100%" style="position: absolute; z-index:10000; user-select: none;">
|
||||
Get a better browser, bro.
|
||||
</canvas>
|
||||
</main>
|
||||
<script>
|
||||
Bootstrap.import('./main.js')
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,90 +0,0 @@
|
||||
import PIXIApp from '../../lib/pixi/app.js'
|
||||
import Button from '../../lib/pixi/button.js'
|
||||
import ButtonGroup from '../../lib/pixi/buttongroup.js'
|
||||
import Stylus from './stylus.js'
|
||||
|
||||
class StylusApp extends PIXIApp {
|
||||
|
||||
sceneFactory() {
|
||||
return new Stylus(this.renderer)
|
||||
}
|
||||
|
||||
setup() {
|
||||
let buttonColor = 0x666666
|
||||
super.setup()
|
||||
|
||||
this.tools = new ButtonGroup({
|
||||
type: 'checkbox',
|
||||
margin: 0,
|
||||
x: 16,
|
||||
y: 16,
|
||||
fill: buttonColor,
|
||||
buttons: [{icon: 'edit',
|
||||
iconColorActive: 0xFFFF00,
|
||||
action: (event, button) => this.toggleEditMode() },
|
||||
{icon: 'undo',
|
||||
action: (event, button) => this.undo(button) },
|
||||
{icon: 'redo',
|
||||
action: (event, button) => this.redo(button) },
|
||||
{icon: 'delete',
|
||||
action: (event, button) => this.clear(button) }
|
||||
]
|
||||
})
|
||||
this.scene.addChild(this.tools)
|
||||
|
||||
let defaults = { icon: 'brightness_1',
|
||||
action: (event, button) => this.selectColor(button),
|
||||
fillAlpha: 0,
|
||||
strokeAlpha: 0,
|
||||
fillActiveAlpha: 0,
|
||||
strokeActiveAlpha: 0}
|
||||
|
||||
this.palette = new ButtonGroup( {
|
||||
type: "radio",
|
||||
x: 200,
|
||||
y: 16,
|
||||
margin: 0,
|
||||
strokeAlpha: 0,
|
||||
fill: buttonColor,
|
||||
buttons: [
|
||||
Object.assign({}, defaults, { iconColor: 0x111111,
|
||||
iconColorActive: 0x111111}), // tooltip: "Black",
|
||||
Object.assign({}, defaults, { iconColor: 0xFFFF00,
|
||||
iconColorActive: 0xFFFF00}), // tooltip: "Yellow",
|
||||
Object.assign({}, defaults, { iconColor: 0x00FF00,
|
||||
iconColorActive:0x00FF00}), // tooltip: "Green",
|
||||
Object.assign({}, defaults, { iconColor: 0xFF00FF,
|
||||
iconColorActive:0xFF00FF}) // tooltip: "Violet",
|
||||
]
|
||||
})
|
||||
this.scene.addChild(this.palette)
|
||||
}
|
||||
|
||||
selectColor(button) {
|
||||
this.scene.color = button.opts.iconColor
|
||||
}
|
||||
|
||||
undo(button) {
|
||||
this.scene.undo()
|
||||
setTimeout(() => {
|
||||
button.active = false}, 200)
|
||||
}
|
||||
|
||||
redo(button) {
|
||||
this.scene.redo()
|
||||
setTimeout(() => {
|
||||
button.active = false}, 200)
|
||||
}
|
||||
|
||||
clear(button) {
|
||||
this.scene.clearAll()
|
||||
setTimeout(() => {
|
||||
button.active = false}, 200)
|
||||
}
|
||||
}
|
||||
|
||||
const app = new StylusApp({ view: canvas })
|
||||
window.app = app
|
||||
app.setup()
|
||||
app.run()
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 6.7 KiB |
Reference in New Issue
Block a user