Position a foreignObject to the top-right of an svg - javascript

I'm adding a foreignObject to a chart built upon svg. I want to put it on the top-right of the svg, irrespective of how big/small that svg is. So I don't want a hardcoded solution, I need a dynamic solution.
Setting width={'100%'} height={'100%'} inside the foreignObject isn't workable, because it makes the rest of the chart unclickable.
I've got a non-dynamic solution by setting x and y manually inside foreignObject, but I need a dynamic solution.
How can I achieve this?
<g>
<foreignObject //x={0} y={0}
width={'1'} height={'1'} style={{overflow: 'visible'}} x={50} y={50}>
<Menu>
<MenuButton as={Button} rightIcon={<ChevronDownIcon />}
transition="all 0.001s"
borderRadius="md"
borderWidth="0px"
_hover={{ bg: "gray.400" }}
_expanded={{ bg: "blue.400" }}
_focus={{ boxShadow: "none" }}
style={{ marginTop: "1px", position: "absolute", right: 0 }}>
Actions
</MenuButton>
<Portal>
<MenuList zIndex={10}>
<MenuItem>Download</MenuItem>
<MenuItem>Create a Copy</MenuItem>
<MenuItem>Mark as Draft</MenuItem>
<MenuItem>Delete</MenuItem>
<MenuItem>Attend a Workshop</MenuItem>
</MenuList>
</Portal>
</Menu>
</foreignObject>
</g>
Codesandbox:
https://codesandbox.io/s/floral-water-v11gx?file=/src/BasicLineSeries.tsx

Your parent component BasicLineSeries already knows the width, so you can pass that into the component generating the foreignObject as follows:
<ChartCanvas
height={height}
ratio={ratio}
width={width}
...
>
<Chart id={1} yExtents={this.yExtents}>
<LineSeries yAccessor={this.yAccessor} strokeWidth={3} />
<XAxis />
<YAxis />
</Chart>
<TestMenu width={width} />
</ChartCanvas>
function TestMenu({width}) {
return (
<g className="react-financial-charts-enable-interaction">
<foreignObject
width={"1"}
height={"1"}
style={{ overflow: "visible" }}
x={width}
y={50}
>

Related

Change viewport width for component running inside svg

I Have a component that is perfectly responsive based on window width. Now this component is loaded dynamically inside an SVG through foriegnObject. The Problem is component is working based on window media queries while I want the component to run based on svg size.. Is it possible?
Here is the view
My Question is It possible to somehow run child component media queries based parent svg width and height
Here is code
<svg
xmlns="http://www.w3.org/2000/svg"
xmlnsXlink="http://www.w3.org/1999/xlink"
width="357"
height="725"
fill="none"
viewBox="0 0 357 725"
>
......
<foreignObject
style={{ width: '322px', borderRadius: '30px' }}
x="5.2%"
y="5%"
height="656"
>
<div
id="style-4"
style={{
overflowY: 'auto',
overflowX: 'hidden',
width: '100%',
height: '634px',
}}
>
<ErrorBoundary>
<Suspense fallback={<CircularProgress />}>
<Component
profile={props.selectedProfile}
downloadVcf={() => console.log('vcf')}
/>
</Suspense>
</ErrorBoundary>
</div>
</foreignObject>
</svg>

React navigation (Tab Navigator) with custom SVGIcons

I'm using React navigation to change screens with the bottom tab navigations, but when I try to use a custom SVG I have many troubles and using an image to show as an icon the color obviously doesn't change, how can I use an SVG file that can recognize the color im passing to change when I'm on the page?
function MyTabs() {
return(
<Tab.Navigator
tabBarOptions={{
showLabel: false,
style:{
backgroundColor:'#313A3F',
borderTopColor: 'transparent'
},
activeTintColor: '#E6B056',
}}
>
<Tab.Screen
name="ProfileScreen"
component={ProfileScreen}
options={{
tabBarIcon: ({color}) => (
<Ionicons name="person" size={32} color={color} />
)
}}
/>
<Tab.Screen
name="MatchScreen"
component={MatchScreen}
options={{
tabBarIcon: ({color}) => (
<Image
style={{ width: 38, height: 38 }}
source={require('../images/Icons/ico-menu-busca-evas.png')}
/>
)
}}
/>
<Tab.Screen
name="CheckIn"
component={CheckIn}
options={{
tabBarIcon: ({color}) => (
<FontAwesome5 name="map-marker" size={32} color={color} />
)
}}
/>
<Tab.Screen name="ChatScreen"
component={ChatScreen}
options={{
tabBarIcon: ({color}) => (
<Ionicons name="chatbubbles" size={32} color={color} />
)
}}
/>
</Tab.Navigator>
)
}
I have fixed this issue using:
import Svg, { G, Path } from 'react-native-svg';
then using the original svg passing props for color and size.
The accepted answer from #Renan works, I just wanted to share the full code sample.
So, like he said, first add this import...
import Svg, { G, Path } from 'react-native-svg';
after that, use it like this in your code...
<Svg
width={size}
height={size}
viewBox='0 0 24 24'
fillRule='evenodd'
clipRule='evenodd'
strokeLinejoin='round'
strokeMiterlimit={2}
>
<G transform='matrix(1,0,0,1,-2.99997,-1.5)'>
<Path
d='M13.003,14C13.553,14 14,13.544 14,13.005L14,4.995C13.997,4.449 13.549,4.002 13.003,4L6.997,4C6.447,4 6,4.456 6,4.995L6,13.005C6.003,13.551 6.451,13.998 6.997,14L13.003,14ZM13.003,23C13.553,23 14,22.562 14,21.997L14,17.003C14,16.449 13.547,16 13.003,16L6.997,16C6.996,16 6.994,16 6.993,16C6.448,16 6,16.448 6,16.993C6,16.996 6,17 6,17.003L6,21.997C6,22.551 6.453,23 6.997,23L13.003,23ZM23.003,23C23.553,23 24,22.555 24,22.004L24,12.996C23.998,12.45 23.549,12.002 23.003,12L16.997,12C16.997,12 16.996,12 16.996,12C16.45,12 16,12.45 16,12.996L16,22.004C16.002,22.55 16.451,22.998 16.997,23L23.003,23ZM16,9.01C16,9.556 16.453,10 16.997,10L23.003,10C23.553,10 24,9.549 24,9.01L24,4.99C23.996,4.446 23.547,4.001 23.003,4L16.997,4C16.453,4.001 16.005,4.446 16,4.99L16,9.01Z'
fill={color}
/>
</G>
</Svg>

Recharts - align axis label in the left side

I am creating a horizontal bar graph using recharts library. I want to align the y-axis label in the left side.
<BarChart width={400} height={300} data={data} layout="vertical" margin={{right: 40}}>
<XAxis hide axisLine={false} type="number"/>
<YAxis dataKey="name" type="category" axisLine={false} tickLine={false} />
<Bar dataKey="pv" stackId="a" barSize={15} radius={[20,20,20,20]} fill="#8884d8" background={{fill: "#eee", radius: [20,20,20,20]}} tick={false} />
<Bar dataKey="uv" stackId="a" barSize={15} radius={[20,20,20,20]} fill="#eee" >
<LabelList dataKey="amt" position="right" />
</Bar>
</BarChart>
Jsfiddle
You can accomplish this by using a custom Tick component.
const CustomYAxisTick = React.createClass({
render() {
const { x, y, payload } = this.props;
return (<g transform={`translate(${0},${y})`}>
<text x={0} y={0}
textAnchor="start"
fill="#666">{payload.value}</text>
</g>)
}
})
And then you can use that in your YAxis:
<YAxis tick={<CustomYAxisTick />} />
I forked your JSFiddle and added those changes.

ReCharts - not able to see label when right aligned for stacked bar chart

I am creating an example of StackBarChart using Recharts library but I am not able to see the label when it's position is set to "right" though I am able to show the other label positions.
<BarChart width={400} height={300} data={data} layout="vertical">
...
<Bar dataKey="pv" stackId="a" barSize={15} radius={[20,20,20,20]} fill="#8884d8" background={{fill: "#ddd", radius: [20,20,20,20]}} tick={false} />
<Bar dataKey="uv" stackId="a" barSize={15} radius={[20,20,20,20]} fill="#aaa" >
<LabelList dataKey="name" position="right" />
{/* works fine <LabelList dataKey="name" position="top" /> */}
</Bar>
</BarChart>
Here is the Jsfiddle(updated).
I have updated your fiddle script here.
You have to provide a correct dataKey field to LabelList, and put LabelList as a child of Bar component
UPDATED:
New jsfiddle, you need margin in your case. So that the SVG reserved some spaces aside of the chart for additional text. NOTE that it is the margin props of the chart, not the margin from CSS style.

Recharts - Horizontally Align Line and Bar Charts

I am using Recharts and have a component that displays a line chart followed by a bar chart. The two charts are displaying the same seven day span, but the ticks are not aligned. The line chart starts on the Y Axis line, while the bar chart has left padding (by default).
On the line chart I tried adding padding={{left: 100 }}, which got the starting of the X axes aligned, but the rest of the ticks were off, and more importantly it isn't responsive to the screen size. As far as I can tell using something like '5%' is not allowed.
On the bar chart I tried setting the padding to zero and a negative number, but ran into the same issues with responsive scaling and tick misalignment.
Is there a way to align the ticks and data on the two graphs?
Here is the code:
<ResponsiveContainer width="95%" height={300} >
<LineChart width={350} height={300} data={this.props.data.activityResponse.edges} connectNulls={true} >
<Legend verticalAlign="top" height={36}/>
<Line type="monotone" dataKey="node.participation" stroke={this.participationColor} name="Participation" strokeWidth={this.strokeWidth} />
<Line type="monotone" dataKey="node.focus" stroke={this.focusColor} name="Focus" strokeWidth={this.strokeWidth} />
<XAxis dataKey="node.logDate" tickFormatter={this.formatXAxis} />
<YAxis dataKey="node.participation" >
<Label value="%" position="insideLeft" />
</YAxis>
<Tooltip content={this.renderResponseTooltip} />
</LineChart>
</ResponsiveContainer>
<ResponsiveContainer width="95%" height={300} >
<BarChart width={350} height={300} data={this.props.data.activityStep.edges} connectNulls={true} >
<Legend verticalAlign="top" height={36}/>
<Bar dataKey="node.stepCount" fill={this.stepColor} name="Steps" />
<XAxis dataKey="node.logDate" tickFormatter={this.formatXAxis} />
<YAxis dataKey="node.stepCount" >
</YAxis>
<Tooltip content={this.renderStepTooltip} />
</BarChart>
</ResponsiveContainer>
I'm not sure if you are still interested in this, since the question is pretty old, but I have found a solution that worked for me.
You can use ComposedChart to solve this. Taking your code, the solution should look something like this:
<ResponsiveContainer width="95%" height={300} >
<ComposedChart data={this.props.data.activityResponse.edges} connectNulls={true} >
<Legend verticalAlign="top" height={36}/>
<Line type="monotone" dataKey="node.participation" stroke={this.participationColor} name="Participation" strokeWidth={this.strokeWidth} />
<Line type="monotone" dataKey="node.focus" stroke={this.focusColor} name="Focus" strokeWidth={this.strokeWidth} />
<XAxis dataKey="node.logDate" tickFormatter={this.formatXAxis} />
<YAxis dataKey="node.participation" >
<Label value="%" position="insideLeft" />
</YAxis>
<Tooltip content={this.renderResponseTooltip} />
</ComposedChart>
</ResponsiveContainer>
<ResponsiveContainer width="95%" height={300} >
<ComposedChart data={this.props.data.activityStep.edges} connectNulls={true} >
<Legend verticalAlign="top" height={36}/>
<Bar dataKey="node.stepCount" fill={this.stepColor} name="Steps" />
<XAxis dataKey="node.logDate" tickFormatter={this.formatXAxis} />
<YAxis dataKey="node.stepCount" >
</YAxis>
<Tooltip content={this.renderStepTooltip} />
</ComposedChart>
</ResponsiveContainer>
I also removed your width / height arguments on the charts since the ResponsiveContainer will take care of that already.
In my personal case, this solves the issue, when I try to horizontally align an Area and a Bar Chart.
Providing a syncid for both charts, by adding that attribute to both ComposedCharts, the Tooltip will also follow in both charts simultaneously.
This link might help in this case.
Try syncId="anyId" on both LineChar and BarChar element.
Rechart - SynchronizedLineChart

Categories

Resources