Incorrect geometric shape - javascript

I'm trying to create geometric shapes (circles) that change color depending on certain values ​​assumed by a variable.
In theory I set the values ​​of these geometric shapes so that they turn out to be circles, instead they turn out to be squares. Can you tell me why?
this.state = {
pressColorDx1: "",
//...
}
//....
if (this.pressDx_p1 >= 10) { this.setState({ pressColorDx1: "#00438c" }) }
else { this.setState({ pressColorDx1: '#afeeee' }) }
render() {
return (
//..
<View style={{width: 15,height: 15,borderRadius: 15/2,backgroundColor: this.state.pressColorDx1,right: 30, top: 40}}></View>
)}
this should be a circle, but it is displayed like a square.
It's not a problem of top and right.. I have tried also borderRadius: 50% and it doesn't work.
You can see there https://snack.expo.io/#keyz23/92058c

Related

Custom react-native circle menu help needed

I need to build a custom circle menu in react-native. I am currently building this menu with expo. It needs to have a circle in the middle of the screen with a logo/text and when you press and hold on the circle, smaller circles buttons come out from the middle and grow into place around the main circle, evenly spaced. Then, while still pressing, as you move your finger towards these smaller circles, they get bigger to reveal an icon and or text. When you release your finger on one of these outer circle buttons, it then takes you to that part of the app.
The closest module I found for my need is this one:
https://github.com/Ramotion/react-native-circle-menu
It did not work out of the box. I had to modify it to get it working with the most recent react-native/expo and the progress portion also doesn't work, so I commented that out as well.
As far as my need and what I have, I was able to get the circle in the middle with text, you press and hold and the smaller circle buttons come out and are evenly spaces around it, but when you drag to them and let go, im not sure which events on which components would register how I need.
Here is the code that renders the main menu button:
return <Animated.View style={{
transform: [
{
scaleX: this.state.animation.interpolate({
inputRange: [0, .2, .75, 1],
outputRange: [1.5, 1.2, .5, 1]
})
},
{
scaleY: this.state.animation.interpolate({
inputRange: [0, .2, .75, 1],
outputRange: [1.5, 1.2, .5, 1]
})
}
]
}}>
<TouchableOpacity
onPressIn={this.openMenu}
onPressOut={this.closeMenu}
style={styles.closedButton}
activeOpacity="1">
<Text style={styles.closedButtonText}>XYZ</Text>
</TouchableOpacity>
</Animated.View>
This renders the smaller circle buttons that are around the outside of the main menu button above:
renderActions() {
if (!this.state.active) {
return null
}
// Defines the amount of angle to increase for each item so they do not overlap
const increase = Math.PI * 2 / this.props.items.length;
// Define initial angle
let angle = -Math.PI / 2;
// Loop through each action (item) to add them to the display
return this.props.items.map((item, index) => {
// Angle first starts at the initial angle
const btnAngle = angle;
// Then increases the angle by 'increase' for each button
angle += increase;
// Displays the individual action (item)
return <ActionIcon
key={index}
animation={this.state.animation}
angle={btnAngle}
bgColor={this.props.bgColor}
buttonColor={item.color}
icon={item.name}
radius={this.props.radius - this.props.itemSize}
onPress={() => {
this.closeMenu();
this.props.onPress(index);
}}
size={this.props.itemSize}
style={[styles.actionContainer, { position: 'absolute' }]}
/>
})
}
and finally, here is how the circle menu is being called from the main App.js
items = [
{
name: 'md-home',
color: '#298CFF',
},
{
name: 'md-search',
color: '#30A400',
},
{
name: 'md-time',
color: '#FF4B32',
},
{
name: 'md-settings',
color: '#8A39FF',
},
{
name: 'md-navigate',
color: '#FF6A00',
},
];
onPress = index => console.log(`${this.items[index].name} icon pressed!`);
render() {
return <View style={styles.container}>
<CircleMenu
bgColor="#0E1329"
items={this.items}
onPress={this.onPress}
/>
</View>
}
If there is any other information I can provide, please let me know. Thanks in advance.

Why won't "angleString" update in Animated rotate?

I'm trying to create a component on my screen, where the user is able to use their finger to rotate the componnent around its center. I have been able to get the angle and consistently update it (verified through console.log), but the value is not being passed rotate under Animated.view.
Here is my code:
class Spinner extends React.Component {
constructor(props){
super(props);
this.angleCalculation = this.angleCalculation.bind(this);
this.state = {
angleString: '0deg'
}
}
angleCalculation(x,y){
xValue = x - 50
yValue = (y * -1) + 150
angle = Math.atan(yValue/xValue) * (180/Math.PI)
this.state.angleString = angle + 'deg'
console.log(this.state.angleString)
}
render() {
return(
<View style={styles.container}>
<Animated.View
style={styles.box, {
backgroundColor: 'blue',
width:100,
height:300,
transform:[{ rotate: this.state.angleString
}]
}}
onStartShouldSetResponder={(evt) => true}
onResponderGrant={(evt) => {this.angleCalculation(evt.nativeEvent.locationX,evt.nativeEvent.locationY)}}
onResponderMove={(evt) => {this.angleCalculation(evt.nativeEvent.locationX,evt.nativeEvent.locationY)}}
onResponderRelease={(evt) => {this.angleCalculation(evt.nativeEvent.locationX,evt.nativeEvent.locationY)}}
/>
</View>
)
}
}
The console.log consistently updates as I moved my finger in a circular fashion. And it does so in the angleString form that I want. In my this.state, I set an initial value of '0 deg' but I am not sure why it is updating under 'rotate'.
What can I do to make it update in real-time? So the rotate accepts the updated values and follows along with the user's finger?
Thanks for any help that you can provide!

How can I select VerticalBarSeries from a ReactVis series plot?

ReactVis API here outlines what is available which might be helpful. I have successfully added a "drag to select" function to my custom code. In the picture, we would be selecting 13 to 17 and turn the fill value to red for example.
More pseudo code question but code would be awesome.
A container div in a Hook would look like this:
<div className="unselectable"
style={{ position: 'relative' }}
onMouseDown={(e) => {
if (!x && !y) {
setX(e.clientX); setY(e.clientY)
}
}}
onMouseMove={(e) => {
if (x && y) {
const newX = e.clientX; const newY = e.clientY;
setX1(newX); setY1(newY);
setRect(
<div style={{
zIndex: 10000,
position: 'fixed',
left: x > newX ? newX : x, top: y > newY ? newY : y,
width: Math.abs(newX - x), height: Math.abs(newY - y),
backgroundColor: 'gray', opacity: 0.2
}} />
)
}
}}
onMouseUp={(e) => {
setX(null); setY(null); setX1(null); setY1(null);
setRect(null);
}}
>
<XYPlot>
//...
</XYPlot>
{rect}
</div>
Thank you very much.
In order to achieve "selected" vs "notSelected" state of the series, we need to use "datawithcolor" objects as our data object: {x: foo, y: bar, color:0}. Passing such an array to a react-series would be sufficient to render different coloured series (bars for example). For example: [{x: foo, y: bar, color:0}] where colorDomain would be [0, 1] and the colorRange would be some blue and red.
In order to have a listed of selected "values", we can hold on to a list of values in a react state (hooks or class), either during a dragging of a rectangle or after the rectangle has been drawn, in my case only during dragging. Every time the rectangle changes, the list must be updated.
On re-render generate a new "datawithcolor" array for React-vis bar-series with colour ranges and domains defined using indexes returned from onNearestX or similar React-vis callback.
How do we update the selected list?
<ReactSeries
// see React-vis source of abstract-series.js for details
/*
onNearestX(value, {
innerX: xScaleFn(value),
index: valueIndex,
event: event.nativeEvent
});
*/
onNearestX={(datapoint, { index, innerX }) => {
// rect is mentioned in the question
if (rect && isWithinRect({ x, x1, value: innerX })) {
if (!selected.includes(index)) { // prevent rerender
setSelected([...selected, index]);
}
} else {
if (!rect) {
setSelected([index]); // single hover
}
}
}}
colorDomain={[0, 1]}
colorRange={['red', 'blue']}
data={dataWithColor} />
For full example see this.
Things to remember, managing the rectangle and selected list are two different things. React-vis colorRange should be clear by now, the docs were not so helpful to me.

React-Leaflet change GEOJSON shape color by state change

Through an API call, I get GEOJSON data (points) . I immediately display that data in the leaflet map by using circleMaker and display them all to be one color. I then give the user the option to slide a slider ( triggers action with payload being the slider value/location). What I want to do is change the color of some circles ( i.e one those who have an attribute that is lower that the slider value). How can I do this without re-rendering all circles?
Example: ( all circles are green and slider value is at 0, I then change the slider to 4 and all the circles that have a value (that I get from the GEOJSON features) lower than 4 ( slider value) change color to red, and the rest stay the same.
Sample Code:
I have a GEOJSON component:
<GeoJSON
key={_.uniqueId()}
data= {this.props.countrySelected.geojson}
pointToLayer={this.pointToLayer.bind(this)}
></GeoJSON>
^ The data is a GEOJSON object with all points that have a feature of lets say "score"
Here is pointToLayer:
pointToLayer = (feature, latlng) => {
return L.circleMarker(latlng, {
color: '#228B22',
fillColor: '#228B22',
fillOpacity: .6,
radius: 3
}).bindPopup(popUpString(feature.properties));
}
In another component I have a slider that calls handleChange everytime it is changed:
handleChange = (value) => {
this.props.sliderChanged(value);
}
This then triggers an action, that then triggers a reducer that makes the adequate changes to the state ( i.e. it makes the state slider value change to the value in the slider that the user just changed.
Check out these two links to get some context for the solution I've come up with:
https://github.com/PaulLeCam/react-leaflet/issues/382
http://leafletjs.com/reference-1.2.0.html#geojson
You will need to create a renderGeojson function like this which will be re-evaluated every re-render:
function renderCountries(countryGeoJson, sliderValue) {
return countryGeoJson.map(country => {
let style = () => { color: 'defaultColor' };
if (country.score < sliderValue ) {
style = () => { color: 'red' };
} else if ( country.score > slidervalue ) {
style = () => { color: 'green' };
return (
<GeoJSON key={field.id} data={field.geoJson} style={style} />
);
});
}
Now, this function will be called in the actual render function in your component which will be called every time slider value changes.
Pseudo-code but something like:
<Map>
{ renderCountries( this.props.countrySelected.geojson, this.state.sliderValue ) }
</Map>
Make sense? :)

How to transform a shape in Snap.svg without applying the transformation to its mask?

I want to transform a rectangle (position, scale, and angle) that has a mask.
I created a fiddle file to demonstrate my problem.
http://jsfiddle.net/MichaelSel/vgw3qxpg/2/
Click the green rectangle, and see how it moves in relationship to the circle on top of it. The rectangle is moving and the circle is stationary. This is how I want to objects to act.
But now click the button on top.
The circle is now a mask for the green rectangle, now when you press it, you can see that that the transformations are applied to the mask as well. (the circle doesn't stay stationary like when it wasn't a mask).
I know that more often then not, you want to treat a mask this way, but for my app I want the opposite.
I was able to overcome this problem by creating an opposite movement in the blue example.
With that, my demo is very simple and I am looking to implement this in a big app. Is there a way to achieve what I want without all the hassle?
This is the code for the green(bad) example:
s = Snap("#player")
rect = s.rect(100, 100, 100, 100).attr({"fill" : "green" })
circle = s.circle(200, 200, 50).attr({"fill" : "white" })
rect.attr("mask",circle)
rect.click(function () {
rect.transform("t20,10s1.1...")
})
This is the code for the blue (good) example:
rect2 = s.rect(300, 100, 100, 100).attr({ "fill": "blue" })
circle2 = s.circle(400, 200, 50).attr({ "fill": "white" })
rect2.attr("mask", circle2)
rect2.click(function () {
rect2.transform("t20,10s1.1...")
circle2.transform("t-20,-10s"+1/1.1 + "...")
})
Any suggestions?
Thank you.
If you put the rectangle in a group, and then apply the mask to the group, you can transform the rect any way you like without affecting the mask.
s = Snap("#player")
rect = s.rect(100, 100, 100, 100).attr({"fill" : "green" })
g = s.group(rect);
circle = s.circle(200, 200, 50).attr({"fill" : "white" })
rect.click(function () {
rect.transform("t20,10s1.1...")
})
$("#myButton").click(function () {
g.attr("mask",circle)
})
http://jsfiddle.net/vgw3qxpg/3/

Categories

Resources