I'm working on a project with react native and we chose to use react-native-svg in order to display our map. Everything's worked perfectly so far, except for this :
I have an array of objects that each have coordinates and a size. I want to loop through this array to display an image at all of these coordinates. But no luck, I managed to diplay shapes and texts but no images.
Here is the render function of my parent element :
render() {
return (
<View>
<Svg
height={screen.height}
width={screen.width}
>
<G
width={mapSize.x}
height={mapSize.y}
x={this.state.center.x}
y={this.state.center.y}
originX={mapSize.x / 2}
originY={mapSize.y / 2}
rotation={this.state.orientation}
scale={1}
>
<Rect
width={mapSize.x}
height={mapSize.y}
x={0}
y={0}
scale={1}
fill="#0071e9"
/>
<G
width={mapSize.x}
height={mapSize.y}
x={this.state.cnv.x}
y={this.state.cnv.y}
scale={1}
>
// this is my child component's tag
<Islands
islands={this.state.contentToRender}
deg={this.state.orientation}
/>
</G>
</G>
<Image
x={(screen.width / 2) - 50}
y={-(screen.height / 2) + 94.46}
width="100"
height="189.9"
preserveAspectRatio="xMidYMid slice"
href={images.bateau}
/>
</G>
</Svg>
</View>
)
}
}
here is my child component's render :
render(){
const that = this
return(
this.props.islands.map((c) => {
return (
<Image
key={ c.id }
x={ c.position.x }
y={ c.position.y }
width={ c.size.x }
height={ c.size.y }
preserveAspectRatio="xMidYMid slice"
rotation={-that.props.deg}
originX={ c.position.x + (c.size.x / 2) }
originY={ c.position.y + (c.size.y / 2) }
href={images.rouge}
/>
)
})
)
}
And finally my images.js file :
const images = {
boussole: require('./img/Boussole.png'),
aiguille: require('./img/Aiguille.png'),
bateau: require('./img/Bateau.png'),
home: require('./img/home.png'),
cyclop_island: require('./img/ile_cyclope_navig.png'),
rouge: require('./img/smiley-carre-rouge-simple-face-magnetique.jpg'),
}
export default images
I have no issue with any aspect of the Svg component, I can display every image of the images.js file as long as they are not in a loop.
Also, even if the image doesn't display the console shows no error.
Related
I am using jsPDF in React js. I am crating some content and drawings inside a <svg>. When I want to render the pdf, everything inside the SVG is not rendered. Is there any solution to solve this or another one to export the SVG to pdf? I want the text inside the pdf to be selectable as well, I don't want just to transform the SVG into a picture and drop it into a pdf, that is not a solution. Below is my code that is not working
import React from 'react'
import jsPDF from 'jspdf'
const About = () => {
const downloadPDF = () => {
let doc = new jsPDF("p","pt","a4")
doc.html(document.querySelector("#graph"), {
callback: function(pdf){
pdf.save("doc.pdf");
}
})
}
return (
<div id = "graph">
Some text // {/*This is rendered */}
<h1>some title</h1> {/*This is rendered */}
<svg width="500" height="500"> {/*This is not rendered */}
<circle cx="50" cy="80" r={radius} stroke="rgb(0,125,225)" stroke-width="2" fill="red"/>
</svg>
</div>
)
}
export default About
I'm trying to create a custom progress bar for the HTML5 video tag. The progress bar doesn't need any controls, it's just an SVG that I'd like to fill as the video progresses.
The video is a React component:
import React, {useRef} from 'react'
const VideoSection = () => {
const videoRef = useRef()
const handlePlayVideo = () => videoRef.current.play()
return (
<div>
<button onClick={handlePlayVideo}>
Play video
</button>
<video src='./video.mp4' ref={videoRef}/>
//The SVG I'd like to animate
<svg width="595" height="28" viewBox="0 0 595 28" fill="none"
xmlns="http://www.w3.org/2000/svg">
<path d="M0 14C0 6.26801 6.26801 0 14 0H595V28H14C6.26801 28 0 21.732 0
14V14Z" fill="#072760"/>
</svg>
</div>
)
}
export default VideoSection
Or is there an alternative way to approach/build the progress bar? Thanks!
I want to dynamically draw/turn an SVG with React from degree paramters that im recieving. Its like the direction arrow from a weather-info.
How do I dynamically draw an SVG in Javascript / ReactJS?
How do I turn the SVG with variable input?
I'm aware, that you can draw SVG-Graphics like this:
function draw_square() {
var draw = SVG('square_1');
draw.size(120, 120);
var square = draw.rect(100, 100);
square.attr({ fill: '#f06' });
}
draw_square()
but how do I connect different svg-paths to each other?
I recommend a slightly different approach:
const WindDirectionIcon = ({ width, height }) => {
return (
<svg
id="wind-direction-arrow"
width={width}
height={height}
viewBox="0 0 12 12"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path d="M6 0L0 12L6 9L12 12L6 0Z" fill="black" />
</svg>
);
};
export default function App() {
useEffect(() => {
const degrees = 90; // Retrieve from your API
const arrow = document.getElementById("wind-direction-arrow");
arrow.setAttribute("transform", `rotate(${degrees})`);
}, []);
return (
<div className="App">
<WindDirectionIcon width="24" height="24" />
</div>
);
}
So the svg itself can be composed of a single path and the only thing we do with javascript is to set the transform attribute to rotate a certain number of degrees based on the API data you receive using template literals.
Rotate with javascript based on this answer.
Sandbox Example
I'm using Recharts to try to accomplish a doughnut chart with rounded segments, which should end by looking more or less like this:
This is the closest I can achieve, but as you can see I'm running into some problems:
First, the first segment is overlapping the others at both edges. I don't know how to correct that despite my searches.
Next, I'm struggling with aligning the legend properly. I found no way to define a width to svg text so long text would go to the next line. (These texts are contained into variables and not hardcoded)
This is my chart.js. I cropped some parts to make it simpler, but I'll post the whole thing if needed.
const renderLabelContent = (props) => {
const { value, title, x, y, midAngle } = props;
return (
<g transform={`translate(${x}, ${y})`} textAnchor={'start'}>
<text x={(midAngle < -90 || midAngle >= 90) ? (0 - (title.length * 3)) : 0} y={0}
{`${title}`}
</text>
<text x={(midAngle < -90 || midAngle >= 90) ? (0 - (title.length * 3)) : 0} y={20}>
{`${value}`}€
</text>
</g>
);
};
...
export default class Chart extends Component {
...
render() {
return (
<div className="pie-charts">
<div className="pie-chart-wrapper">
<PieChart width={400} height={400}>
<Pie
stroke="none"
legendType="circle"
data={this.state.data}
dataKey="value"
startAngle={180}
endAngle={-180}
cornerRadius={100}
innerRadius={60}
outerRadius={80}
label={renderLabelContent}
paddingAngle={-10}
labelLine={false}
isAnimationActive={true}
>
{
data.map((entry, index) => (
<Cell key={`slice-${index}`} fill={entry.color} />
))
}
<Label width={50} position="center">
2,87€
</Label>
</Pie>
</PieChart>
</div>
</div>
);
}
}
I think there are a couple of ways to approach the Labels issue, in recharts you can place a React component on the Label content prop, and this could be the way for you to inject your own custom Text component that has a max-width and wrap, for example:
<Label content={<Text warp style={{maxWidth:"50px"}}>long string </Text> } />
One more option is to play with the offset property of the label, but it is flexible and will impact the overall Label position, for example:
<Label value="Pages of my website" offset={0} position="center" />
I'm working on building a range slider and I am stuck trying to use the .drag function. Specifically I can't seem to get any function to run during start or drag.
I have a very simple component here:
<g
className="handle1"
transform={`translate(${xScale(value)},0)`}
onMouseOver={() => onMouseOver()}
>
<rect
className="valueBuble"
x="-8"
y="-2.5rem"
width="1rem"
height="1rem"
fill="green"
></rect>
<text
x="0"
y="-1.75rem"
width="1rem"
height="1rem"
fill="white"
textAnchor="middle"
>
{value}
</text>
<circle r="10px" fill="#fa7070" />
</g>
The entire <g> moves according to a value prop. Now my d3 code with the drag function:
d3.select("g.handle1")
.call(d3.drag().on("start", drag).on("drag", drag));
Here I attempted to call a function named drag however this function is not being called. I'm testing this with a console.log:
const drag = (event, d) => {
console.log(event.target.value);
};
I am using React functional components. Any advice on how to fix the problem.
Code Pen example: https://codepen.io/trevordammon/pen/WNxWQRm