ReactJS KonvasJS How to create 2 layers that cannot overlaps - reactjs

i'm trying to create 2 layers (Images) that cannot overlap,
So they can still dragged freely, but won't showed over each other.
I've tried using zIndex or a blank Rect, but can't figure out how to make 2 draggable layers that can't overlap (Very similar to overflow: hidden behavior)
a GIF is attached to show the problem, each layer shouldn't be visible behind the divider line.
return (
<Stage width={size.width} height={size.height}>
{stateImages.map((imageConfig) => {
index++
return <Layer><Image
x={size.width/2 * index}
y={0}
image={imageConfig.image}
draggable
/>
</Layer>
})}
{stateImages.length > 1 &&
<Layer>
<Rect
x={size.width / 2}
y={0}
width={4}
height={size.height}
fill="white"
shadowBlur={10}
zIndex={2}
/>
</Layer>
}
</Stage>
)

You can use clip https://konvajs.org/docs/clipping/Clipping_Regions.html#page-title for that use case:
import React, { Component } from "react";
import { render } from "react-dom";
import { Stage, Layer, Image, Group } from "react-konva";
import useImage from "use-image";
// the first very simple and recommended way:
const MyImage = () => {
const [image] = useImage("https://i.imgur.com/ktWThtZ.png");
return <Image image={image} draggable />;
};
class App extends Component {
render() {
return (
<Stage width={window.innerWidth} height={window.innerHeight}>
<Layer>
<Group
clipX={0}
clipY={0}
clipWidth={window.innerWidth / 2}
clipHeight={window.innerHeight}
>
<MyImage />
</Group>
<Group
x={window.innerWidth / 2}
clipX={0}
clipY={0}
clipWidth={window.innerWidth / 2}
clipHeight={window.innerHeight}
>
<MyImage />
</Group>
</Layer>
</Stage>
);
}
}
render(<App />, document.getElementById("root"));
https://codesandbox.io/s/react-konva-clip-images-demo-onp3w?file=/src/index.js

Related

React-raphael Rect Hover

I've looked at this answer but I still can't wrap my head around about how to implement this with react-raphael. This is what my component looks like. How do I use the hover prop for Rect in react?
import React from 'react';
import {Paper, Rect} from 'react-raphael';
import "./style.less"
const SVGBoxes = () => {
return (
<Paper width={500} height={700} container={{className: "svg-parent"}}>
<Rect
x={30} y={148} width={150} height={150}
attr={{"fill":"#10a54a","stroke":"#000","stroke-width":2,"fill-opacity": 0.2}}
/>
</Paper>
)
}

can you portal elements into a Canvas in react-three-fibre?

Is it possible to portal some react-three-fibre elements into a canvas from outside of one?
I.e. in the following example, which was my first attempt to portal a mesh into a Canvas which errored with "target element is not a DOM element" (which makes sense, given these aren't DOM elements)
import * as React from 'react'
import { Canvas, createPortal } from '#react-three/fiber'
export const Element = ({ parent }) => {
return createPortal(
<mesh>
<boxGeometry args={[1, 1, 1]} />
<meshStandardMaterial color="red" />
</mesh>
, parent);
};
export const MyPage = () => {
const ref = React.useRef(null);
return (
<div>
<Canvas>
<group ref={ref} />
</Canvas>
<Element parent={ref.current} />
</div>
);
};
So I found the createPortal method (which has incredibly limited documentation) from react-three-fiber, but with that it throws errors, presumably here because the createPortal method only works when already inside a Canvas context and is for portaling around inside a Canvas
import * as ReactDOM from 'react-dom'
import * as React from 'react'
import { Canvas } from '#react-three/fiber'
export const Element = ({ parent }) => {
return ReactDOM.createPortal(
<mesh>
<boxGeometry args={[1, 1, 1]} />
<meshStandardMaterial color="red" />
</mesh>
, parent);
};
export const MyPage = () => {
const ref = React.useRef(null);
return (
<div>
<Canvas>
<group ref={ref} />
</Canvas>
<Element parent={ref.current} />
</div>
);
};
the above throws this error:
react-dom.development.js:22839 Uncaught R3F hooks can only be used within the Canvas component!
Is there a way of doing this?
My hope is to be able to portal elements from elsewhere in the project into a single document-sized Canvas element that sits at the root.
update:
I have managed to get this to work by wrapping the call to createPortal in a second <Canvas />
export const Element = ({ parent }) => {
return (
<Canvas>
{createPortal(
<mesh>
<boxGeometry args={[1, 1, 1]} />
<meshStandardMaterial color="blue" />
</mesh>,
portalTo
)}
</Canvas>
);
};
</code>
however this is unworkable as three.js lmits the number of canvases in a project (and having unused actual canvases everywhere in the DOM is really gross anyway)
is there a way of giving createPortal access to that context without needing to render it inside a Canvas?

How To create this custom shape in react konva

Hi I am new to react konva and trying to make a custom shape for my project
I wanted to create the yellow element which is basically a trapezium with curved sides and should fit inside the red ring as shown in the image. Any help is much appreciated.
You can use Konva.Ring and Konva.Arc shapes for that.
import React from "react";
import { render } from "react-dom";
import { Stage, Layer, Arc, Ring } from "react-konva";
const App = () => {
return (
<Stage width={window.innerWidth} height={window.innerHeight}>
<Layer>
<Ring
x={200}
y={200}
innerRadius={40}
outerRadius={70}
fill="red"
stroke="black"
/>
<Arc
x={200}
y={200}
innerRadius={40}
outerRadius={70}
angle={60}
rotation={-120}
fill="yellow"
stroke="black"
/>
</Layer>
</Stage>
);
};
https://codesandbox.io/s/react-konva-arc-demo-yhkoh

react-three-fiber 360 image darker than the original image

I'm trying to create a 360 image using react-three-fiber. The 360 viewer is working perfectly as it purposed but the generated image is darker than the original image.
Here's the screenshot from my 360 viewer
Here's the original image
Here's my code
import React, { Suspense } from "react";
import { useTexture, OrbitControls } from "#react-three/drei";
import { Canvas } from "#react-three/fiber";
import * as THREE from "three";
const Generate360Image = (props) => {
var myTexture = useTexture(props.imageLocation);
return (
<>
<mesh
position={[0, 0, 0]}
>
<sphereGeometry attach="geometry" args={[500, 60, 60]} />
<meshBasicMaterial
attach="material"
map={myTexture}
side={THREE.DoubleSide}
/>
</mesh>
</>
);
};
class GenerateImage extends React.Component {
render() {
return (
<Canvas style={{ width: "100%", height: "100%" }}>
<Suspense fallback={null}>
<Generate360Image
imageLocation={this.props.myImage}
className="image-canvas"
/>
</Suspense>
<OrbitControls
autoRotate="true"
autoRotateSpeed={0.4}
minDistance={5}
maxDistance={80}
/>
</Canvas>
);
}
}
export default GenerateImage;
Any help will be appreciated. Thanks!
try use meshPhysicalMaterial instead of meshBasicMaterial. meshBasicMaterial does not properly reflect lightings.
compare these two samples from three.js docs
meshBasicMaterial
meshPhysicalMaterial

How to use Konva Node with ReactJs

I want to use konva.js node nesting in react app. I need help on how to use it.
Thanks in advance.
I can advise you to use react-konva library
https://github.com/konvajs/react-konva
The examples with the draggable circles:
import React, { Component } from 'react';
import Konva from 'konva';
import { render } from 'react-dom';
import { Stage, Layer, Circle, Text } from 'react-konva';
class App extends Component {
handleDragStart = e => {
e.target.setAttrs({
scaleX: 1.3,
scaleY: 1.3
});
};
handleDragEnd = e => {
e.target.to({
duration: 0.5,
scaleX: 1,
scaleY: 1
});
};
render() {
return (
<Stage width={window.innerWidth} height={window.innerHeight}>
<Layer>
<Text text="You can drag a circle" />
{[...Array(10)].map(i => (
<Circle
key={i}
x={Math.random() * window.innerWidth}
y={Math.random() * window.innerHeight}
radius={20}
fill="green"
opacity={0.8}
draggable
onDragStart={this.handleDragStart}
onDragEnd={this.handleDragEnd}
/>
))}
</Layer>
</Stage>
);
}
}
render(<App />, document.getElementById('root'));
You need to add react, konva, react-dom and react-konva dependencies

Resources