The expected 3D effect:
Code:
<Group
ref={mainRef}
x={x}
y={y}
scaleX={scaleX}
scaleY={scaleY}
onTap={onTap}
rotation={rotation}
onClick={onTap}
draggable
onDragEnd={onDragEnd}
onDragMove={onDragMove}
onTransformEnd={onTransformEnd}
>
{[...Array(6)].map((_, i) => <Text
text={letter}
x={i}
y={i}
fontFamily="Bangers-Regular"
fontSize={fontSize}
stroke="red"
strokeWidth={3}
fill="red"
fillPriority="color"
/>)}
< Text
ref={(ref) => onRender(ref)}
text={letter}
fontFamily="Bangers-Regular"
fontSize={fontSize}
stroke="blue"
strokeWidth={3}
fill="blue"
fillPriority="color"
/>
</Group>
Result from code above:
As you can see in the comparison the quality of the reference 3D effect is much higher and there is no aliasing, in theory I could get a better effect by increasing the number of copies, but it still looks worse at zoom-in.
Reference from: https://www.graffiti-empire.com/graffiti-generator/
A possible solution is to increase number of steps when your scale is increased:
import React from "react";
import { createRoot } from "react-dom/client";
import { Stage, Layer, Rect, Text, Circle, Line, Group } from "react-konva";
const App = () => {
const [scale, setScale] = React.useState(1);
return (
<>
<input
type="range"
min="0.5"
max="5"
step="0.1"
value={scale}
onChange={() => {
setScale(Number(event.target.value));
}}
/>
<Stage width={window.innerWidth} height={window.innerHeight}>
<Layer>
<Group draggable scaleX={scale} scaleY={scale}>
{[...Array(Math.round(6 * scale))].map((_, i) => (
<Text
text={"Hello"}
x={i / scale}
y={i / scale}
stroke="red"
strokeWidth={3}
fill="red"
fillPriority="color"
fontSize={50}
/>
))}
<Text
text={"Hello"}
stroke="blue"
strokeWidth={3}
fill="blue"
fillPriority="color"
fontSize={50}
/>
</Group>
</Layer>
</Stage>
</>
);
};
const container = document.getElementById("root");
const root = createRoot(container);
root.render(<App />);
https://codesandbox.io/p/sandbox/react-konva-3d-text-fj5gg4
Note: creating many layers may harm performance a lot. I suggest to cache the group if possible.