# 各種組み込み例
# Vanilla JS
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script defer src="https://cdn.jsdelivr.net/npm/shogi-player@1.1.17"></script>
<script type="module">
const el = document.querySelector("shogi-player-wc")
el.addEventListener("ev_play_mode_move", e => {
alert(e.detail[0].last_move_info.to_kif)
})
</script>
</head>
<body>
<shogi-player-wc
sp_mode="play"
sp_body="position startpos moves 7g7f 3c3d 8h2b+ 3a2b"
sp_controller="true"
></shogi-player-wc>
</body>
</html>
Also see: 使い方
# Ruby
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script defer src="https://cdn.jsdelivr.net/npm/shogi-player@1.1.17"></script>
<script defer src="https://cdn.jsdelivr.net/npm/ruby-head-wasm-wasi@latest/dist/browser.script.iife.js"></script>
<script type="text/ruby">
require "js"
document = JS.global[:document]
el = document.querySelector("shogi-player-wc")
el.setAttribute("sp_body", "position startpos moves 7g7f 3c3d 8h2b+ 3a2b")
el.addEventListener("ev_play_mode_move") do |e|
JS.global.alert(e[:detail][0][:last_move_info][:to_kif])
end
</script>
</head>
<body>
<shogi-player-wc sp_mode="play"></shogi-player-wc>
</body>
</html>
# React
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script defer src="https://cdn.jsdelivr.net/npm/react@18/umd/react.production.min.js"></script>
<script defer src="https://cdn.jsdelivr.net/npm/react-dom@18/umd/react-dom.production.min.js"></script>
<script defer src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.34/browser.min.js"></script>
<script defer src="https://cdn.jsdelivr.net/npm/shogi-player@1.1.17"></script>
<script type="text/babel">
class App extends React.Component {
constructor(props) {
super(props)
this.spRef = React.createRef()
}
componentDidMount() {
this.spRef.current.addEventListener("ev_play_mode_move", e => {
alert(e.detail[0].last_move_info.to_kif)
})
}
render() {
return (<shogi-player-wc
ref={this.spRef}
sp_mode="play"
sp_body="position startpos moves 7g7f 3c3d 8h2b+ 3a2b"
sp_controller="true"
></shogi-player-wc>)
}
}
ReactDOM.render(<App/>, document.getElementById("root"))
</script>
</head>
<body>
<div id="root"></div>
</body>
</html>
# Solid.js
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script defer src="https://cdn.jsdelivr.net/npm/shogi-player@1.1.17"></script>
<script type="module">
import { render } from "https://cdn.skypack.dev/solid-js/web"
import html from "https://cdn.skypack.dev/solid-js/html"
const App = () => {
return html`
<shogi-player-wc
sp_mode="play"
sp_body="position startpos moves 7g7f 3c3d 8h2b+ 3a2b"
sp_controller="true"
></shogi-player-wc>`
}
render(App, document.body)
const el = document.querySelector("shogi-player-wc")
el.addEventListener("ev_play_mode_move", e => alert(e.detail[0].last_move_info.to_kif))
</script>
</head>
<body>
</body>
</html>
# Web Components
# Basic
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script defer src="https://cdn.jsdelivr.net/npm/shogi-player@1.1.17"></script>
<script type="module">
class ShogiBoard extends HTMLElement {
constructor() {
super()
this.attachShadow({mode: "open"})
}
connectedCallback() {
this.shadowRoot.innerHTML = `
<shogi-player-wc
sp_mode="play"
sp_body="position startpos moves 7g7f 3c3d 8h2b+ 3a2b"
sp_controller="true"
></shogi-player-wc>`
const el = this.shadowRoot.querySelector("shogi-player-wc")
el.addEventListener("ev_play_mode_move", e => alert(e.detail[0].last_move_info.to_kif))
}
}
customElements.define("shogi-board", ShogiBoard)
</script>
</head>
<body>
<shogi-board></shogi-board>
</body>
</html>
# Full Component
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script defer src="https://cdn.jsdelivr.net/npm/shogi-player@1.1.17"></script>
<script type="module">
class ShogiBoard extends HTMLElement {
constructor() {
super()
this.attachShadow({mode: "open"})
}
static get observedAttributes() {
return ["source"]
}
attributeChangedCallback(name, oldValue, newValue) {
if (name === "source") {
this.source = newValue
}
if (this.isConnected) {
this.render()
}
}
render() {
this.shadowRoot.innerHTML = `
<style>
:host {
display: block;
background-color: hsl(0 0% 0% / 0.1);
padding: 1rem;
}
.container {
display: flex;
justify-content: center;
}
shogi-player-wc {
flex-basis: 640px;
}
shogi-player-wc::part(root) {
--sp_board_color: LightSkyBlue;
}
</style>
<div class="container">
<shogi-player-wc
sp_mode="play"
sp_body="${this.source}"
sp_controller="true"
></shogi-player-wc>
</div>
`
const el = this.shadowRoot.querySelector("shogi-player-wc")
el.addEventListener("ev_play_mode_move", e => alert(e.detail[0].last_move_info.to_kif))
}
}
customElements.define("shogi-board", ShogiBoard)
// Reactive Test
// setTimeout(() => document.querySelector('shogi-board').setAttribute("source", "position startpos moves 7g7f"), 1000 * 1)
</script>
</head>
<body>
<shogi-board source="position startpos moves 7g7f 3c3d 8h2b+ 3a2b"></shogi-board>
</body>
</html>
# Lit
# Basic
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script defer src="https://cdn.jsdelivr.net/npm/shogi-player@1.1.17"></script>
<script type="module">
import { LitElement, html } from "https://cdn.jsdelivr.net/gh/lit/dist@2/core/lit-core.min.js"
export class MyApp extends LitElement {
render() {
return html`
<shogi-player-wc
sp_mode="play"
sp_body="position startpos moves 7g7f 3c3d 8h2b+ 3a2b"
sp_controller="true"
@ev_play_mode_move="${e => alert(e.detail[0].last_move_info.to_kif)}"
></shogi-player-wc>`
}
}
customElements.define("my-app", MyApp)
</script>
</head>
<body>
<my-app></my-app>
</body>
</html>
# Full Component
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script defer src="https://cdn.jsdelivr.net/npm/shogi-player@1.1.17"></script>
<script type="module">
import { LitElement, css, html } from "https://cdn.jsdelivr.net/gh/lit/dist@2/core/lit-core.min.js"
export class ShogiBoard extends LitElement {
static styles = css`
:host {
display: block;
background-color: hsl(0 0% 0% / 0.1);
padding: 1rem;
}
.container {
display: flex;
justify-content: center;
}
shogi-player-wc {
flex-basis: 640px;
}
shogi-player-wc::part(root) {
--sp_board_color: LightSkyBlue;
}
`
static properties = {
source: { type: String },
}
constructor() {
super()
this.source ??= "position sfen 4k4/9/9/9/9/9/9/9/9 b 2r2b4g4s4n4l18p 1"
}
render() {
return html`
<div class="container">
<shogi-player-wc
sp_mode="play"
sp_body="${this.source}"
sp_controller="true"
@ev_play_mode_move="${e => alert(e.detail[0].last_move_info.to_kif)}"
></shogi-player-wc>
</div>
`
}
}
customElements.define("shogi-board", ShogiBoard)
</script>
</head>
<body>
<shogi-board source="position startpos moves 7g7f 3c3d 8h2b+ 3a2b"></shogi-board>
</body>
</html>
# Vue.js 2
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script defer src="https://cdn.jsdelivr.net/npm/vue@2"></script>
<script defer src="https://cdn.jsdelivr.net/npm/shogi-player@1.1.17"></script>
<script type="module">
Vue.config.ignoredElements = ["shogi-player-wc"]
new Vue({el: "#app"})
</script>
</head>
<body>
<div id="app">
<shogi-player-wc
sp_mode="play"
sp_body="position startpos moves 7g7f 3c3d 8h2b+ 3a2b"
sp_controller="true"
@ev_play_mode_move="e => alert(e.detail[0].last_move_info.to_kif)"
></shogi-player-wc>
</div>
</body>
</html>
# Vue.js 2 + UMD
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script defer src="https://cdn.jsdelivr.net/npm/vue@2"></script>
<script defer src="https://cdn.jsdelivr.net/npm/shogi-player@1.1.17/dist/lib/production/shogi-player.umd.min.js"></script>
<script type="module">
new Vue({el: "#app", components: { ShogiPlayer }})
</script>
</head>
<body>
<div id="app">
<shogi-player
sp_mode="play"
sp_body="position startpos moves 7g7f 3c3d 8h2b+ 3a2b"
sp_controller
@ev_play_mode_move="e => alert(e.last_move_info.to_kif)"
></shogi-player>
</div>
</body>
</html>
# Vue 3
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script defer src="https://cdn.jsdelivr.net/npm/shogi-player@1.1.17"></script>
<script defer src="https://cdn.jsdelivr.net/npm/vue@3"></script>
<script type="module">
const app = Vue.createApp({
methods: {
ev_play_mode_move(e) {
alert(e.detail[0].last_move_info.to_kif)
},
},
})
app.config.compilerOptions.isCustomElement = tag => tag === "shogi-player-wc"
app.mount("#app")
</script>
</head>
<body>
<div id="app">
<shogi-player-wc
sp-pass-props='{
sp_mode: "play",
sp_body: "position startpos moves 7g7f 3c3d 8h2b+ 3a2b",
sp_controller: true,
sp_pass_style: "{\"--sp_controller_width\": 1.0}",
}'
@ev_play_mode_move="ev_play_mode_move"
></shogi-player-wc>
</div>
</body>
</html>
引数が渡せない問題と回避方法
- Vue.js 2 で作成した Web Components を Vue 3 と組み合わせたときに限り snake_case なパラメータ名を持つ値が渡せない問題がある
- 簡単に言えば
_
を含むパラメータが無視される
- 簡単に言えば
- そこでその嫌がらせのような制約を回避するために仕方なく
sp-pass-props
を用意した - これは
v-bind
に似ているが Vue はただの文字列として解釈するため確実に内容を渡すことができる sp-pass-props
の内容は JSON5 形式の文字列としてパースする- 型変換は JSON5 のパーサーに任せているので Boolean 型の真は
"true"
ではなくtrue
と書く - 最終的に
sp-pass-props
の内容は$props
相当として扱う
# Vue.js 2 (vue/cli) + UMD
- 手動で組み込んだ例を shogi-player-vue2-sample-umd (opens new window) に置いている
- すでにビルドしているため
vue.config.js
に何も書かなくても動く - CSSも js に含んでいるため読み込む必要がない
# Vue.js 2 (vue/cli) + ShogiPlayer.vue
- 手動で組み込んだ例を shogi-player-vue2-sample (opens new window) に置いている
- もともと Vue.js 2 製なので Vue.js 2 とは親和性が高い
- ただしBulma (opens new window)が他のCSSフレームワークと干渉する恐れがある
# Nuxt.js + ShogiPlayer.vue
手動で組み込んだ例を shogi-player-nuxt-sample (opens new window) に置いている
# Svelte
手動で組み込んだ例を shogi-player-svelte-sample (opens new window) に置いている
そこから該当箇所の抜粋:
<script>
function ev_play_mode_move(e) {
alert(e.detail[0].last_move_info.to_kif)
}
</script>
<main>
<shogi-player-wc
sp-pass-props={'{sp_mode: "play", sp_body: "position startpos moves 7g7f 3c3d 8h2b+ 3a2b", sp_controller: true, sp_pass_style: {\"--sp_controller_width\": 1.0}}'}
on:ev_play_mode_move={ev_play_mode_move}
></shogi-player-wc>
</main>
- Vue 3 の場合と同じパラメータを渡す例が上になる
- パラメータの渡し方が Vue 3 よりも難しい
sp-pass-props
は途中で改行すると動かなくなる
# 自力ビルドの要点
- transpile 問題
node_modules/shogi-player
以下を babel のビルド対象に含める- これをやらないとビルドできない
- クラス定数や
??
演算子が解釈されない
- クラス定数や
- @vue/cli であれば vue.config.js の
transpileDependencies
に指定する - Nuxt.js であれば nuxt.config.js の
build.transpile
に含める
- webpack-dev-server で
ResizeObserver loop limit exceeded
が出る場合devServer.client.overlay.runtimeErrors
をfalse
にする
- jest
- Babel の設定は
.babelrc
ではなくbabel.config.js
に書く - そうしないと node_modules/* に適用されず jest が動かない
- Babel の設定は