1e41f4b71Sopenharmony_ci# RenderNode 2e41f4b71Sopenharmony_ci 3e41f4b71Sopenharmony_ci## Overview 4e41f4b71Sopenharmony_ci 5e41f4b71Sopenharmony_ciFor third-party frameworks that do not have their own rendering environment, although they have implemented frontend parsing and processing for layout and events, they rely on the system's basic rendering and animation capabilities. The universal attributes and events on [FrameNode](./arkts-user-defined-arktsNode-frameNode.md) are superfluous for such frameworks, leading to redundant operations, including handling logic for layout and events. 6e41f4b71Sopenharmony_ci 7e41f4b71Sopenharmony_ciThis is where [RenderNode](../reference/apis-arkui/js-apis-arkui-renderNode.md) comes into the picture. **RenderNode** is a more lightweight rendering node that includes only rendering-related capabilities. It exposes the capability to set basic rendering attributes and provides capabilities for dynamically adding or removing nodes, as well as custom drawing. This can supply third-party frameworks with basic rendering and animation functionalities. 8e41f4b71Sopenharmony_ci 9e41f4b71Sopenharmony_ci## Creating and Removing Nodes 10e41f4b71Sopenharmony_ci 11e41f4b71Sopenharmony_ciYou can create and remove nodes with **RenderNode**. You can create a custom instance of **RenderNode** using its constructor, and the instance thereby created corresponds to an entity node. You can use the **dispose** API in **RenderNode** to break the binding with the entity node. 12e41f4b71Sopenharmony_ci 13e41f4b71Sopenharmony_ci## Operating the Node Tree 14e41f4b71Sopenharmony_ci 15e41f4b71Sopenharmony_ciWith **RenderNode**, you can add, delete, query, and modify nodes, thereby changing the subtree structure of nodes; you can also query the parent-child relationships to obtain the results. 16e41f4b71Sopenharmony_ci 17e41f4b71Sopenharmony_ci> **NOTE** 18e41f4b71Sopenharmony_ci> 19e41f4b71Sopenharmony_ci> - The subtree structure obtained through queries in **RenderNode** is constructed based on the parameters passed through the APIs of **RenderNode**. 20e41f4b71Sopenharmony_ci> 21e41f4b71Sopenharmony_ci> - To display a RenderNode in conjunction with built-in components, you need to mount the RenderNode obtained from a FrameNode onto the component tree. 22e41f4b71Sopenharmony_ci 23e41f4b71Sopenharmony_ci## Setting and Obtaining Rendering-related Properties 24e41f4b71Sopenharmony_ci 25e41f4b71Sopenharmony_ciIn **RenderNode**, you can set rendering-related properties, such as **backgroundColor**, **clipToFrame**, and **opacity**. For details about the supported attributes, see [RenderNode](../reference/apis-arkui/js-apis-arkui-renderNode.md#rendernode). 26e41f4b71Sopenharmony_ci 27e41f4b71Sopenharmony_ci> **NOTE** 28e41f4b71Sopenharmony_ci> 29e41f4b71Sopenharmony_ci> - The properties obtained from a query in **RenderNode** are the values that have been explicitly set. 30e41f4b71Sopenharmony_ci> 31e41f4b71Sopenharmony_ci> - If no parameters are provided or if the provided parameters are invalid, the query will return the default values. 32e41f4b71Sopenharmony_ci> 33e41f4b71Sopenharmony_ci> - Avoid modifying RenderNodes in a BuilderNode. 34e41f4b71Sopenharmony_ci 35e41f4b71Sopenharmony_ci```ts 36e41f4b71Sopenharmony_ciimport { FrameNode, NodeController, RenderNode } from '@kit.ArkUI'; 37e41f4b71Sopenharmony_ci 38e41f4b71Sopenharmony_ciconst renderNode = new RenderNode(); 39e41f4b71Sopenharmony_cirenderNode.frame = { x: 0, y: 0, width: 200, height: 350 }; 40e41f4b71Sopenharmony_cirenderNode.backgroundColor = 0xffff0000; 41e41f4b71Sopenharmony_cifor (let i = 0; i < 5; i++) { 42e41f4b71Sopenharmony_ci const node = new RenderNode(); 43e41f4b71Sopenharmony_ci // Set the frame size of the node. 44e41f4b71Sopenharmony_ci node.frame = { x: 10, y: 10 + 60 * i, width: 50, height: 50 }; 45e41f4b71Sopenharmony_ci // Set the background color of the node. 46e41f4b71Sopenharmony_ci node.backgroundColor = 0xff00ff00; 47e41f4b71Sopenharmony_ci // Mount the new node to the RenderNode. 48e41f4b71Sopenharmony_ci renderNode.appendChild(node); 49e41f4b71Sopenharmony_ci} 50e41f4b71Sopenharmony_ci 51e41f4b71Sopenharmony_ciclass MyNodeController extends NodeController { 52e41f4b71Sopenharmony_ci private rootNode: FrameNode | null = null; 53e41f4b71Sopenharmony_ci 54e41f4b71Sopenharmony_ci makeNode(uiContext: UIContext): FrameNode | null { 55e41f4b71Sopenharmony_ci this.rootNode = new FrameNode(uiContext); 56e41f4b71Sopenharmony_ci 57e41f4b71Sopenharmony_ci const rootRenderNode = this.rootNode?.getRenderNode(); 58e41f4b71Sopenharmony_ci if (rootRenderNode) { 59e41f4b71Sopenharmony_ci rootRenderNode.appendChild(renderNode); 60e41f4b71Sopenharmony_ci } 61e41f4b71Sopenharmony_ci return this.rootNode; 62e41f4b71Sopenharmony_ci } 63e41f4b71Sopenharmony_ci} 64e41f4b71Sopenharmony_ci 65e41f4b71Sopenharmony_ci@Entry 66e41f4b71Sopenharmony_ci@Component 67e41f4b71Sopenharmony_cistruct Index { 68e41f4b71Sopenharmony_ci private myNodeController: MyNodeController = new MyNodeController(); 69e41f4b71Sopenharmony_ci 70e41f4b71Sopenharmony_ci build() { 71e41f4b71Sopenharmony_ci Row() { 72e41f4b71Sopenharmony_ci NodeContainer(this.myNodeController) 73e41f4b71Sopenharmony_ci .width(200) 74e41f4b71Sopenharmony_ci .height(350) 75e41f4b71Sopenharmony_ci Button('getNextSibling') 76e41f4b71Sopenharmony_ci .onClick(() => { 77e41f4b71Sopenharmony_ci const child = renderNode.getChild(1); 78e41f4b71Sopenharmony_ci const nextSibling = child!.getNextSibling() 79e41f4b71Sopenharmony_ci if (child === null || nextSibling === null) { 80e41f4b71Sopenharmony_ci console.log('the child or nextChild is null'); 81e41f4b71Sopenharmony_ci } else { 82e41f4b71Sopenharmony_ci // Obtain the position of the child node. 83e41f4b71Sopenharmony_ci console.log(`the position of child is x: ${child.position.x}, y: ${child.position.y}, ` + 84e41f4b71Sopenharmony_ci `the position of nextSibling is x: ${nextSibling.position.x}, y: ${nextSibling.position.y}`); 85e41f4b71Sopenharmony_ci } 86e41f4b71Sopenharmony_ci }) 87e41f4b71Sopenharmony_ci } 88e41f4b71Sopenharmony_ci } 89e41f4b71Sopenharmony_ci} 90e41f4b71Sopenharmony_ci``` 91e41f4b71Sopenharmony_ci 92e41f4b71Sopenharmony_ci## Using Custom Drawing 93e41f4b71Sopenharmony_ci 94e41f4b71Sopenharmony_ciOverride the [draw](../reference/apis-arkui/js-apis-arkui-renderNode.md#draw) API in **RenderNode** to customize the drawing content and use the [invalidate](../reference/apis-arkui/js-apis-arkui-renderNode.md#invalidate) API to manually trigger a redraw of the node. 95e41f4b71Sopenharmony_ci 96e41f4b71Sopenharmony_ci> **NOTE** 97e41f4b71Sopenharmony_ci> 98e41f4b71Sopenharmony_ci> - Triggering multiple **invalidate** calls at once will only result in a single redraw. 99e41f4b71Sopenharmony_ci> 100e41f4b71Sopenharmony_ci> - Custom drawing can be implemented by calling ArkTS APIs or Node-APIs. 101e41f4b71Sopenharmony_ci 102e41f4b71Sopenharmony_ci**ArkTS API sample code** 103e41f4b71Sopenharmony_ci 104e41f4b71Sopenharmony_ci```ts 105e41f4b71Sopenharmony_ciimport { FrameNode, NodeController, RenderNode } from '@kit.ArkUI'; 106e41f4b71Sopenharmony_ciimport { drawing } from '@kit.ArkGraphics2D'; 107e41f4b71Sopenharmony_ci 108e41f4b71Sopenharmony_ciclass MyRenderNode extends RenderNode { 109e41f4b71Sopenharmony_ci draw(context: DrawContext) { 110e41f4b71Sopenharmony_ci // Obtain the canvas object. 111e41f4b71Sopenharmony_ci const canvas = context.canvas; 112e41f4b71Sopenharmony_ci // Create a brush. 113e41f4b71Sopenharmony_ci const brush = new drawing.Brush(); 114e41f4b71Sopenharmony_ci // Set the brush color. 115e41f4b71Sopenharmony_ci brush.setColor({ alpha: 255, red: 255, green: 0, blue: 0 }); 116e41f4b71Sopenharmony_ci canvas.attachBrush(brush); 117e41f4b71Sopenharmony_ci // Draw a rectangle. 118e41f4b71Sopenharmony_ci canvas.drawRect({ left: 0, right: 200, top: 0, bottom: 200 }); 119e41f4b71Sopenharmony_ci canvas.detachBrush(); 120e41f4b71Sopenharmony_ci } 121e41f4b71Sopenharmony_ci} 122e41f4b71Sopenharmony_ci 123e41f4b71Sopenharmony_ciconst renderNode = new MyRenderNode(); 124e41f4b71Sopenharmony_cirenderNode.frame = { x: 0, y: 0, width: 300, height: 300 }; 125e41f4b71Sopenharmony_cirenderNode.backgroundColor = 0xff0000ff; 126e41f4b71Sopenharmony_cirenderNode.opacity = 0.5; 127e41f4b71Sopenharmony_ci 128e41f4b71Sopenharmony_ciclass MyNodeController extends NodeController { 129e41f4b71Sopenharmony_ci private rootNode: FrameNode | null = null; 130e41f4b71Sopenharmony_ci 131e41f4b71Sopenharmony_ci makeNode(uiContext: UIContext): FrameNode | null { 132e41f4b71Sopenharmony_ci this.rootNode = new FrameNode(uiContext); 133e41f4b71Sopenharmony_ci 134e41f4b71Sopenharmony_ci const rootRenderNode = this.rootNode?.getRenderNode(); 135e41f4b71Sopenharmony_ci if (rootRenderNode !== null) { 136e41f4b71Sopenharmony_ci rootRenderNode.frame = { x: 0, y: 0, width: 500, height: 500 } 137e41f4b71Sopenharmony_ci rootRenderNode.appendChild(renderNode); 138e41f4b71Sopenharmony_ci } 139e41f4b71Sopenharmony_ci 140e41f4b71Sopenharmony_ci return this.rootNode; 141e41f4b71Sopenharmony_ci } 142e41f4b71Sopenharmony_ci} 143e41f4b71Sopenharmony_ci 144e41f4b71Sopenharmony_ci@Entry 145e41f4b71Sopenharmony_ci@Component 146e41f4b71Sopenharmony_cistruct Index { 147e41f4b71Sopenharmony_ci private myNodeController: MyNodeController = new MyNodeController(); 148e41f4b71Sopenharmony_ci 149e41f4b71Sopenharmony_ci build() { 150e41f4b71Sopenharmony_ci Column() { 151e41f4b71Sopenharmony_ci NodeContainer(this.myNodeController) 152e41f4b71Sopenharmony_ci .width('100%') 153e41f4b71Sopenharmony_ci Button('Invalidate') 154e41f4b71Sopenharmony_ci .onClick(() => { 155e41f4b71Sopenharmony_ci // Triggering multiple invalidate calls at once will only result in a single redraw. 156e41f4b71Sopenharmony_ci renderNode.invalidate(); 157e41f4b71Sopenharmony_ci renderNode.invalidate(); 158e41f4b71Sopenharmony_ci }) 159e41f4b71Sopenharmony_ci } 160e41f4b71Sopenharmony_ci } 161e41f4b71Sopenharmony_ci} 162e41f4b71Sopenharmony_ci``` 163e41f4b71Sopenharmony_ci 164e41f4b71Sopenharmony_ci**Node-API sample code** 165e41f4b71Sopenharmony_ci 166e41f4b71Sopenharmony_ciThe C++ side can obtain the canvas through the Node-API and perform subsequent custom drawing operations. 167e41f4b71Sopenharmony_ci 168e41f4b71Sopenharmony_ci```c++ 169e41f4b71Sopenharmony_ci// native_bridge.cpp 170e41f4b71Sopenharmony_ci#include "napi/native_api.h" 171e41f4b71Sopenharmony_ci#include <native_drawing/drawing_canvas.h> 172e41f4b71Sopenharmony_ci#include <native_drawing/drawing_color.h> 173e41f4b71Sopenharmony_ci#include <native_drawing/drawing_path.h> 174e41f4b71Sopenharmony_ci#include <native_drawing/drawing_pen.h> 175e41f4b71Sopenharmony_ci 176e41f4b71Sopenharmony_cistatic napi_value OnDraw(napi_env env, napi_callback_info info) 177e41f4b71Sopenharmony_ci{ 178e41f4b71Sopenharmony_ci size_t argc = 4; 179e41f4b71Sopenharmony_ci napi_value args[4] = { nullptr }; 180e41f4b71Sopenharmony_ci napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); 181e41f4b71Sopenharmony_ci 182e41f4b71Sopenharmony_ci int32_t id; 183e41f4b71Sopenharmony_ci napi_get_value_int32(env, args[0], &id); 184e41f4b71Sopenharmony_ci 185e41f4b71Sopenharmony_ci // Obtain the pointer to the canvas. 186e41f4b71Sopenharmony_ci void* temp = nullptr; 187e41f4b71Sopenharmony_ci napi_unwrap(env, args[1], &temp); 188e41f4b71Sopenharmony_ci OH_Drawing_Canvas *canvas = reinterpret_cast<OH_Drawing_Canvas*>(temp); 189e41f4b71Sopenharmony_ci 190e41f4b71Sopenharmony_ci // Obtain the canvas width. 191e41f4b71Sopenharmony_ci int32_t width; 192e41f4b71Sopenharmony_ci napi_get_value_int32(env, args[2], &width); 193e41f4b71Sopenharmony_ci 194e41f4b71Sopenharmony_ci // Obtain the canvas height. 195e41f4b71Sopenharmony_ci int32_t height; 196e41f4b71Sopenharmony_ci napi_get_value_int32(env, args[3], &height); 197e41f4b71Sopenharmony_ci 198e41f4b71Sopenharmony_ci // Pass in information such as the canvas, height, and width to the drawing API for custom drawing. 199e41f4b71Sopenharmony_ci auto path = OH_Drawing_PathCreate(); 200e41f4b71Sopenharmony_ci OH_Drawing_PathMoveTo(path, width / 4, height / 4); 201e41f4b71Sopenharmony_ci OH_Drawing_PathLineTo(path, width * 3 / 4, height / 4); 202e41f4b71Sopenharmony_ci OH_Drawing_PathLineTo(path, width * 3 / 4, height * 3 / 4); 203e41f4b71Sopenharmony_ci OH_Drawing_PathLineTo(path, width / 4, height * 3 / 4); 204e41f4b71Sopenharmony_ci OH_Drawing_PathLineTo(path, width / 4, height / 4); 205e41f4b71Sopenharmony_ci OH_Drawing_PathClose(path); 206e41f4b71Sopenharmony_ci 207e41f4b71Sopenharmony_ci auto pen = OH_Drawing_PenCreate(); 208e41f4b71Sopenharmony_ci OH_Drawing_PenSetWidth(pen, 10); 209e41f4b71Sopenharmony_ci OH_Drawing_PenSetColor(pen, OH_Drawing_ColorSetArgb(0xFF, 0xFF, 0x00, 0x00)); 210e41f4b71Sopenharmony_ci OH_Drawing_CanvasAttachPen(canvas, pen); 211e41f4b71Sopenharmony_ci 212e41f4b71Sopenharmony_ci OH_Drawing_CanvasDrawPath(canvas, path); 213e41f4b71Sopenharmony_ci 214e41f4b71Sopenharmony_ci return nullptr; 215e41f4b71Sopenharmony_ci} 216e41f4b71Sopenharmony_ci 217e41f4b71Sopenharmony_ciEXTERN_C_START 218e41f4b71Sopenharmony_cistatic napi_value Init(napi_env env, napi_value exports) 219e41f4b71Sopenharmony_ci{ 220e41f4b71Sopenharmony_ci napi_property_descriptor desc[] = { 221e41f4b71Sopenharmony_ci { "nativeOnDraw", nullptr, OnDraw, nullptr, nullptr, nullptr, napi_default, nullptr } 222e41f4b71Sopenharmony_ci }; 223e41f4b71Sopenharmony_ci napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc); 224e41f4b71Sopenharmony_ci return exports; 225e41f4b71Sopenharmony_ci} 226e41f4b71Sopenharmony_ciEXTERN_C_END 227e41f4b71Sopenharmony_ci 228e41f4b71Sopenharmony_cistatic napi_module demoModule = { 229e41f4b71Sopenharmony_ci .nm_version =1, 230e41f4b71Sopenharmony_ci .nm_flags = 0, 231e41f4b71Sopenharmony_ci .nm_filename = nullptr, 232e41f4b71Sopenharmony_ci .nm_register_func = Init, 233e41f4b71Sopenharmony_ci .nm_modname = "entry", 234e41f4b71Sopenharmony_ci .nm_priv = ((void*)0), 235e41f4b71Sopenharmony_ci .reserved = { 0 }, 236e41f4b71Sopenharmony_ci}; 237e41f4b71Sopenharmony_ci 238e41f4b71Sopenharmony_ciextern "C" __attribute__((constructor)) void RegisterEntryModule(void) 239e41f4b71Sopenharmony_ci{ 240e41f4b71Sopenharmony_ci napi_module_register(&demoModule); 241e41f4b71Sopenharmony_ci} 242e41f4b71Sopenharmony_ci``` 243e41f4b71Sopenharmony_ci 244e41f4b71Sopenharmony_ciAdd the following content to the **src/main/cpp/CMakeLists.txt** file of the project: 245e41f4b71Sopenharmony_ci```cmake 246e41f4b71Sopenharmony_ci# the minimum version of CMake. 247e41f4b71Sopenharmony_cicmake_minimum_required(VERSION 3.4.1) 248e41f4b71Sopenharmony_ciproject(NapiTest) 249e41f4b71Sopenharmony_ci 250e41f4b71Sopenharmony_ciset(NATIVERENDER_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR}) 251e41f4b71Sopenharmony_ci 252e41f4b71Sopenharmony_ciinclude_directories(${NATIVERENDER_ROOT_PATH} 253e41f4b71Sopenharmony_ci ${NATIVERENDER_ROOT_PATH}/include) 254e41f4b71Sopenharmony_ci 255e41f4b71Sopenharmony_ciadd_library(entry SHARED native_bridge.cpp) 256e41f4b71Sopenharmony_citarget_link_libraries(entry PUBLIC libace_napi.z.so) 257e41f4b71Sopenharmony_citarget_link_libraries(entry PUBLIC libace_ndk.z.so) 258e41f4b71Sopenharmony_citarget_link_libraries(entry PUBLIC libnative_drawing.so) 259e41f4b71Sopenharmony_ci``` 260e41f4b71Sopenharmony_ci 261e41f4b71Sopenharmony_ciAdd the definition of the custom drawing API on the ArkTS side to the **src/main/cpp/types/libentry/index.d.ts** file of the project. The following is an example: 262e41f4b71Sopenharmony_ci```ts 263e41f4b71Sopenharmony_ciimport { DrawContext } from '@kit.ArkUI' 264e41f4b71Sopenharmony_ci 265e41f4b71Sopenharmony_ciexport const nativeOnDraw: (id: number, context: DrawContext, width: number, height: number) => number; 266e41f4b71Sopenharmony_ci``` 267e41f4b71Sopenharmony_ci 268e41f4b71Sopenharmony_ciCode in ArkTS: 269e41f4b71Sopenharmony_ci 270e41f4b71Sopenharmony_ci```ts 271e41f4b71Sopenharmony_ci// Index.ets 272e41f4b71Sopenharmony_ciimport bridge from "libentry.so" // This .so file is written and generated by Node-API. 273e41f4b71Sopenharmony_ciimport { DrawContext, FrameNode, NodeController, RenderNode } from '@kit.ArkUI' 274e41f4b71Sopenharmony_ci 275e41f4b71Sopenharmony_ciclass MyRenderNode extends RenderNode { 276e41f4b71Sopenharmony_ci draw(context: DrawContext) { 277e41f4b71Sopenharmony_ci // The width and height in the context need to be converted from vp to px. 278e41f4b71Sopenharmony_ci bridge.nativeOnDraw(0, context, vp2px(context.size.height), vp2px(context.size.width)); 279e41f4b71Sopenharmony_ci } 280e41f4b71Sopenharmony_ci} 281e41f4b71Sopenharmony_ci 282e41f4b71Sopenharmony_ciclass MyNodeController extends NodeController { 283e41f4b71Sopenharmony_ci private rootNode: FrameNode | null = null; 284e41f4b71Sopenharmony_ci 285e41f4b71Sopenharmony_ci makeNode(uiContext: UIContext): FrameNode | null { 286e41f4b71Sopenharmony_ci this.rootNode = new FrameNode(uiContext); 287e41f4b71Sopenharmony_ci 288e41f4b71Sopenharmony_ci const rootRenderNode = this.rootNode.getRenderNode(); 289e41f4b71Sopenharmony_ci if (rootRenderNode !== null) { 290e41f4b71Sopenharmony_ci const renderNode = new MyRenderNode(); 291e41f4b71Sopenharmony_ci renderNode.size = { width: 100, height: 100 } 292e41f4b71Sopenharmony_ci rootRenderNode.appendChild(renderNode); 293e41f4b71Sopenharmony_ci } 294e41f4b71Sopenharmony_ci return this.rootNode; 295e41f4b71Sopenharmony_ci } 296e41f4b71Sopenharmony_ci} 297e41f4b71Sopenharmony_ci 298e41f4b71Sopenharmony_ci@Entry 299e41f4b71Sopenharmony_ci@Component 300e41f4b71Sopenharmony_cistruct Index { 301e41f4b71Sopenharmony_ci private myNodeController: MyNodeController = new MyNodeController(); 302e41f4b71Sopenharmony_ci 303e41f4b71Sopenharmony_ci build() { 304e41f4b71Sopenharmony_ci Row() { 305e41f4b71Sopenharmony_ci NodeContainer(this.myNodeController) 306e41f4b71Sopenharmony_ci } 307e41f4b71Sopenharmony_ci } 308e41f4b71Sopenharmony_ci} 309e41f4b71Sopenharmony_ci``` 310e41f4b71Sopenharmony_ci 311e41f4b71Sopenharmony_ci## Setting the Label 312e41f4b71Sopenharmony_ci 313e41f4b71Sopenharmony_ciYou can use the [label](../reference/apis-arkui/js-apis-arkui-renderNode.md#label12) API to set label information for **FrameNode**, which makes it easier to identify nodes in the node Inspector. 314e41f4b71Sopenharmony_ci 315e41f4b71Sopenharmony_ci```ts 316e41f4b71Sopenharmony_ciimport { RenderNode, FrameNode, NodeController, UIContext } from '@kit.ArkUI'; 317e41f4b71Sopenharmony_ci 318e41f4b71Sopenharmony_ciclass MyNodeController extends NodeController { 319e41f4b71Sopenharmony_ci private rootNode: FrameNode | null = null; 320e41f4b71Sopenharmony_ci 321e41f4b71Sopenharmony_ci makeNode(uiContext: UIContext): FrameNode | null { 322e41f4b71Sopenharmony_ci this.rootNode = new FrameNode(uiContext); 323e41f4b71Sopenharmony_ci const renderNode: RenderNode | null = this.rootNode.getRenderNode(); 324e41f4b71Sopenharmony_ci if (renderNode !== null) { 325e41f4b71Sopenharmony_ci const renderChildNode: RenderNode = new RenderNode(); 326e41f4b71Sopenharmony_ci renderChildNode.frame = { x: 0, y: 0, width: 100, height: 100 }; 327e41f4b71Sopenharmony_ci renderChildNode.backgroundColor = 0xffff0000; 328e41f4b71Sopenharmony_ci renderChildNode.label = 'customRenderChildNode'; 329e41f4b71Sopenharmony_ci console.log('label:', renderChildNode.label); 330e41f4b71Sopenharmony_ci renderNode.appendChild(renderChildNode); 331e41f4b71Sopenharmony_ci } 332e41f4b71Sopenharmony_ci 333e41f4b71Sopenharmony_ci return this.rootNode; 334e41f4b71Sopenharmony_ci } 335e41f4b71Sopenharmony_ci} 336e41f4b71Sopenharmony_ci 337e41f4b71Sopenharmony_ci@Entry 338e41f4b71Sopenharmony_ci@Component 339e41f4b71Sopenharmony_cistruct Index { 340e41f4b71Sopenharmony_ci private myNodeController: MyNodeController = new MyNodeController(); 341e41f4b71Sopenharmony_ci 342e41f4b71Sopenharmony_ci build() { 343e41f4b71Sopenharmony_ci Column() { 344e41f4b71Sopenharmony_ci NodeContainer(this.myNodeController) 345e41f4b71Sopenharmony_ci .width(300) 346e41f4b71Sopenharmony_ci .height(700) 347e41f4b71Sopenharmony_ci .backgroundColor(Color.Gray) 348e41f4b71Sopenharmony_ci } 349e41f4b71Sopenharmony_ci } 350e41f4b71Sopenharmony_ci} 351e41f4b71Sopenharmony_ci``` 352