HarmonyOS 鸿蒙Next @ohos.graphics.drawing绘制模块中的RenderNode怎么制定坐标绘制图片

发布于 1周前 作者 zlyuanteng 最后一次编辑是 5天前 来自 鸿蒙OS

HarmonyOS 鸿蒙Next @ohos.graphics.drawing绘制模块中的RenderNode怎么制定坐标绘制图片
<markdown _ngcontent-uos-c149="" class="markdownPreContainer">

在RenderNode节点中添加一个自定义的图片节点,想把图片绘制到容器的中央,无法拿确定中心点坐标,怎么能绘制到中心去呢

2 回复

可以使用componentUtils获取组件属性自己去计算 https://developer.huawei.com/consumer/cn/doc/harmonyos-references-V5/js-apis-arkui-componentutils-V5 demo参考:

//index.ets
import { ImageRenderNode, MyNodeController, MyRenderNode } from '../RenderNodeModel';
import inspector from '@ohos.arkui.inspector';
import { image } from '@kit.ImageKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
import { componentUtils } from '@kit.ArkUI';

const NODE_CONTAINER_ID = 'root';

@Entry
@Component
struct Index {
private myNodeController: MyNodeController = new MyNodeController();
private currentNode: MyRenderNode | null = null; // 当前正在绘制的节点
listener: inspector.ComponentObserver = inspector.createComponentObserver(NODE_CONTAINER_ID)

aboutToAppear(): void {
let onLayoutComplete: () => void = async (): Promise<void> => {
let value = componentUtils.getRectangleById(NODE_CONTAINER_ID)
console.log('xxxx:' + JSON.stringify(value));
let valueW = value.size.width;
let valueH = value.size.height;
//获取pixelMap
hilog.error(0x0000, "tag", "组件布局完成")
let resourceManager = getContext().resourceManager;
let uint8Array = resourceManager.getRawFileContentSync('ardilla1.png');
let pixelMap = await image.createImageSource(uint8Array.buffer).createPixelMap();
pixelMap.getImageInfo().then((imageInfo: image.ImageInfo) => {
if (imageInfo == undefined) {
console.error(`Failed to obtain the image pixel map information.`);
}
let wit = imageInfo.size.width;
let hig = imageInfo.size.height;
console.log(`Succeeded in obtaining the image pixel map information., ${JSON.stringify(wit)}, ${JSON.stringify(hig)}`);
let imageNode = new ImageRenderNode(pixelMap, valueW / 2 - wit/2, valueH / 2-hig/2)
imageNode.frame = {
x: 0,
y: 0,
width: this.myNodeController.width,
height: this.myNodeController.height
};
this.myNodeController.rootRenderNode?.appendChild(imageNode)
})
}
// this.listener.on('layout', onLayoutComplete)
this.listener.on('draw', onLayoutComplete)
}

build() {
Column() {
NodeContainer(this.myNodeController)
.width('100%')
.height('100%')
.id(NODE_CONTAINER_ID)
.key(NODE_CONTAINER_ID)
.onTouch((event: TouchEvent) => {
this.onTouchEvent(event);
})
}
.border({
width: 1,
style: BorderStyle.Dashed
})
.margin({
top: 30,
bottom: 30,
right: 20,
left: 20
})
}

/**
* touch事件触发后绘制手指移动轨迹
*/
onTouchEvent(event: TouchEvent): void {
// 获取手指触摸位置的坐标点
const positionX: number = vp2px(event.touches[0].x);
const positionY: number = vp2px(event.touches[0].y);
switch (event.type) {
case TouchType.Down: {
// 每次手指按下,创建一个MyRenderNode对象,用于记录和绘制手指移动的轨迹
const newNode = new MyRenderNode();
// 定义newNode的大小和位置,位置从组件NodeContainer的左上角(0,0)坐标开始,大小为NodeContainer的宽高
newNode.frame = {
x: 0,
y: 0,
width: this.myNodeController.width,
height: this.myNodeController.height
};
this.currentNode = newNode;
// 移动新节点中的路径path到手指按下的坐标点
this.currentNode.path.moveTo(positionX, positionY);
if (this.myNodeController.rootRenderNode !== null) {
// appendChild在renderNode最后一个子节点后添加新的子节点
this.myNodeController.rootRenderNode.appendChild(this.currentNode);
}
break;
}
case TouchType.Move: {
if (this.currentNode !== null) {
// 手指移动,绘制移动轨迹
this.currentNode.path.lineTo(positionX, positionY);
// 节点的path更新后需要调用invalidate()方法触发重新渲染
this.currentNode.invalidate();
}
break;
}
case TouchType.Up: {
// 手指抬起,释放this.currentNode
this.currentNode = null;
}
default: {
break;
}
}
}
}
//RenderNodeModel.ets

import { DrawContext, FrameNode, NodeController, RenderNode, Size } from '@kit.ArkUI';
import { common2D, drawing } from '@kit.ArkGraphics2D';
import { image } from '@kit.ImageKit';

export class ImageRenderNode extends RenderNode {
pixelMap?: image.PixelMap = undefined;
xLeft: number = 0;
yTop: number = 0;

constructor(pixelMap: image.PixelMap, x: number, y: number) {
super();
this.pixelMap = pixelMap;
this.xLeft = x;
this.yTop = y;
}

draw(context: DrawContext) {
context.canvas.drawImage(this.pixelMap, this.xLeft, this.yTop)
}
}

/**
* MyRenderNode类,初始化画笔和绘制路径
*/
export class MyRenderNode extends RenderNode {
path: drawing.Path = new drawing.Path(); // 新建路径对象,用于绘制手指移动轨迹
penWidth: number = 10
isErase: boolean = false;
rote = 0
pen_color: common2D.Color = {
alpha: 255,
red: 255,
green: 0,
blue: 0
}

// RenderNode进行绘制时会调用draw方法
async draw(context: DrawContext): Promise<void> {
const canvas = context.canvas;
// 创建一个画笔Pen对象,Pen对象用于形状的边框线绘制
const pen = new drawing.Pen();
// 设置画笔开启反走样,可以使得图形的边缘在显示时更平滑
pen.setAntiAlias(true);
// 设置画笔的线宽为5px
pen.setStrokeWidth(this.penWidth);
pen.setDither(true);
pen.setColor(this.pen_color)

// 将Pen画笔设置到canvas中
canvas.attachPen(pen);
// 绘制path
canvas.drawPath(this.path);
canvas.detachPen();
}
}

/**
* NodeController的子类MyNodeController
*/
export class MyNodeController extends NodeController {
private rootNode: FrameNode | null = null; // 根节点
rootRenderNode: RenderNode | null = null; // 从NodeController根节点获取的RenderNode,用于添加和删除新创建的MyRenderNode实例
width: number = 0; // 实例绑定的NodeContainer组件的宽,单位px
height: number = 0; // 实例绑定的NodeContainer组件的宽,单位px

// MyNodeController实例绑定的NodeContainer创建时触发,创建根节点rootNode并将其挂载至NodeContainer
makeNode(uiContext: UIContext): FrameNode {
this.rootNode = new FrameNode(uiContext);
if (this.rootNode !== null) {
this.rootRenderNode = this.rootNode.getRenderNode();
}
return this.rootNode;
}

// 绑定的NodeContainer布局时触发,获取NodeContainer的宽高
aboutToResize(size: Size): void {
this.width = size.width;
this.height = size.height;
// 设置画布底色为白色
if (this.rootRenderNode !== null) {
// NodeContainer布局完成后设置rootRenderNode的背景色为白色
this.rootRenderNode.backgroundColor = 0XFFFFFFFF;
// rootRenderNode的位置从组件NodeContainer的左上角(0,0)坐标开始,大小为NodeContainer的宽高
this.rootRenderNode.frame = {
x: 0,
y: 0,
width: this.width,
height: this.height
};
}
}
}

更多关于HarmonyOS 鸿蒙Next @ohos.graphics.drawing绘制模块中的RenderNode怎么制定坐标绘制图片的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


在HarmonyOS鸿蒙系统的@ohos.graphics.drawing绘制模块中,RenderNode是一个用于高效管理和绘制复杂图形的核心类。若要使用RenderNode来制定坐标绘制图片,你通常需要执行以下步骤:

  1. 创建RenderNode:首先,你需要创建一个RenderNode实例。这可以通过调用Canvas类的createRenderNode方法实现。

  2. 获取Canvas:接着,你需要获取一个Canvas对象,这通常在你的自定义组件或视图的onDraw方法中进行。

  3. 绘制内容到RenderNode:使用CanvassaveLayersave方法保存当前状态,然后设置所需的变换(如平移、缩放等)以定位图片。之后,将图片绘制到Canvas上,此时实际是绘制到RenderNode中。

  4. 将RenderNode添加到父节点:最后,将绘制好的RenderNode通过父组件的绘制逻辑添加到视图树中。

注意,坐标系的设置和调整是关键,你可以通过Canvas的变换方法(如translate, scale, rotate等)来精确定位图片。

如果问题依旧没法解决请联系官网客服,官网地址是:https://www.itying.com/category-93-b0.html

回到顶部