@anweather/plugin-board-kit (英语)
网页游戏平台上任意游戏板的棋盘-UI原始:一个远程
插件的前端捆绑( t)boardgame-plugins, (中文(简体) ), tactics-game-plugin,则
平台本身 plugins/tic-tac-toe-remote和仍然在
这个雷波 frontend/一次执行,一次一揽子,公开npm
登记.
在SDK的版本中与SDK一起出版. publish-plugin-sdk.yml
与 @anweather/game-plugin-ssdk 编辑
Kotlin 从一个运行时间 sdk-v* 标记,所以插件的棋盘套件, SSDK 和
运行时标出所有名称 相同的发布 。 见 plugin-protocol/CLAUDE.md, (中文(简体) ),
"为跨repo插件配置".
为什么是包裹而不是副本. 插件的前端捆绑自己的反应
(没有标记) external) (中文(简体) ). react 财务报告和审定财务报表 react-dom 为: 端点
这里的依赖,所以消费者自己的 node_modules/react 是那个
此代码绑定为: 每捆完全一个反应实例 。 贝壳标记
卖出这个替换来躲避双反应失败
生成的交叉目录导入( “不能读取无效的属性( 读取) )
'""用"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""".
目录
mountReactBoard(Component, { onError?, fallback? })返回时{ mount, update, unmount }操作跨区域远程捆绑输出 影月分界线. 它将棋盘包裹在一个错误的边界:一个渲染 错误显示信件而不是空白矩形,通过onError,并在下一个update()。 。 。 .BoardShell(中心栏布局)和TurnIdentity("你是 X"行,有旁观者变相. 整个内含样式;TurnIdentity使用 CSS 软件color从来没有一个类名, 所以它使同样的内部 影子根,没有尾风到达.computeIsMyTurn编号 :computeIsAwaiting编号 :computeIsSpectator一个以上 最小结构TurnState(任何与lifecycle, (中文(简体) ),currentTurnParticipantId, (中文(简体) ),participants选择awaitingParticipantIds, (中文(简体) ),GameView(包括中文).computeIsAwaiting实值 "等着我"在同时期意味着什么.teamOf编号 :teamMembers四等座 二等座 二等座 二等座 (模拟平台域名)TeamAssignment) (中文(简体) ).- 显示平台域的一半
TurnClock数字 :useClockNow, (中文(简体) ),useClockTimeout, (中文(简体) ),formatClock, (中文(简体) ),remainingMs, (中文(简体) ),clockReading,则ClockBadge编号 :StartTurnGate组件。 或 已经 留下来 引擎的调用. - 董事会的相机,
useCamera(见下文"板相机"): 剪接, 拖动、 轮子和键盘缩放/ 泛到 a<canvas>,一个<svg>视图框或位置<div>附加时FitButton编号 :FitIcon, (中文(简体) ),mergeHandlers在它下面的纯数学paddedWorld, (中文(简体) ),fitWorld, (中文(简体) ),canvasTransform,(......)和createCamera没有反应的机器.useCanvasCamera是它堕落的前身,现在是它的包袱. - 董事会框架,
useBoardFrame(见下文"董事会框架"): 是否在平台的全屏框中,其大小 菜单角以保持清晰和宽/全布局,加平台的 全屏几何作为常数( e)MENU_RESERVE(中文(简体) ). boardTelemetry(props): 主持人BoardProps.telemetry记者 (单位:千美元)event(name, attrs), (中文(简体) ),error(err, context)进入平台的法罗, 限定费率,并由平台以游戏类型/id/参与者来盖章), 或者说NOOP_BOARD_TELEMETRY在一个没有主机。 永不掷出.
不是故意在这里的 nameplateAccent.ts (这首歌)
frontend/src/plugins/硬码每 -gameType 整个本地颜色
编目,是站台逻辑,不是棋盘原始.
板子相机
每板一相相机. 它聚集在棋盘-插座中
@boardgame-plugins/game-ui 从四块板上取出胶水
useCanvasCamera (原始内容存档于2012-10-12). spirit- island, catan, vititum and complete, svg
然后把帆布板移到这里 所以画布板(危险、斑点),
口袋战术)运行同一个. 三层,每层可单独使用:
camera.ts (纯粹的数学:一个世界,一个缩放,一个被夹在内部的抵消)
(世界), cameraController.ts (单位:千美元)createCamera:指针机,不
反应,在它交接的窗外没有DOM)和 useCamera.tsx (单位:千美元)
钩子, FitButton) (中文(简体) ).
// An svg: the drawing is lw x lh; the world is it padded to the
// element's shape, so the svg's `meet` and the pointer mapping agree.
const cam = useCamera({ world: paddedWorld(lw, lh, elW, elH), label: 'Map' })
<svg ref={cam.ref} {...cam.props} viewBox={cam.viewBoxAttr} style={{ touchAction: 'none' }}>...</svg>
{cam.zoomed && <FitButton onFit={cam.fit} />}
// A canvas: map the world at zoom 1 onto the canvas, then the camera,
// then draw in drawing coordinates.
const cam = useCamera<HTMLCanvasElement>({ world: paddedWorld(w, h), onTap: (p) => select(cam.toLayout(p.x, p.y)) })
ctx.setTransform(canvas.width / cam.world.w, 0, 0, canvas.height / cam.world.h, 0, 0)
cam.applyTransform(ctx)
<canvas ref={cam.ref} {...cam.props} style={{ touchAction: 'none' }} />
选项( E)CameraOptions),除此之外,没有其他 world 选项:
world(单位:千美元)paddedWorld,或fitWorld以保持图解 浮在地上的东西,origin(这里的画盒) 开始),minZoom编号 :maxZoom(第1/4条).opening(): 以缩放和世界点为中心, 以山为框架 以及何时frameKey更改;任何时候settleKey变化也一样, 直到玩家首先触摸相机. 放大了一个新的world不被带走(它会把板子移到手指下) 除非元素改变形状.- 磁带: 默认情况下, 未移动的相机点击到达下方的元素
这个.
onTap(clientPoint)(一个撞击测试自己的板:一张帆布) 换成是用tapSlop(6个px),tapMaxMs财务报告和审定财务报表onDoubleTap(320ms, 30px) (英语). 媒体走过斜坡,长出一副手指 或被声称吞下它的点击. singlePointerPan(默认为真):对自己的董事会不实 一指手势是一种拖动;然后两个手指移动相机和onDrag(单位:千美元)start编号 :move编号 :end编号 :cancel,绘图坐标) 得到拖曳, 被第二个手指取消。 每个媒体都读.keyboard(默认为: 表面可聚焦)role="group"名称label;箭头为视图的八分之一,+ / - 缩放 x1.25, (第3条).
其回报( W)Camera: view (单位:千美元)zoom, (中文(简体) ), offsetX, (中文(简体) ), offsetY, (中文(简体) ),
world, (中文(简体) ), viewBox 编号 : viewBoxAttr, (中文(简体) ), transform 编号 : applyTransform(ctx), (中文(简体) ),
zoomed, (中文(简体) ), pressing, (中文(简体) ), fit, (中文(简体) ), zoomTo, (中文(简体) ), zoomBy, (中文(简体) ), centerOn, (中文(简体) ), toWorld, (中文(简体) ),
toLayout, (中文(简体) ), toClient, (中文(简体) ), claim 编辑 controller。 。 。 . useCameraOn(ref, opts) 和打电话的人一样.
没有捕捉到指针:在向窗口发泡时听到动作
(某事阻止了一个人的手势) 在下行的路上,
所以,一个离开板子的平板 继续前进,一个升降机在任何地方结束
指针; PointerBook 修理升降机 从来没有到达。 中学
鼠标按钮从不平板;侧道滚动从不缩放. 一个长压
以解释发送 CAMERA_CLAIM_EVENT 一、导 言
它下面的相机 放弃了其余的媒体(没有锅,没有水龙头).
@anweather/plugin-board-kit/testing是因为 rigCamera(config) 驱动
装入假窗口的机器 node:test (这个包裹)
test/cameraController.test.ts) (中文(简体) ).
useCanvasCamera (折旧) 保持其签字和合同
游戏本身 onPointerDown/Move/Up/Cancel (世界坐标,
反应事件, 声称其余的序列) 作为包装
结束 useCamera。改变了的是相机本身的行为:修正
车轮的出站正好是1分之1的倒数,
(没有0.9个).
董事会框架
全屏为克能游戏布局. 登记条目
fullScreenBoard: true 获得 FullScreenBoard 改为 GamePage是因为
列: 100dvh 感觉根被安全区域插件加入一次,一个框
标记 data-fullscreen-board 这是董事会的整个区域及其
滚动容器, qq BoardCornerMenu 浮在那个盒子上
左上方,在56px侧设置和结果之间沿上方注意
底部的卡片. useBoardFrame 董事会如何理解合同
(它取代灵岛) useFrame 及其在卡坦语和
阴道和战术 fullScreen.ts:
const [el, ref] = useState<HTMLDivElement | null>(null)
const frame = useBoardFrame(el, { wideAspect: 1.15, minHeight: 360 })
<div ref={ref} style={{ height: frame.height ?? 560, flexDirection: frame.wide ? 'row' : 'column' }}>
<Header style={{ paddingLeft: frame.menuReserve }} />
</div>
将元件本身传递(回调回调为状态),而非回调对象,
钩子一旦存在就会运行 它返回( E)BoardFrame:
full:在站台的盒子内. 礛height这正是盒子的 (a) 调整观察员的大小使其保持当前:电话转接、工具栏 崩溃、 框卷轴和套件已经应用: 永远 再给他们一个垫子.menuReserve数字 :MENU_RESERVE(48) 而平台的qq浮出水面 盒子是左上方的, 否则0。 保持48px平方块(MENU_CORNER_RECT, (中文(简体) ),overlapsMenuCorner(rect)没有任何可挖掘的、可长压的 或必须读取。 默认是... ... 坐在平台上方 栏 上文 盒子(盒子说:data-fullscreen-menu="bar", (中文(简体) ),menuInBar(box)),且保留地为 0;只有选择退出的游戏 栏(登记)fullScreenTopBar: false)得到浮起相角. 读取frame.menuReserve而不是说MENU_RESERVE自己,所以一个板 随其所入.width, (中文(简体) ),height: 元素的宽度; 在普通页面上的高度 从它的顶端到取景口的底部(平台的铬) 上面算着topCap,至少40%的取景点)minHeight(数目,或{ tall, wide }) (中文(简体) ).layout编号 :wide: 宽度/ 高时宽度 >wideAspect(默认) 1.2)和宽度minWideWidth(默认为0). 灵岛1.2, catan 1.15,葡萄栽培1.05与900px.insets: 仅与viewportFallback: true,固定在 没有平台框的赤色取景口——全屏和板垫SAFE_AREA自己来 没有平台布局产生一个.box:盒子元素,一旦找到.
在测量前(静态渲染, 第一种颜料),它是
UNMEASURED_FRAME:不满而高也,无大小也. 在盒子里,它变成一个
阴影山主机 overflow-x: hidden 输入 clip 挂载时
(单位:千美元)clipHost,默认在),所以粘贴头会粘住盒子,而不是
永不滚动的主机; 通过的注册项 hostOverflowX="clip"
已经拥有了.
纯净的一半是 boardFrame.ts (单位:千美元)computeFrame, (中文(简体) ), frameLayout, (中文(简体) ),
findFullScreenBox,常数),所有可测试的节点. 常数
是平台本身的编号: MENU_BUTTON_INSET 8号, MENU_BUTTON_SIZE
40 (中文(简体) )BoardCornerMenu, (中文(简体) ), NOTICE_SIDE_INSET 页:1 RESULT_CARD_INSET 第12条
(单位:千美元)FullScreenBoard) (中文(简体) ). test/boardFrame.test.ts 阅读这两个平台
文件如果停止匹配则失败, 因此移动菜单意味着
改变两个都在一个公关.
不是这里(yet):一个"这是电话"的断点. 其他董事会的支票
不同的问题(520px和
(pointer: coarse)760px以下的三行窗口 垄断
900px以下的容器,q-blood的连续尺度; 将其折叠成
一个帮手会改变每个人的工作 让他们留在自己的董事会里
直到每个移动到全屏幕. frameLayout(w, h, { wideAspect: 0, minWideWidth: 900 }) 已经说垄断.
发展中国家
npm ci && npm run build && npm test && npm run typecheck
npm test 包括纯助行者(转弯、团队和时钟算术)、
相机的数学和指针机,相机框的算术(及其
常数与平台本身的FullScreenBoard和BoardCornerMenu相对应,
钩子变成静止
标记,带有 node:test; 组件按键检查并使用
消费者拥有Playwright套房. 尝试一个未公布的更改
消费者, npm pack 在这里安装柏油球,消费者的
package.json 永远不要用路径指向这个目录,因为
file: 链接解析 react 通过此目录本身 node_modules
并重新引入两反应包.