gpt4 book ai didi

javascript - 如何正确调整 Xterm.js 的大小?

转载 作者:行者123 更新时间:2023-11-30 14:06:17 25 4
gpt4 key购买 nike

长话短说我创建了一个 React 包装器来将一组日志消息呈现到终端中,但调整大小会产生奇怪的输出(请参见屏幕截图)。 (NPM 上有一个 React-Wrapper,但它不适用于我的用例 - 导致屏幕闪烁)

我正在为 Guppy 开发一项功能,我在其中添加了 Xterm.js用于终端输出。可以找到PR here .

由于超链接扫描/解析,我已经添加了 xterm,并且可以正常工作。

但我一直坚持调整大小才能工作。如果我在应用程序中启动 devServer 并等待一些文本,它将以正确的字母宽度显示。如果我减小尺寸,我得到的输出字母宽度不正确。就像下面的截图: Messed output

它在未调整大小的状态下总是看起来正确,但在调整大小后它会得到错误的显示 - 所以这会发生在放大和缩小屏幕宽度时。

输出应该类似于下面的截图(可能有一些换行): Correct output

我认为这是由 Fit addon 引起的或者我使用调整大小观察器处理调整大小的方式,但我不确定。

xterm 字母的跨度样式的宽度为 NaNpx就像下面的截图: CSS with width NaNpx这是由我使用的媒体查询引起的吗?我还没有看到,也许我必须暂时禁用所有媒体查询以查看是否是导致该行为的原因。

到目前为止我尝试了什么:

  • 包装this.xterm.fit()进入setTimeout(func, 0)但没有效果
  • 修改了一些我正在使用的样式,但我还没有找到原因。

代码

我正在使用的代码可以在 Github branch feature-terminal-links 上找到但在这里我想提取我为使 Xterm 与 React 一起工作而添加的部分:

  1. 我创建了一个样式组件 XtermContainer作为一个 div,所以我可以添加 Xterm 样式和自己的样式。以下代码在render里面并将成为我们的 xterm.js 容器(innerRef 稍后将在 ComponentDidMount 中使用以使用该容器初始化 Xterm):
<XtermContainer
width={width}
height={height}
innerRef={node => (this.node = node)}
/>
  1. componentDidMount 中初始化 xterm使用上面的容器:
componentDidMount() {
Terminal.applyAddon(webLinks);
Terminal.applyAddon(localLinks);
Terminal.applyAddon(fit);

this.xterm = new Terminal({
convertEol: true,
fontFamily: `'Fira Mono', monospace`,
fontSize: 15,
rendererType: 'dom', // default is canvas
});

this.xterm.setOption('theme', {
background: COLORS.blue[900],
foreground: COLORS.white,
});

this.xterm.open(this.node);
this.xterm.fit();

/* ... some addon setup code here (not relevant for the problem) ... */
}
  1. 已添加 react-resize-observer在也包含终端容器的包装器内部,因此我可以触发 this.xterm.fit()如果大小发生变化(在 repo 协议(protocol)中有一个 setTimeout 包装用于测试)。
<ResizeObserver onResize={() => this.xterm && this.xterm.fit()} />
  1. 使用 componentDidUpdate(prevProps, prevState)如果组件正在获取新日志,则更新终端并将终端滚动到底部:
componentDidUpdate(prevProps, prevState) {
if (prevProps.task.logs !== this.state.logs) {
if (this.state.logs.length === 0) {
this.xterm.clear();
}
for (const log of this.state.logs) {
/*
We need to track what we have added to xterm - feels hacky but it's working.
`this.xterm.clear()` and re-render everything caused screen flicker that's why I decided to not use it.
Todo: Check if there is a react-xterm wrapper that is not using xterm.clear or
create a wrapper component that can render the logs array (with-out flicker).
*/
if (!this.renderedLogs[log.id]) {
this.writeln(log.text);
this.xterm.scrollToBottom();
this.renderedLogs[log.id] = true;
}
}
}
}

我要找原因的思路:

  • 检查 ResizeObserver 代码。(请参阅下面的更新)
  • 尝试找出 xterm css 宽度为 NaN 的原因。 Xterm.js 是否使用容器的样式宽度?如果是,则可能设置不正确。

更新

好的,可能不需要调整大小的观察服务器,因为我在注释掉 <ResizeObserver/> 后得到了相同的行为。在渲染中。所以我认为这是由 xterm.js 或 Guppy 中的 css 引起的。

最佳答案

我已经解决了这个问题。它现在在上述功能分支中工作。不确定是否有更好的解决方案,但它对我有用。

我想解释一下我是如何解决调整大小问题的:

问题出在 DevelopmentServerPane 中使用的 OnlyOn 组件。它总是呈现两个 TerminalOutput 组件。一个终端使用 display: none 隐藏,另一个终端使用 display: inline 显示 - 样式更改是通过 styled-component 中的媒体查询处理的。

OnlyOn 替换为 React-responsive 后并使用渲染 Prop 检查 mdMin 断点是否按预期工作。 React-responsive 正在从 DOM 中删除未显示的媒体查询组件,因此 DOM 中同时只有一个终端。

我仍然不知道为什么字母宽度有问题,但可能这两个实例以某种方式发生了冲突。我无法创建最小的复制品。我试图在此 Codesandbox 中重现该问题但我一次只调整了一个终端的大小,所以我没有遇到问题。

修复问题的代码(上述 repo 的简化版本):

import MediaQuery from 'react-responsive';

const BREAKPOINT_SIZES = {
sm: 900,
};

const BREAKPOINTS = {
mdMin: `(min-width: ${BREAKPOINT_SIZES.sm + 1}px)`,
};

const DevelopmentServerPane = () => (
<MediaQuery query={BREAKPOINTS['mdMin']}>
{matches =>
matches ? (
<div>{/* ... render Terminal for matching mdMin and above */}</div>
) : (
<div> {/* ... render Terminal for small screens */}</div>
)
}
</MediaQuery>
);

关于javascript - 如何正确调整 Xterm.js 的大小?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55322629/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com