How can I select VerticalBarSeries from a ReactVis series plot? - javascript

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.

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.

Recharts — Is there a way to add a padding between the chart and labels for RadarChart?

I'm looking at the simple RadarChart example from their website and I would like to add some padding between the labels and the chart itself but there doesn't seem to be a simple way to do this.
Can this be done somehow or can someone suggest another chart library I could use?
One way to do it is to use a custom tick and manipulate the x and y values
function renderPolarAngleAxis({ payload, x, y, cx, cy, ...rest }) {
return (
<Text
{...rest}
verticalAnchor="middle"
y={y + (y - cy) / 2}
x={x + (x - cx) / 2}
>
{payload.value}
</Text>
);
}
return (
<RadarChart data={data}>
...
<PolarAngleAxis tick={props => renderPolarAngleAxis(props)} />
...
</RadarChart>
)
Here's the result
You can do it with CSS
those have .recharts-polar-angle-axis-tick-value class, so simply add css on it
.recharts-polar-angle-axis-tick-value {
transform: translateX(-3rem);
}

react drag,drop, and connect arrow(or anything else) with animation between elements

after few days of trying with no success, I came here (again..), to all of you experts.
first of all: live demo! because we all love live demos.
Codesandbox
https://codesandbox.io/s/drag-with-not-animation-b3eh7?file=/src/App.js
I'm trying to make interactive draggable and dropable arrows between containers(means - there is a connector to a box, you can drag your mouse from one of the containers to another box and an arrow between them will be created).
implementation 1: I can get an animation of a draggable arrow while dragging - but the onDrop event does not fire.
implementation 2: in the second implementation I can make the drop effect happen but not the animation.
NEVER THEM BOTH!
HELP! ;<
more detailed explanations inside the code.
what I've already tried:
react-dnd - did not work also because it's based on the same DOM event system the native browser drag & drop API based on(or maybe(and probably) I did it wrong?).
Here you go :
To draw a Xarrow you need a starting point and ending point
Start point : will always be dragging from
End Point : Where you are dropping
Here We have 2 refs ,
ref0 : Starting drag point ( which will be the box )
ref1 : Draggable point ( Will be the draggable point )
Here is the code that needs to be changed, please do read the comments also, that will make the flow clear.
const ConnectPointsWrapper = ({ boxId, handler, ref0 }) => {
const ref1 = useRef();
const [position, setPosition] = useState({});
const [beingDragged, setBeingDragged] = useState(false);
return (
<React.Fragment>
<div
className="connectPoint"
ref={ref1} // <---- referencing the point
style={{
...connectPointStyle,
...connectPointOffset[handler],
...position // <----- Updating the position as we drags
}}
draggable
onDragStart={e => {
setBeingDragged(true);
e.dataTransfer.setData("arrow", boxId);
}}
onDrag={e => {
setPosition({ // <---- Setting up the position to draw line as we drags
position: "fixed",
left: e.clientX,
top: e.clientY,
transform: "none",
opacity: 0
});
}}
onDragEnd={e => {
setPosition({});
setBeingDragged(false);
}}
/>
{beingDragged ? <Xarrow start={ref0} end={ref1} /> : null} // <---- this will draw the arrow b/w ref0 and ref1
</React.Fragment>
);
};
const Box = ({ text, handler, addArrow, boxId }) => {
const ref0 = useRef();
return (
<div
id={boxId}
style={boxStyle}
ref={ref0} // <---- referencing the box it self
onDragOver={e => e.preventDefault()}
onDrop={e => {
if (e.dataTransfer.getData("arrow") === boxId) {
console.log(e.dataTransfer.getData("arrow"), boxId);
} else {
const refs = { start: e.dataTransfer.getData("arrow"), end: boxId };
addArrow(refs);
}
}}
>
{text}
<ConnectPointsWrapper {...{ boxId, handler, ref0 }} /> // <---- Passing the `ref0` to `ConnectPointsWrapper` to draw line from point
</div>
);
};
WORKING DEMO :
NOTE :
I was trying to set style just via ref1 and not with setPosition,
you can check the below code snippet for that,
<div
className="connectPoint"
style={{
...connectPointStyle,
...connectPointOffset[handler]
}}
draggable
onDragStart={e => {
setBeingDragged(true);
e.dataTransfer.setData("arrow", boxId);
}}
onDrag={e => {
setPosition({}); // <---- just to force re-rendering, to draw arrow with updated value
ref1.current.style.position = "fixed";
ref1.current.style.left = e.clientX + "px";
ref1.current.style.top = e.clientY + "px";
ref1.current.style.transform = "none";
ref1.current.style.opacity = 0;
}}
ref={ref1}
onDragEnd={e => {
ref1.current.style.position = "absolute";
ref1.current.style.left = connectPointOffset[handler].left;
ref1.current.style.top = connectPointOffset[handler].top;
ref1.current.style.transform = connectPointOffset[handler].transform;
ref1.current.style.opacity = 0.5;
setBeingDragged(false);
}}
/>
WORKING DEMO : ( this is just another way )
EDIT :
WORKING DEMO : ( With draggable box also )

Incorrect geometric shape

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

Highcharts, get point index when shared tooltip is shows/hides

I have a group of charts which have the same categories.
When user hover on the chart and the tooltip is shown, I need to set all charts's corresponding point state to hover to help user to compare the data.
Firstly I use mouseOver and mouseOut events and it almost meet my needs, but I use shared tooltip so sometimes the tooltip shows without mouse on the point, so the event is not fired.
So I guess I need an event that when the tooltip shows/hides, and I find this and try tooltipRefresh event but I can't find the exactly index of on which point the tooltip shows. I have tried:
tooltipRefresh: function(e) {
var index = this.hoverPoint.index; //No dependentable
}
Is that any way that I can get the index at the right event firing moment?
you can use Label which just like the tootip, show X, Y value on the Lable.
What i did is :
1.click on one chart === >
2.get X value ===>
3.fire a Event (click event of chart) === >
4.render Label on every other chart using X (get Y value in each chart by X)
when create chart, I set an click event
options.chart = $.extend(true, options.chart, {
renderTo: 'hChart_' + chartIndex,
type: 'spline',
events: {
click: function (event) {
if($scope.label.length > 0){
$scope.clearAllLabels();
}else{
var charts = $scope.ui.charts;
$.each(charts, function (index, chart) {
//render Label to chart
});
}
}
}
});
Below is add label in chart.
var label = chart.renderer.label(
moment(xAxis).format('dddd, MMM DD, HH:mm:ss') + '<br>' + kpiName + ': <b>' + Highcharts.numberFormat(yAxis, 2) + kpiUnit + '</b>',
120,
40)
.attr({
fill: Highcharts.getOptions().colors[0],
padding: 10,
r: 5,
zIndex: 8
})
.css({
lineHeight: '20%',
fontSize: '11px',
color: '#FFFFFF'
})
.add();
Hope it will help you.

Categories

Resources