Similar to having drag and drop without moving the element in Konva, is there a way to do the same with Konva-react?
Tried doing this. But, could not find a way to add cloned shape back to the Layer.
Thank you and any help would be appreciated.
Update:
Code used:
Trying to clone "Shp1" in the below code
class Shp1 extends Component {
state = {
x1: 0,
y1: 0
};
handleDragStart = e => {
e.target.setAttrs({
scaleX: 1.1,
scaleY: 1.1
});
//clone code goes here
};
handleDragEnd = e => {
this.setState({
x1: e.target.x(),
y1: e.target.y()
});
};
render() {
return(
<Group x={this.state.x1} y={this.state.y1}
id="shp1" draggable onDragStart={this.handleDragStart} onDragEnd={this.handleDragEnd}
onMouseOver={this.handleMouseOver} onMouseOut={this.handleMouseOut}>
<RegularPolygon x={110} y={160} sides={3} radius={80}
fill="black" rotation={90}/>
<Circle x={190} y={160} radius={30}
fill="black"/>
</Group>
);
}
}
class App extends Component {
render() {
return (
<Stage id='stg1' width={window.innerWidth} height={window.innerHeight} draggable={false}>
<Layer id="menu" className="layer" x={0} y={0} width={200} height={window.innerHeight} visible={true}>
<Shp1/>
</Layer>
</Stage>
);
}
}
Related
I'm trying to onDragMove to manually update an elements position. The shape itself is dragging around, and the is updating the objects, but it is not being rendered?
Same with onDragEnd. Both are updating the array of shapes correctly, but it is not appearing on the render, even though
import React, { useState, useEffect } from "react";
import { Stage, Layer, Rect } from "react-konva";
import "./styles.css";
export default function App() {
const [objects, setObject] = useState([{ id: "rect1", x: 50, y: 50 }]);
// Function
const updatePosition = (id) => {
let update = objects.map((entry) => {
if (entry.id !== id) return entry;
else return { ...entry, x: 100, y: 0 };
});
setObject(update);
};
// We can see the object is updated with the new coords
useEffect(() => {
console.log(objects);
});
return (
<main style={{ background: "lightgrey" }}>
<Stage width={800} height={800}>
<Layer>
{objects.map((object) => {
// This shows an updated X value correclty
console.log(object.x);
// It doesn't render the new x position at all
return (
<Rect
key={object.id}
fill={"green"}
width={200}
height={300}
x={object.x}
y={object.y}
draggable
onDragMove={() => updatePosition(object.id)}
onDragEnd={() => updatePosition(object.id)}
/>
);
})}
</Layer>
</Stage>
</main>
);
}
https://codesandbox.io/s/priceless-dust-cjr6z?file=/src/App.js:0-1323
From your demo, I see that you are setting the same {x, y} position to the shape:
const updatePosition = (id) => {
let update = objects.map((entry) => {
if (entry.id !== id) return entry;
else return { ...entry, x: 100, y: 0 };
});
setObject(update);
};
By default react-konva will set 100, 0 position just once. On the next render calls, properties for <Rect /> element are not changing. react-konva will update only CHANGED from previous render properties.
If you want to strictly set the last properties, you should use strict mode
enter code hereCan we implement Object Erasing in konva js for eraser tool. Actually i need to erase free drawing line if we erase with destination-out im facing issues while moving or dragging lines from one place to another. To overcome this issue can anyone suggest me how to implement Object eraser in konva js or group the free drawn line and eraser lines.
import React from "react"
import Konva from "konva";
import {Layer, Line, Stage} from "react-konva";
import {CirclePicker} from "react-color";
const Pencil =() => {
const [tool, setTool] = React.useState("pen");
const [isDrawing, toggleDrawing] = React.useState(false);
const [lines, setLines] = React.useState([]);
const[size,setSize] = React.useState(3);
const[color,setColor]= React.useState("red");
return(
<div>
<CirclePicker value={color} color={color} onChange = {e=>{
setColor(e.hex);
}}/>
<select
value={tool}
onChange={e => {
setTool(e.target.value);
}}
>
<option value="pen">Pen</option>
<option value="eraser">Eraser</option>
</select>
<input value={size} onChange={e =>{
setSize(parseInt(e.target.value))
console.log(setSize)
}} type='range' step='3' min='3' max='16'/>
<Stage
width={window.innerWidth}
height={window.innerHeight}
onMouseDown={e => {
toggleDrawing(true);
const pointer = e.target.getStage().getPointerPosition();
const newLines = lines.concat({
id: Date.now(),
tool: tool,
points: [pointer.x, pointer.y]
});
setLines(newLines);
}}
onMouseMove={e => {
if (!isDrawing) {
return;
}
const pointer = e.target.getStage().getPointerPosition();
const newLines = lines.slice();
const lastLine = {
...newLines[newLines.length - 1]
};
lastLine.size=size;
lastLine.color=color;
lastLine.points = lastLine.points.concat([pointer.x, pointer.y]);
newLines[newLines.length - 1] = lastLine;
setLines(newLines);
}}
onMouseUp={e => {
toggleDrawing(false);
}}>
<Layer
>
{lines.map(line => (
<Line
draggable={true}
x={window.length}
y={window.length}
width={window.length}
height={window.length}
onDragEnd={e => {
e.target.to({
// duration: 0.5,
// easing: Konva.Easings.ElasticEaseOut,
// scaleX: 1,
// scaleY: 1,
shadowOffsetX: 0,
shadowOffsetY: 0
});
}}
key={line.id}
strokeWidth={line.size}
stroke={line.color}
points={line.points}
globalCompositeOperation={
line.tool === "eraser" ? "destination-out" : "source-over"
}
/>
))}
</Layer>
</Stage>
</div>)
};
export default Pencil;
I currently have a loading screen that renders an animation. After doing so I would like it to immediately, based on firebase.auth().onAuthStateChange, navigate the user to a specific page.
I have already implemented the animation and part of the logic. I just need the ability to navigate immediately after the first render/animation has completed.
class LoadingScreen extends Component {
state = {
opacity: new Animated.Value(0),
}
onLoad = () => {
Animated.timing(this.state.opacity, {
toValue: 1,
duration: 1500,
delay: 1000,
useNativeDriver: true,
}).start();
}
render() {
return (
<Animated.Image
onLoad={this.onLoad}
{...this.props}
style={[
{
opacity: this.state.opacity,
transform: [
{
scale: this.state.opacity.interpolate({
inputRange: [0, 1],
outputRange: [0.85, 1],
})
},
],
},
this.props.style,
]}
/>
);
}
}
export default class App extends Component{
render()
{
return (
<View style={styles.container}>
<LoadingScreen
style={styles.image}
source= {require('../assets/images/logo.png')}
/>
</View>
)
}
checkIfLoggedIn = () => {
firebase.auth().onAuthStateChanged((user)=>
{
if(user)
{
this.props.navigation.navigate('Login');
}
else
{
this.props.navigation.navigate('Signup');
}
})
}
}
To do something on the end of the animation, you should add a callback to the start() function, so:
Pass your checkIfLoggedIn function as a prop to LoadingScreen component
<LoadingScreen
style={styles.image}
source= {require('../assets/images/logo.png')}
onAnimationEnd={this.checkIfLoggedIn}
/>
Use the function passed as a prop for the animation callback
onLoad = () => {
Animated.timing(this.state.opacity, {
toValue: 1,
duration: 1500,
delay: 1000,
useNativeDriver: true,
}).start(() => this.props.onAnimationEnd());
}
Like the example shown for shape, this has x,y,rotation etc. https://konvajs.github.io/docs/select_and_transform/Transform_Events.html
Image in react-konva also extends shape.
How can I get these values for image(with transformer) in react-konva.
You can listen transform event and then read all properties from the image node.
handleTransform = () => {
const props = {
x: this.image.x(),
y: this.image.y(),
rotatio: this.image.rotation(),
width: this.image.width(),
height: this.image.height(),
scaleX: this.image.scaleX(),
scaleY: this.image.scaleY()
};
console.log(props);
};
render() {
return (
<Stage width={window.innerWidth} height={window.innerHeight}>
<Layer>
<Image
image={this.state.image}
ref={node => {
this.image = node;
}}
draggable
onTransform={this.handleTransform}
onDragMove={this.handleTransform}
/>
<Transformer
ref={node => {
this.transformer = node;
}}
/>
</Layer>
</Stage>
);
}
Demo: https://codesandbox.io/s/wq184owy45
I copied the code from here.
This throws this warning:
.
How to fix this warning?
Code:
'use strict';
var React = require('react-native');
// I have import the ScrollView and RefreshControl
var{
StyleSheet,
Image,
ScrollView,
RefreshControl,
View,
} = React;
var Carousel = require('react-native-looped-carousel');
var Dimensions = require('Dimensions');
var {width, height} = Dimensions.get('window');
var NewsListView = React.createClass({
getInitialState: function () {
return {
isRefreshing: false,
loaded: 0,
};
},
componentDidMount: function () {
},
render: function () {
return (
// if I remove RefreshControl , the warming missing. how to fix this problem
<ScrollView
style={styles.scrollview}
refreshControl={
<RefreshControl
refreshing={this.state.isRefreshing}
onRefresh={this._onRefresh}
tintColor="#ff0000"
title="Loading..."
/>
}>
<View>
<Carousel delay={5000} style={{width: width, height: height/4 }}>
<Image
source={require('RT_XiaoYiSiGou/Image/img_banner.png')
}
style={{width: width, height: height/4}}
/>
<Image
source={require('RT_XiaoYiSiGou/Image/img_banner2.png')}
style={{width: width, height: height/4}}
/>
<Image
source={require('RT_XiaoYiSiGou/Image/img_banner3.png')}
style={{width: width, height: height/4}}
/>
</Carousel>
</View>
</ScrollView>
);
},
_onRefresh() {
this.setState({isRefreshing: true});
setTimeout(() => {
this.setState({
loaded: this.state.loaded + 10,
isRefreshing: false,
});
}, 5000);
},
});
var styles = StyleSheet.create({
scrollview: {
flex: 1,
},
});
module.exports = NewsListView;
What I "suggest" because I can't do more from your code is:
1) The error you get is because you do not call the React.createElement correctly. You should write your code in simple segments, I suggest chopping it up in three parts, definition, creation and render...
// define your element
var definitionObject = {
// a property called render which is a function which returns your markup.
render: function() {
return (
<h1 className="peterPan">
Peter Pan.
</h1>
);
}
}
// create the actual element
var PeterPanElement = React.createClass(definitionObject);
ReactDOM.render(
<PeterPanElement />,
document.getElementById('willBeReplacedByPeterPanElement')
);
I hope you agree I can't deduce more from your question, if you clean the question up we might be able to help you out more...