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 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>
@@ -43,6 +43,8 @@ div.board {
43
43
  width: calc(100vw - 40px);
44
44
  margin-right: 20px;
45
45
  margin-bottom: 20px; }
46
+ div.board.board-small {
47
+ max-width: 320px; }
46
48
 
47
49
  .clearfix::after {
48
50
  content: "";
@@ -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,GACpB;;AAED,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"
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
  }
@@ -64,6 +64,9 @@ div.board {
64
64
  width: calc(100vw - 40px);
65
65
  margin-right: 20px;
66
66
  margin-bottom: 20px;
67
+ &.board-small {
68
+ max-width: 320px;
69
+ }
67
70
  }
68
71
 
69
72
  .clearfix::after {
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> 🆕</li>
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.0",
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) {