cm-chessboard 5.5.0 → 5.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -1
- package/examples/extensions/chessboard-render-video-extension.html +50 -0
- package/examples/styles/examples.css +2 -0
- package/examples/styles/examples.css.map +1 -1
- package/examples/styles/examples.scss +3 -0
- package/index.html +2 -1
- package/package.json +3 -2
- package/src/cm-chessboard/extensions/render-video/RenderVideo.js +94 -0
- package/src/cm-chessboard/model/Extension.js +1 -0
- package/src/cm-chessboard/view/PositionAnimationsQueue.js +17 -0
package/README.md
CHANGED
|
@@ -20,7 +20,8 @@ aspects of chess games.
|
|
|
20
20
|
|
|
21
21
|
- [Accessibility Extension](https://shaack.com/projekte/cm-chessboard/examples/extensions/chessboard-accessibility-extension.html)
|
|
22
22
|
- [Arrows Extension](https://shaack.com/projekte/cm-chessboard/examples/extensions/chessboard-arrows-extension.html) (by [@barakmich](https://github.com/barakmich))
|
|
23
|
-
- [PromotionDialog Extension](https://shaack.com/projekte/cm-chessboard/examples/extensions/chessboard-promotion-dialog-extension.html)
|
|
23
|
+
- [PromotionDialog Extension](https://shaack.com/projekte/cm-chessboard/examples/extensions/chessboard-promotion-dialog-extension.html)
|
|
24
|
+
- [RenderVideo](https://shaack.com/projekte/cm-chessboard/examples/extensions/chessboard-render-video-extension.html) 🆕
|
|
24
25
|
|
|
25
26
|
## Demo and repository
|
|
26
27
|
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<title>cm-chessboard</title>
|
|
6
|
+
<meta name="viewport" content="width=device-width, user-scalable=yes, initial-scale=1.0"/>
|
|
7
|
+
<link rel="stylesheet" href="../styles/examples.css"/>
|
|
8
|
+
<link rel="stylesheet" href="../../assets/styles/cm-chessboard.css"/>
|
|
9
|
+
</head>
|
|
10
|
+
<body>
|
|
11
|
+
<h1><a href="../..">cm-chessboard</a></h1>
|
|
12
|
+
<h2>Example: RenderVideo extension</h2>
|
|
13
|
+
<p>Works in Chrome.</p>
|
|
14
|
+
<div class="board board-small" id="board"></div>
|
|
15
|
+
<video id="videoOut" controls="controls"></video>
|
|
16
|
+
<br style="clear: both"/>
|
|
17
|
+
|
|
18
|
+
<script type="module">
|
|
19
|
+
import {RenderVideo} from "../../src/cm-chessboard/extensions/render-video/RenderVideo.js"
|
|
20
|
+
import {Chessboard} from "../../src/cm-chessboard/Chessboard.js"
|
|
21
|
+
import {FEN} from "../../src/cm-chessboard/model/Position.js"
|
|
22
|
+
|
|
23
|
+
const boardElement = document.getElementById("board")
|
|
24
|
+
const chessboard = new Chessboard(boardElement, {
|
|
25
|
+
position: FEN.start,
|
|
26
|
+
sprite: {url: "../../assets/images/chessboard-sprite.svg"},
|
|
27
|
+
extensions:
|
|
28
|
+
[{
|
|
29
|
+
class: RenderVideo,
|
|
30
|
+
props: {}
|
|
31
|
+
}]
|
|
32
|
+
})
|
|
33
|
+
chessboard.recorderStart()
|
|
34
|
+
setTimeout(() => {
|
|
35
|
+
chessboard.movePiece("e2", "e4", true).then(() => {
|
|
36
|
+
chessboard.movePiece("e7", "e5", true).then(() => {
|
|
37
|
+
setTimeout(() => {
|
|
38
|
+
const url = chessboard.recorderStop()
|
|
39
|
+
const video = document.getElementById("videoOut")
|
|
40
|
+
video.src = url
|
|
41
|
+
}, 100)
|
|
42
|
+
|
|
43
|
+
})
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
}, 500)
|
|
47
|
+
|
|
48
|
+
</script>
|
|
49
|
+
</body>
|
|
50
|
+
</html>
|
|
@@ -5,5 +5,5 @@
|
|
|
5
5
|
"examples.scss"
|
|
6
6
|
],
|
|
7
7
|
"names": [],
|
|
8
|
-
"mappings": "AASA,AAAA,IAAI,CAAC;EACH,KAAK,EAPG,IAAI;EAQZ,gBAAgB,EATL,IAAI;EAUf,OAAO,EAAE,IAAI;EACb,MAAM,EAAE,CAAC;EACT,WAAW,EAAE,4BAA4B;EACzC,WAAW,EAAE,GAAG;EAChB,SAAS,EATC,IAAI,GAcf;EAZD,AASE,IATE,CASF,CAAC,CAAC;IACA,SAAS,EAZD,IAAI,GAab;;AAGH,AAAA,CAAC,CAAC;EACA,KAAK,EAxBA,OAAO,GAiCb;EAVD,AAGE,CAHD,CAGG,OAAO,CAAC;IACR,KAAK,EAAE,OAAO,GACf;EALH,AAOE,CAPD,CAOG,KAAK,CAAC;IACN,KAAK,EA9BI,OAAO,GA+BjB;;AAGH,AAAA,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;EACP,UAAU,EAAE,CAAC;EACb,SAAS,EAAE,MAAgB;EAC3B,KAAK,EAlCE,OAAO,GAmCf;;AAED,AAAA,EAAE,CAAC;EACD,aAAa,EAAE,IAAI,GACpB;;AAED,AAAA,EAAE,CAAC;EACD,aAAa,EAAE,IAAI;EACnB,SAAS,EAAE,MAAgB;EAC3B,KAAK,EA5CE,OAAO,GA6Cf;;AAED,AAAA,GAAG,CAAC;EACF,WAAW,EAAE,wBAAwB;EACrC,SAAS,EAAE,GAAG;EACd,gBAAgB,EAjDA,IAAI;EAkDpB,KAAK,EAjDA,IAAI;EAkDT,OAAO,EAAE,GAAG;EACZ,QAAQ,EAAE,IAAI,GACf;;AAED,AAAA,GAAG,AAAA,MAAM,CAAC;EACR,KAAK,EAAE,IAAI;EACX,SAAS,EAAE,KAAK;EAChB,KAAK,EAAE,kBAAkB;EACzB,YAAY,EAAE,IAAI;EAClB,aAAa,EAAE,IAAI,
|
|
8
|
+
"mappings": "AASA,AAAA,IAAI,CAAC;EACH,KAAK,EAPG,IAAI;EAQZ,gBAAgB,EATL,IAAI;EAUf,OAAO,EAAE,IAAI;EACb,MAAM,EAAE,CAAC;EACT,WAAW,EAAE,4BAA4B;EACzC,WAAW,EAAE,GAAG;EAChB,SAAS,EATC,IAAI,GAcf;EAZD,AASE,IATE,CASF,CAAC,CAAC;IACA,SAAS,EAZD,IAAI,GAab;;AAGH,AAAA,CAAC,CAAC;EACA,KAAK,EAxBA,OAAO,GAiCb;EAVD,AAGE,CAHD,CAGG,OAAO,CAAC;IACR,KAAK,EAAE,OAAO,GACf;EALH,AAOE,CAPD,CAOG,KAAK,CAAC;IACN,KAAK,EA9BI,OAAO,GA+BjB;;AAGH,AAAA,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;EACP,UAAU,EAAE,CAAC;EACb,SAAS,EAAE,MAAgB;EAC3B,KAAK,EAlCE,OAAO,GAmCf;;AAED,AAAA,EAAE,CAAC;EACD,aAAa,EAAE,IAAI,GACpB;;AAED,AAAA,EAAE,CAAC;EACD,aAAa,EAAE,IAAI;EACnB,SAAS,EAAE,MAAgB;EAC3B,KAAK,EA5CE,OAAO,GA6Cf;;AAED,AAAA,GAAG,CAAC;EACF,WAAW,EAAE,wBAAwB;EACrC,SAAS,EAAE,GAAG;EACd,gBAAgB,EAjDA,IAAI;EAkDpB,KAAK,EAjDA,IAAI;EAkDT,OAAO,EAAE,GAAG;EACZ,QAAQ,EAAE,IAAI,GACf;;AAED,AAAA,GAAG,AAAA,MAAM,CAAC;EACR,KAAK,EAAE,IAAI;EACX,SAAS,EAAE,KAAK;EAChB,KAAK,EAAE,kBAAkB;EACzB,YAAY,EAAE,IAAI;EAClB,aAAa,EAAE,IAAI,GAIpB;EATD,AAME,GANC,AAAA,MAAM,AAMN,YAAY,CAAC;IACZ,SAAS,EAAE,KAAK,GACjB;;AAGH,AAAA,SAAS,EAAE,KAAK,CAAC;EACf,OAAO,EAAE,EAAE;EACX,KAAK,EAAE,IAAI;EACX,OAAO,EAAE,KAAK,GACf;;AAED,AAAA,MAAM,CAAC;EACL,OAAO,EAAE,QAAQ;EACjB,SAAS,EAAE,GAAG;EACd,YAAY,EAAE,IAAI;EAClB,aAAa,EAAE,IAAI;EACnB,gBAAgB,EAAE,IAAI;EACtB,KAAK,EAAE,KAAK;EACZ,MAAM,EAAE,IAAI;EACZ,aAAa,EAAE,GAAG;EAClB,MAAM,EAAE,OAAO,GAKhB;EAdD,AAWE,MAXI,CAWF,KAAK,CAAC;IACN,gBAAgB,EAAE,IAAI,GACvB;;AAGH,AAAA,KAAK,CAAA,AAAA,IAAC,CAAD,IAAC,AAAA,EAAW;EACf,SAAS,EAAE,GAAG;EACd,OAAO,EAAE,GAAG;EACZ,aAAa,EAAE,GAAG;EAClB,MAAM,EAAE,IAAI,GACb;;AAED,AAAA,EAAE,CAAC;EACD,OAAO,EAAE,OAAO,GAEjB;;AAED,AAAA,gBAAgB,CAAC;EACf,SAAS,EAAE,KAAK,GACjB"
|
|
9
9
|
}
|
package/index.html
CHANGED
|
@@ -30,7 +30,8 @@ It works, it is cool and it is easy to use. 👍</p>
|
|
|
30
30
|
<ul>
|
|
31
31
|
<li><a href="examples/extensions/chessboard-accessibility-extension.html">Accessibility extension</a></li>
|
|
32
32
|
<li><a href="examples/extensions/chessboard-arrows-extension.html">Arrows extension</a></li>
|
|
33
|
-
<li><a href="examples/extensions/chessboard-promotion-dialog-extension.html">PromotionDialog extension</a
|
|
33
|
+
<li><a href="examples/extensions/chessboard-promotion-dialog-extension.html">PromotionDialog extension</a></li>
|
|
34
|
+
<li><a href="examples/extensions/chessboard-render-video-extension.html">RenderVideo extension</a> 🆕</li>
|
|
34
35
|
</ul>
|
|
35
36
|
</div>
|
|
36
37
|
<h2>Chessboard</h2>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cm-chessboard",
|
|
3
|
-
"version": "5.5.
|
|
3
|
+
"version": "5.5.1",
|
|
4
4
|
"description": "A JavaScript chessboard which is lightweight, ES6 module based, responsive, SVG rendered and without dependencies.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"chess",
|
|
@@ -30,5 +30,6 @@
|
|
|
30
30
|
"homepage": "https://github.com/shaack/cm-chessboard#readme",
|
|
31
31
|
"devDependencies": {
|
|
32
32
|
"teevi": "^2.2.2"
|
|
33
|
-
}
|
|
33
|
+
},
|
|
34
|
+
"dependencies": {}
|
|
34
35
|
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Author and copyright: Stefan Haack (https://shaack.com)
|
|
3
|
+
* Repository: https://github.com/shaack/cm-chessboard
|
|
4
|
+
* License: MIT, see file 'LICENSE'
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import {Extension, EXTENSION_POINT} from "../../model/Extension.js"
|
|
8
|
+
|
|
9
|
+
export class RenderVideo extends Extension {
|
|
10
|
+
|
|
11
|
+
constructor(chessboard, props) {
|
|
12
|
+
super(chessboard, props)
|
|
13
|
+
this.props = {
|
|
14
|
+
mediaType: "video/webm;codecs=H264"
|
|
15
|
+
}
|
|
16
|
+
Object.assign(this.props, props)
|
|
17
|
+
this.images = []
|
|
18
|
+
this.makeSpriteInline()
|
|
19
|
+
this.registerExtensionPoint(EXTENSION_POINT.animation, () => {
|
|
20
|
+
// console.log("EXTENSION_POINT.animation", data)
|
|
21
|
+
let clonedSvgElement = this.chessboard.view.svg.cloneNode(true)
|
|
22
|
+
// this.makeStyleInline(clonedSvgElement)
|
|
23
|
+
let serialized = new XMLSerializer().serializeToString(clonedSvgElement)
|
|
24
|
+
// console.log(serialized)
|
|
25
|
+
const blob = new Blob([serialized], {type: "image/svg+xml"})
|
|
26
|
+
const blobURL = URL.createObjectURL(blob)
|
|
27
|
+
const image = new Image()
|
|
28
|
+
this.images.push(image)
|
|
29
|
+
image.onload = () => {
|
|
30
|
+
// console.log("onload", event)
|
|
31
|
+
let context = this.canvas.getContext('2d')
|
|
32
|
+
// console.log(image)
|
|
33
|
+
context.drawImage(image, 0, 0, this.canvas.width, this.canvas.height)
|
|
34
|
+
}
|
|
35
|
+
image.src = blobURL
|
|
36
|
+
})
|
|
37
|
+
this.registerMethod("recorderStart", () => {
|
|
38
|
+
let all = document.querySelectorAll("svg *")
|
|
39
|
+
for (let i = 0; i < all.length; i++) {
|
|
40
|
+
this.transferComputedStyle(all[i])
|
|
41
|
+
}
|
|
42
|
+
const dimensions = this.chessboard.view.svg.getBBox()
|
|
43
|
+
this.canvas = document.createElement("canvas")
|
|
44
|
+
this.canvas.style.display = "none"
|
|
45
|
+
this.canvas.width = dimensions.width
|
|
46
|
+
this.canvas.height = dimensions.height
|
|
47
|
+
document.body.append(this.canvas)
|
|
48
|
+
this.stream = this.canvas.captureStream()
|
|
49
|
+
this.recorder = new MediaRecorder(this.stream, {mimeType: this.props.mediaType})
|
|
50
|
+
this.recordedData = []
|
|
51
|
+
this.recorder.ondataavailable = (event) => {
|
|
52
|
+
// console.log(event)
|
|
53
|
+
if (event.data && event.data.size) {
|
|
54
|
+
this.recordedData.push(event.data)
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
this.recorder.start(0.1)
|
|
58
|
+
console.log("recorder", this.recorder.state)
|
|
59
|
+
})
|
|
60
|
+
/**
|
|
61
|
+
* returns the url of the recorded media
|
|
62
|
+
*/
|
|
63
|
+
this.registerMethod("recorderStop", () => {
|
|
64
|
+
this.recorder.stop()
|
|
65
|
+
console.log("recorder", this.recorder.state)
|
|
66
|
+
return URL.createObjectURL(new Blob(this.recordedData, {type: this.props.mediaType}))
|
|
67
|
+
})
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
transferComputedStyle(element) {
|
|
71
|
+
const computedStyle = getComputedStyle(element, null)
|
|
72
|
+
for (let i = 0; i < computedStyle.length; i++) {
|
|
73
|
+
const style = computedStyle[i] + ""
|
|
74
|
+
if (style === "fill") {
|
|
75
|
+
element.style[style] = computedStyle[style]
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
makeSpriteInline() {
|
|
81
|
+
const wrapper = document.createElement("div")
|
|
82
|
+
wrapper.style.display = "none"
|
|
83
|
+
document.body.appendChild(wrapper)
|
|
84
|
+
const svg = this.chessboard.view.svg
|
|
85
|
+
const xhr = new XMLHttpRequest()
|
|
86
|
+
xhr.open("GET", this.chessboard.props.sprite.url, true)
|
|
87
|
+
xhr.onload = function () {
|
|
88
|
+
const doc = new DOMParser().parseFromString(xhr.response, "text/xml")
|
|
89
|
+
svg.prepend(doc.getElementById("Sprite-PD"))
|
|
90
|
+
}
|
|
91
|
+
xhr.send()
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
}
|
|
@@ -10,6 +10,7 @@ export const EXTENSION_POINT = {
|
|
|
10
10
|
moveInputToggled: "moveInputToggled", // move input was enabled or disabled
|
|
11
11
|
moveInput: "moveInput", // move started, to validate or canceled
|
|
12
12
|
redrawBoard: "redrawBoard", // called after redrawing the board
|
|
13
|
+
animation: "animation", // called on every animation frame
|
|
13
14
|
destroy: "destroy" // called, before the board is destroyed
|
|
14
15
|
}
|
|
15
16
|
|
|
@@ -5,12 +5,19 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import {FEN, Position} from "../model/Position.js"
|
|
7
7
|
import {Svg} from "./ChessboardView.js"
|
|
8
|
+
import {EXTENSION_POINT} from "../model/Extension.js"
|
|
8
9
|
|
|
9
10
|
/*
|
|
10
11
|
* Thanks to markosyan for the idea of the PromiseQueue
|
|
11
12
|
* https://medium.com/@karenmarkosyan/how-to-manage-promises-into-dynamic-queue-with-vanilla-javascript-9d0d1f8d4df5
|
|
12
13
|
*/
|
|
13
14
|
|
|
15
|
+
export const ANIMATION_EVENT = {
|
|
16
|
+
start: "start",
|
|
17
|
+
frame: "frame",
|
|
18
|
+
end: "end"
|
|
19
|
+
}
|
|
20
|
+
|
|
14
21
|
export class PromiseQueue {
|
|
15
22
|
|
|
16
23
|
constructor() {
|
|
@@ -163,6 +170,9 @@ export class PositionsAnimation {
|
|
|
163
170
|
// console.log("animationStep", time)
|
|
164
171
|
if (!this.startTime) {
|
|
165
172
|
this.startTime = time
|
|
173
|
+
this.view.chessboard.state.invokeExtensionPoints(EXTENSION_POINT.animation, {
|
|
174
|
+
event: ANIMATION_EVENT.start
|
|
175
|
+
})
|
|
166
176
|
}
|
|
167
177
|
const timeDiff = time - this.startTime
|
|
168
178
|
if (timeDiff <= this.duration) {
|
|
@@ -175,6 +185,9 @@ export class PositionsAnimation {
|
|
|
175
185
|
Svg.removeElement(animatedItem.element)
|
|
176
186
|
}
|
|
177
187
|
})
|
|
188
|
+
this.view.chessboard.state.invokeExtensionPoints(EXTENSION_POINT.animation, {
|
|
189
|
+
event: ANIMATION_EVENT.end
|
|
190
|
+
})
|
|
178
191
|
this.callback()
|
|
179
192
|
return
|
|
180
193
|
}
|
|
@@ -206,6 +219,10 @@ export class PositionsAnimation {
|
|
|
206
219
|
console.warn("animatedItem has no element", animatedItem)
|
|
207
220
|
}
|
|
208
221
|
})
|
|
222
|
+
this.view.chessboard.state.invokeExtensionPoints(EXTENSION_POINT.animation, {
|
|
223
|
+
event: ANIMATION_EVENT.frame,
|
|
224
|
+
progress: progress
|
|
225
|
+
})
|
|
209
226
|
}
|
|
210
227
|
|
|
211
228
|
static squareDistance(index1, index2) {
|