Stretch
Stretch 是用 Rust 编写的 Flexbox 实现。Stretch 的目标是为所有平台提供可靠的布局基础,特别关注移动设备。长期目标是让 Stretch 不仅支持 flexbox,还支持许多其他布局算法,例如网格布局。Stretch 是为 https://visly.app 而构建的并为之提供动力。
目标
在使用或为 stretch 贡献之前,了解项目的核心目标是很好的。这些是我们正在努力实现的目标,并不一定是我们目前支持的功能。
- 高性能
- 跨平台
- 小体积的二进制文件
- 支持多个布局系统
- 多线程布局
- 为大多数常用语言提供语言绑定
支持的平台
- Rust
- Android
- iOS
- JavaScript / TypeScript
用法
虽然 Stretch 是用 Rust 编写的,但它具有绑定到多个语言和平台,因此您可以根据您项目的需要以最自然的方式使用它。
Rust
# Cargo.toml
[dependencies]
stretch = "0.3.2"
// main.rs
use stretch::geometry::Size;
use stretch::style::*;
fn main() -> Result<(), stretch::Error> {
let mut stretch = stretch::node::Stretch::new();
let child = stretch.new_node(
Style { size: Size { width: Dimension::Percent(0.5), height: Dimension::Auto }, ..Default::default() },
vec![],
)?;
let node = stretch.new_node(
Style {
size: Size { width: Dimension::Points(100.0), height: Dimension::Points(100.0) },
justify_content: JustifyContent::Center,
..Default::default()
},
vec![child],
)?;
stretch.compute_layout(node, Size::undefined())?;
dbg!(stretch.layout(node)?);
}
Android
// Build.gradle
android {
splits {
abi {
enable true
}
}
}
dependencies {
implementation 'app.visly.stretch:stretch:0.3.2'
}
// MainActivity.kt
val node = Node(
Style(size = Size(Dimension.Points(100f), Dimension.Points(100f)), justifyContent = JustifyContent.Center),
listOf(
Node(Style(size = Size(Dimension.Percent(0.5f), Dimension.Percent(0.5f))), listOf())
))
val layout = node.computeLayout(Size(null, null))
Log.d(TAG, "width: ${layout.width}, height: ${layout.height}")
iOS
# Podfile
pod 'StretchKit', '~> 0.3.2'
// ViewController.swift
let node = Node(
style: Style(size: Size(width: .points(100.0), height: .points(100.0)), justifyContent: .center),
children: [
Node(style: Style(size: Size(width: .percent(0.5), height: .percent(0.5))), children: [])
])
let layout = node.computeLayout(thatFits: Size(width: nil, height: nil))
print("width: \(layout.width), height: \(layout.height)")
JavaScript
> npm install --save stretch-layout
// index.js
import { Allocator, Node, JustifyContent } from 'stretch-layout';
const allocator = new Allocator();
const node = new Node(allocator, {width: 100, height: 100, justifyContent: JustifyContent.Center});
node.addChild(new Node(allocator, {width: '50%', height: '50%'}));
const layout = node.computeLayout();
console.log(layout.width, layout.height);
Contributing
贡献非常欢迎。虽然我们在您编写代码之前(在初期)就要求您先打开一个 issue 或 pull request,以便我们可以在您投入时间实现之前讨论解决方案和补充。
- 二进制文件大小减少
- 运行时性能
- 确保构建/测试环境在非 macOS 平台上运行良好
- 备选布局系统(网格布局?)
- Web 兼容性测试
- RTL 支持
- 平台绑定
- API 改进
- 文档 & 示例
Installation
如果您没有安装 Rust,您也需要先安装 Rust,以及安装一些我们使用的组件来格式化和检查代码库。有关 Rust 的更多信息,请参阅他们的网站。
curl https://sh.rustup.rs -sSf | sh
rustup component add rustfmt
rustup component add clippy
完成此操作后,您可以克隆存储库并进行一些检查,以确保一切正常运行。
git clone https://github.com/vislyhq/stretch.git
cd stretch
cargo test
如果您对API进行了任何更改,还应更新并运行所有位于/bindings/*
位置的平台绑定测试。
测试
通过验证在 stretch 中编写的布局与 Chrome 中的布局执行相同,来测试 Stretch。这是通过在 HTML 中渲染等效布局,然后生成一个 Rust 测试用例,该用例假定在 Stretch 中运行时,生成的布局是相同的。
您可以在不设置 webdriver 环境的情况下运行这些测试,但如果您想添加任何测试用例,则需要安装 chromedriver。如果您在 macOS 上开发,则可以通过 brew 很容易地完成此操作。
brew tap homebrew/cask
brew cask install chromedriver
在安装了 chromedriver 并将其放置在 PATH
之后,您可以通过运行 cargo run --package gentest
重新生成所有测试。
要添加新的测试用例,请将另一个 HTML 文件添加到 /test_fixtures
,按照当前测试作为新测试的模板。
基准测试
基准测试基于与测试相同的架构,实际上基准测试就像测试一样自动从测试固定值生成。运行 cargo bench
在本地运行基准测试。
与 Yoga 的关系
Yoga 是用 C 编写的跨平台 Flexbox 实现。Yoga 是一个了不起的项目,但存在问题,我们希望解决这些问题。与 Yoga 相比,我们旨在更严格地遵守 Web 标准、灵活的架构,最终支持多个布局算法,以及未来的性能改进,包括多线程布局。除此之外,我们旨在使用更安全的语言和更具现代性的代码库。
许可协议
Copyright (c) 2018 Visly Inc.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.