1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303
| QuickJS + Yoga 结合使用 QuickJS 是一个轻量级的 JavaScript 引擎,由 Mozilla 开发,适用于嵌入式系统和高性能应用。Yoga 是 Facebook 开发的一个跨平台布局引擎,基于 Flexbox 布局算法。结合 QuickJS 和 Yoga,可以在 JavaScript 中实现高效的布局管理,特别适合用于构建跨平台的应用程序。
以下是一个简单的示例,展示如何在 QuickJS 中使用 Yoga 进行布局计算。
1. 安装依赖 首先,确保你已经安装了 QuickJS 和 Yoga。你可以从各自的 GitHub 仓库获取源代码并编译安装。
QuickJS: https://github.com/bellard/quickjs Yoga: https://github.com/facebook/yoga 2. 编写 C 代码 创建一个 C 文件(例如 main.c),用于初始化 QuickJS 和 Yoga,并提供 JavaScript 接口。
c #include "quickjs.h" #include "yoga/YGNode.h"
// 初始化 Yoga 节点 YGNodeRef createYogaNode() { YGNodeRef node = YGNodeNew(); return node; }
// 设置 Yoga 节点的宽度 void setWidth(YGNodeRef node, float width) { YGNodeStyleSetWidth(node, width); }
// 设置 Yoga 节点的高度 void setHeight(YGNodeRef node, float height) { YGNodeStyleSetHeight(node, height); }
// 设置 Yoga 节点的 Flex 方向 void setFlexDirection(YGNodeRef node, const char* direction) { YGFlexDirection dir = YGFlexDirectionColumn; if (strcmp(direction, "row") == 0) { dir = YGFlexDirectionRow; } else if (strcmp(direction, "column-reverse") == 0) { dir = YGFlexDirectionColumnReverse; } else if (strcmp(direction, "row-reverse") == 0) { dir = YGFlexDirectionRowReverse; } YGNodeStyleSetFlexDirection(node, dir); }
// 计算 Yoga 布局 void calculateLayout(YGNodeRef node, float width, float height) { YGNodeCalculateLayout(node, width, height, YGDirectionLTR); }
// 获取 Yoga 节点的布局属性 float getLayoutLeft(YGNodeRef node) { return YGNodeLayoutGetLeft(node); }
float getLayoutTop(YGNodeRef node) { return YGNodeLayoutGetTop(node); }
float getLayoutWidth(YGNodeRef node) { return YGNodeLayoutGetWidth(node); }
float getLayoutHeight(YGNodeRef node) { return YGNodeLayoutGetHeight(node); }
// 注册 JavaScript 函数 void registerJSFunctions(JSContext* ctx) { JS_NewGlobalObject(ctx); JSValue global_obj = JS_GetGlobalObject(ctx);
JS_SetPropertyStr(ctx, global_obj, "createYogaNode", JS_NewCFunction(ctx, createYogaNode, "createYogaNode", 0)); JS_SetPropertyStr(ctx, global_obj, "setWidth", JS_NewCFunction(ctx, setWidth, "setWidth", 2)); JS_SetPropertyStr(ctx, global_obj, "setHeight", JS_NewCFunction(ctx, setHeight, "setHeight", 2)); JS_SetPropertyStr(ctx, global_obj, "setFlexDirection", JS_NewCFunction(ctx, setFlexDirection, "setFlexDirection", 2)); JS_SetPropertyStr(ctx, global_obj, "calculateLayout", JS_NewCFunction(ctx, calculateLayout, "calculateLayout", 3)); JS_SetPropertyStr(ctx, global_obj, "getLayoutLeft", JS_NewCFunction(ctx, getLayoutLeft, "getLayoutLeft", 1)); JS_SetPropertyStr(ctx, global_obj, "getLayoutTop", JS_NewCFunction(ctx, getLayoutTop, "getLayoutTop", 1)); JS_SetPropertyStr(ctx, global_obj, "getLayoutWidth", JS_NewCFunction(ctx, getLayoutWidth, "getLayoutWidth", 1)); JS_SetPropertyStr(ctx, global_obj, "getLayoutHeight", JS_NewCFunction(ctx, getLayoutHeight, "getLayoutHeight", 1));
JS_FreeValue(ctx, global_obj); }
int main(int argc, char** argv) { JSRuntime* rt = JS_NewRuntime(); JSContext* ctx = JS_NewContext(rt);
registerJSFunctions(ctx);
// 读取并执行 JavaScript 代码 const char* js_code = R"( let root = createYogaNode(); setWidth(root, 300); setHeight(root, 300); setFlexDirection(root, 'column');
let child1 = createYogaNode(); setWidth(child1, 100); setHeight(child1, 100);
let child2 = createYogaNode(); setWidth(child2, 100); setHeight(child2, 100);
root.appendChild(child1); root.appendChild(child2);
calculateLayout(root, 300, 300);
console.log(`Left: ${getLayoutLeft(root)}, Top: ${getLayoutTop(root)}, Width: ${getLayoutWidth(root)}, Height: ${getLayoutHeight(root)}`); console.log(`Child1 Left: ${getLayoutLeft(child1)}, Top: ${getLayoutTop(child1)}, Width: ${getLayoutWidth(child1)}, Height: ${getLayoutHeight(child1)}`); console.log(`Child2 Left: ${getLayoutLeft(child2)}, Top: ${getLayoutTop(child2)}, Width: ${getLayoutWidth(child2)}, Height: ${getLayoutHeight(child2)}`); )";
JS_Eval(ctx, js_code, strlen(js_code), "<input>", JS_EVAL_TYPE_GLOBAL);
JS_FreeContext(ctx); JS_FreeRuntime(rt);
return 0; }
3. 编译和运行 编译上述 C 代码,并链接 QuickJS 和 Yoga 库。假设你已经编译并安装了 QuickJS 和 Yoga,可以使用以下命令进行编译:
gcc -o quickjs_yoga main.c -I/path/to/quickjs -I/path/to/yoga -L/path/to/quickjs -L/path/to/yoga -lquickjs -lyoga -lm
运行编译后的程序: ./quickjs_yoga
解释 初始化 Yoga 节点:
createYogaNode 函数创建一个新的 Yoga 节点。 setWidth 和 setHeight 函数设置节点的宽度和高度。 setFlexDirection 函数设置节点的 Flex 方向。 计算布局:
calculateLayout 函数计算节点的布局。 获取布局属性:
getLayoutLeft、getLayoutTop、getLayoutWidth 和 getLayoutHeight 函数获取节点的布局属性。 注册 JavaScript 函数:
registerJSFunctions 函数将 C 函数注册为 JavaScript 函数,使它们可以在 JavaScript 中调用。 执行 JavaScript 代码:
在 main 函数中,读取并执行 JavaScript 代码,创建和配置 Yoga 节点,并计算布局。 运行结果 当你运行上述程序时,JavaScript 代码将创建一个根节点和两个子节点,设置它们的布局属性,并计算布局。最终,程序将输出每个节点的布局属性。
总结 通过结合 QuickJS 和 Yoga,你可以在 JavaScript 中实现高效的布局管理,特别适合用于构建跨平台的应用程序。这种方式不仅提供了灵活的布局能力,还保持了高性能和低资源消耗。
yoga 编译安装 oga 编译安装指南 Yoga 是 Facebook 开发的一个跨平台的布局引擎,基于 Flexbox 布局算法。它支持多种平台,包括 iOS、Android、Web 和桌面应用。以下是如何在不同平台上编译和安装 Yoga 的详细步骤。 1. 获取 Yoga 源代码 首先,从 GitHub 上克隆 Yoga 仓库: sudo apt-get update sudo apt-get install cmake ninja-build
mkdir build cd build cmake -G Ninja .. ninja 编译完成后,你会在 build 目录下找到生成的库文件,例如 libyoga.a 或 libyoga.so。 Windows 使用 Visual Studio 命令行工具(例如 Developer Command Prompt for VS 2019): shmkdir build cd build cmake -G "Visual Studio 16 2019" -A x64 .. cmake --build . --config Release 编译完成后,你会在 build\Release 目录下找到生成的库文件,例如 yoga.lib。 4. 安装 Yoga Linux 和 macOS 将生成的库文件和头文件复制到适当的位置。例如,复制到 /usr/local/lib 和 /usr/local/include: shsudo cp build/libyoga.a /usr/local/lib/ sudo cp -r ../yoga /usr/local/include/ Windows 将生成的库文件和头文件复制到你的项目目录中。例如,复制到 C:\your_project\lib 和 C:\your_project\include: shcopy build\Release\yoga.lib C:\your_project\lib\ xcopy ..\yoga C:\your_project\include\yoga /E /I
5. 验证安装 创建一个简单的 C++ 程序来验证 Yoga 是否安装成功。 示例代码 创建一个 test_yoga.cpp 文件: cpp#include <iostream> #include <yoga/YGNode.h>
int main() { // 创建一个 Yoga 节点 YGNodeRef root = YGNodeNew(); YGNodeStyleSetWidth(root, 300); YGNodeStyleSetHeight(root, 300);
// 计算布局 YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
// 输出布局信息 std::cout << "Root node layout: " << "Left: " << YGNodeLayoutGetLeft(root) << ", " << "Top: " << YGNodeLayoutGetTop(root) << ", " << "Width: " << YGNodeLayoutGetWidth(root) << ", " << "Height: " << YGNodeLayoutGetHeight(root) << std::endl;
// 释放节点 YGNodeFreeRecursive(root);
return 0; }
编译和运行 Linux 和 macOS shg++ test_yoga.cpp -lyoga -o test_yoga ./test_yoga Windows 使用 Visual Studio 命令行工具: shcl /EHsc /I C:\your_project\include test_yoga.cpp /link /LIBPATH:C:\your_project\lib yoga.lib test_yoga.exe 总结 通过以上步骤,你可以在不同的平台上编译和安装 Yoga,并验证其是否安装成功。Yoga 提供了强大的布局能力,适用于多种应用场景,特别是需要跨平台布局的项目。
javascript 应该如何调用 在你的代码中,已经将 C/C++ 函数注册到了 QuickJS 的全局对象中,这样你就可以在 JavaScript 中直接调用这些函数。以下是如何在 JavaScript 中调用这些函数的详细步骤和示例: 1. 创建和配置 Yoga 节点 你已经在 main 函数中定义了一段 JavaScript 代码,用于创建和配置 Yoga 节点。以下是这段代码的详细解释: javascriptlet root = createYogaNode(); setWidth(root, 300); setHeight(root, 300); setFlexDirection(root, 'column'); createYogaNode():创建一个新的 Yoga 节点。 setWidth(root, 300):设置根节点的宽度为 300。 setHeight(root, 300):设置根节点的高度为 300。 setFlexDirection(root, 'column'):设置根节点的 Flex 方向为列方向。 2. 创建子节点并添加到根节点 javascriptlet child1 = createYogaNode(); setWidth(child1, 100); setHeight(child1, 100);
let child2 = createYogaNode(); setWidth(child2, 100); setHeight(child2, 100);
root.appendChild(child1); root.appendChild(child2); createYogaNode():创建两个子节点 child1 和 child2。 setWidth(child1, 100) 和 setHeight(child1, 100):设置 child1 的宽度和高度。 setWidth(child2, 100) 和 setHeight(child2, 100):设置 child2 的宽度和高度。 root.appendChild(child1) 和 root.appendChild(child2):将子节点添加到根节点中。 3. 计算布局 javascriptcalculateLayout(root, 300, 300); calculateLayout(root, 300, 300):计算根节点及其子节点的布局,给定的宽度和高度分别为 300。 4. 获取并输出布局属性 javascriptconsole.log(`Left: ${getLayoutLeft(root)}, Top: ${getLayoutTop(root)}, Width: ${getLayoutWidth(root)}, Height: ${getLayoutHeight(root)}`); console.log(`Child1 Left: ${getLayoutLeft(child1)}, Top: ${getLayoutTop(child1)}, Width: ${getLayoutWidth(child1)}, Height: ${getLayoutHeight(child1)}`); console.log(`Child2 Left: ${getLayoutLeft(child2)}, Top: ${getLayoutTop(child2)}, Width: ${getLayoutWidth(child2)}, Height: ${getLayoutHeight(child2)}`); getLayoutLeft(node):获取节点的左偏移。 getLayoutTop(node):获取节点的上偏移。 getLayoutWidth(node):获取节点的宽度。 getLayoutHeight(node):获取节点的高度。 console.log():输出节点的布局属性。 完整的 JavaScript 代码 javascriptlet root = createYogaNode(); setWidth(root, 300); setHeight(root, 300); setFlexDirection(root, 'column');
let child1 = createYogaNode(); setWidth(child1, 100); setHeight(child1, 100);
let child2 = createYogaNode(); setWidth(child2, 100); setHeight(child2, 100);
root.appendChild(child1); root.appendChild(child2);
calculateLayout(root, 300, 300);
console.log(`Left: ${getLayoutLeft(root)}, Top: ${getLayoutTop(root)}, Width: ${getLayoutWidth(root)}, Height: ${getLayoutHeight(root)}`); console.log(`Child1 Left: ${getLayoutLeft(child1)}, Top: ${getLayoutTop(child1)}, Width: ${getLayoutWidth(child1)}, Height: ${getLayoutHeight(child1)}`); console.log(`Child2 Left: ${getLayoutLeft(child2)}, Top: ${getLayoutTop(child2)}, Width: ${getLayoutWidth(child2)}, Height: ${getLayoutHeight(child2)}`); 运行结果 运行上述 JavaScript 代码后,你应该会看到类似以下的输出: Left: 0, Top: 0, Width: 300, Height: 300 Child1 Left: 0, Top: 0, Width: 100, Height: 100 Child2 Left: 0, Top: 100, Width: 100, Height: 100 这表明 Yoga 节点的布局已经正确计算并输出。你可以根据需要修改 JavaScript 代码,以实现不同的布局效果。
|