Closed MarcusOy closed 1 year ago
I think the only solution is to use Portals. What did you try? What is the issue with "but this also ignores the parent Group"?
I think the only solution is to use Portals. What did you try? What is the issue with "but this also ignores the parent Group"?
I tried the following:
<Group draggable x={props.x} y={props.y}>
<Portal selector=".layer-circles">
<Circle />
</Portal>
<Portal selector=".layer-wedges">
<Wedge />
</Portal>
...
</Group>
Then to put them back together at the stage level:
<Stage>
<Layer name="layer-wedges"/>
<Layer name="layer-circles"/>
</Stage>
The group did not respond to drag attempts. Also, I had a test with n
complex components, but only the first (or last) component rendered.
Please make a small demo. I think you need to put only circles into the portal.
Please make a small demo. I think you need to put only circles into the portal.
I put together a small demo: https://codesandbox.io/p/sandbox/icy-shape-352chk
Within this demo, I’ve created the hypothetical component (from above) in two ways: the standard way, then with portals. You can see the traditional konva-react
components rendered on x=100 behaving as normal. You can see the “portalized” components (which are supposed to be on x=200) bunched up into the top left corner (hence ignoring parent group transformations)
Also, I want to be able to do this for any number of layers (which is why I'm doing both the Circle and Wedge).
Lastly, I appreciate your time on this. You've done an awesome job creating this library!
Not very elegant. But this may work:
const PortaledComplexComponent = (props) => {
const [pos, setPos] = React.useState({ x: props.x, y: props.y });
// sync local state with props
React.useEffect(() => {
setPos({ x: props.x, y: props.y });
}, [props.x, props.y]);
const handleDragMove = (e) => {
setPos(e.target.position());
};
return (
<Group x={pos.x} y={pos.y} draggable onDragMove={handleDragMove}>
<Wedge radius={80} angle={60} rotation={-30} fill="#90EE90" />
<Portal selector=".layer-circles" enabled>
<Circle
radius={15}
fill="green"
x={pos.x}
y={pos.y}
draggable
onDragMove={handleDragMove}
/>
</Portal>
</Group>
);
};
Not very elegant. But this may work...
Thank you for your solution! Seems like a combination of Portal
s and manual state management of transformations is the way to go here. I've updated the codesandbox above to include your solution (labeled as green ImprovedPortaledComplexComponent
s) for posterity.
Going to close this issue, but I was looking at the portal.tsx source code and it looks like the overhead for using Portal
components includes:
Group
componentsgroup.moveTo()
callslayer.batchDraw()
callsWanted to ask: any major KonvaJS-specific performance implications regarding any of this overhead?
There should be no much overhead. As most of these actions will be called once on mount.
If you relatively small number of targets, it should work just fine.
There should be no much overhead. As most of these actions will be called once on mount.
If you relatively small number of targets, it should work just fine.
Awesome, good to hear! My use case will have lots of targets, so I will let you know if I run into performance issues.
Thanks again for letting me pick your brain!
You can try to use one layer. And use portal to put into different groups. (So just use groups for layering instead of layers). I am not sure it will help, but it may.
Hi there,
This is a bit of a design question that I'm running into regarding the z-index of my complex components (specific to
react-konva
).Hypothetically, let's say I have my component, which consists of a Circle and a Wedge (it could be up to 10 types of layers):
Let's represent this component as such:
My goal would be to render all the
Wedge
children, then all theCircle
children so that allCircle
components are not covered byWedge
components to ensure visibility. Otherwise, this is what would happen:Because
konva-react
relies on the React node ordering for z-index, my original intuition was to return my complex components already split into pieces:Then recombining the components later:
This does not work, as these individual components are no longer underneath a single Group Parent, which means I'll have to do a lot of manual work to get group movement + other features working again.
I also entertained the use of portals, but this also ignores the parent Group.
What would be the best way to achieve a layered separation between children of a group?