Ad

How Do I Put Multiple SVGs In One Render (React Native)?

- 1 answer

I'm new to react native, and I was wondering if there was any way to include two SVGs in the same page. So far I've been able to render both of my figures through one SVG, however, I would like to add multiple SVGs. The following is the code I have so far. I hope someone can lend a hand! Thanks. ............................................................................

function Responsive(Component) {
    return class extends React.Component {
        constructor() {
            super();
            this.state = { width: undefined, height: undefined };
            this.resize = this.resize.bind(this);
        }

        componentDidMount() {
            window.addEventListener('resize', this.resize);
            this.resize();
        }

        resize() {
            const node = this.node;
            const node2 = this.node2;
            const bounds = node.getBoundingClientRect();
            const width = bounds.height;
            const height = bounds.width;
            this.setState({ width, height });
        }

        componentWillMount() {
            window.removeEventListener('resize', this.resize);
        }

        render() {
            const { width, height } = this.state;
            const { props } = this;
            return (
                <div
                    style={{ width: '100%', height: '100%' }}
                    ref={node => this.node = node}
                    id = "divBox">
                    {
                        width && <Component
                            width={width}
                            height={height}
                            {...props}
                        />
                    }
                </div>
            );
        }
    }
}

class BarChart extends React.Component {
    constructor() {
        super();

        this.state = [

            {dishName:"Hamburger/CBJ",price:50,"freq":10,"rating":4.8,"visits":7,"deliveries":3},
            {dishName:"Hamburger/CB",price:35,"freq":8,"rating":4.8,"visits":4,"deliveries":4},
            {dishName:"chickenburger/CBJ",price:30,"freq":7,"rating":3.8,"visits":2,"deliveries":5},
            {dishName:"hummus/KBJI",price:25,"freq":5,"rating":3.6,"visits":3,"deliveries":2},
            {dishName:"Meat/Abu Adel",price:24,"freq":4,"rating":2.7,"visits":2,"deliveries":2},
            {dishName:"Rocket/S Ou Nos",price:22,"freq":2,"rating":1.8,"visits":1,"deliveries":1},
            {dishName:"Hamburger/CBB",price:20,"freq":10,"rating":4.8,"visits":3,"deliveries":7},
            {dishName:"Hamburger/kq",price:19,"freq":8,"rating":4.8,"visits":5,"deliveries":3},
            {dishName:"chickenburger/dairyboys",price:33,"freq":7,"rating":3.8,"visits":4,"deliveries":3},
            {dishName:"hummus/KMB",price:21,"freq":5,"rating":3.6,"visits":3,"deliveries":2},
        ];

        this.state2 = [
            {resto:"CBJ",visits: 10, deliveries: 3},
            {resto:"Kababji",visits:15,deliveries:5},
            {resto:"Abu Adel",visits:10,deliveries:6},
            {resto:"Bliss House",visits:20,deliveries:17},
            {resto:"Sandwich ou Nos",visits:10,deliveries:21},
        ];
    this.draw = this.draw.bind(this);
}

    componentDidMount() {
        this.draw();
    }

    draw() {
        const node = select(this.node);
        node.selectAll("*").remove();
        var {
            width: w,
            height: h,
        } = this.props;

        var data = this.state;
        var data2 = this.state2;
        data = data.sort(function(a,b){
            if(numberOfClicks % 3 == 0){
                return b["price"] - a["price"];
            }
            else if(numberOfClicks % 3 == 1){
                return b["rating"] - a["rating"];
            }
            else{
                return b["freq"] - a["freq"];
            }
        });

        const yscale = scaleBand();
        yscale.domain(data.map(d => d.dishName));
        yscale.padding(0.2);
        yscale.range([0,h/0.7]);
        const xscale = scaleLinear();
        xscale.domain([0, max(data,function(d){
            if(numberOfClicks % 3 == 0){
                return Math.max(d.price)+50;
            }
            else if(numberOfClicks % 3 == 1){
                return Math.max(d.rating)+7;
            }
            else{
                return Math.max(d.freq)+12;
            }
        })]);
        xscale.range([0, w]);

        const upd = node.selectAll('rect');

        upd.data(data).enter()
            .append('rect')
            .merge(upd)
            // .attr("d", rightRoundedRect(-240, -120, 480, 240, 20))
            .attr('x', 20)
            .attr('y', d => yscale(d.dishName)+20)
            .attr('height', yscale.bandwidth()/3)
            .attr('width',0)
            .style('fill','powderblue')
            .transition()
            .duration(1000)
            .attr('width', function(d){
                if(numberOfClicks % 3 == 0){
                    return xscale(d.price);
                }
                else if(numberOfClicks % 3 == 1){
                    return xscale(d.rating);
                }
                else{
                    return xscale(d.freq);
                }
            })
            .style('fill', 'skyblue')
            .transition()
            .duration(1000)
            .style('fill','steelblue')
            .style("opacity",0.7);

        upd.data(data).enter()
            .append("text")
            .text(function(d){
                if(numberOfClicks % 3 == 0){
                    return "$"+d.price;
                }
                else if(numberOfClicks % 3 == 1){
                    return d.rating + " Stars";
                }
                else{
                    return d.freq + " Visits";
                }
            })
            .style('font-family','monospace')
            .attr('transform',function(d){
                if(numberOfClicks % 3 == 0){
                    return "translate("+ (xscale(d.price) + 30) +"," + (yscale(d.dishName)+32)+")";
                }
                else if(numberOfClicks % 3 == 1){
                    return "translate("+ (xscale(d.rating) + 30) +"," + (yscale(d.dishName)+32)+")";
                }
                else{
                    return "translate("+ (xscale(d.freq) + 30) +"," + (yscale(d.dishName)+32)+")";
                }
            });

        upd.on('click',function(d){
            select(this).style('opacity',0.3)
            .transition()
            .delay(10)
            .style('opacity',0.7);
        });

        upd.data(data)
            .enter()    
            .append("text")
            .text(function(d,i){
                return data[i].dishName;
            })
            .attr("y",function(d,i){
                return yscale(data[i].dishName)+15;
            })
            .attr('x',function(d,i){
                //return h - xscale(data[i].price) - data[i].dishName.length;
                return 20;
            })
            .attr('class','textBar')
            .style('stroke','black')
            .style('opacity',0.7)
            .style('font-family','monospace')
            .style('font-size',13)
            .style('stroke-width',0.5);


        const sectionAngles = pie().value(d => d.visits)(data2)

        node.selectAll('path')
            .data(sectionAngles)
            .enter()
            .append('path')
            .attr('d', 
                arc().innerRadius(50)
                .outerRadius(100)
            )
            .attr('fill','steelblue')
            .attr('stroke','white')
            .attr('stroke-width',15)
            .attr('transform','translate('+ (document.getElementById('divBox').offsetWidth/2) +","+ 685 +")");
    }

    componentDidUpdate() {
        this.draw();
    }

    render() {
        // make SVG stretch fully in width and height of parent node
        return (

             <ScrollView style={{ height:document.getElementById('divBox').offsetHeight}}>  
                 {/* style={{ height:500 }}> */}
                <Text style={{alignSelf:'center',paddingTop:40,opacity:0.7,fontSize:20, fontFamily:'monospace' }}>
                    Top 10 Dishes</Text> 
                    <View style={{flex: 2, flexDirection: 'column'} }>
                        <View style={{flex: 2, flexDirection: 'row',alignSelf:'center',padding:20} }>
                            <View style ={{paddingRight:10,height:20}}>
                                <Button
                                    // style= {{paddingTop:20}}
                                    onPress={() => {
                                        numberOfClicks=0;
                                        this.draw();
                                    }}
                                    title="Prices"
                                    />
                            </View>

                            <View style ={{paddingRight:10,height:20}}>
                                <Button
                                    // style= {{paddingTop:20}}
                                    onPress={() => {
                                        numberOfClicks=1;
                                        this.draw();
                                    }}
                                    title="Ratings"
                                    />
                            </View>

                            <View style ={{paddingRight:10,height:20}}>
                            <Button
                                // style= {{paddingTop:20}}
                                onPress={() => {
                                    numberOfClicks =2;
                                    this.draw();
                                }}
                                title="Portions"
                                />
                            </View>
                        </View>
                        <svg
                            style={{ width: '100%', height: document.getElementById("divBox").offsetHeight*1.5, paddingTop:10 }}
                            ref={node => {
                                this.node = node;
                            }}
                                >
                        </svg>
                </View>
             </ScrollView>
        );
    }
}

var numberOfClicks = 0;
export default Responsive(BarChart);
Ad

Answer

To answer this properly I took split the code into two files with a similar setup, then I added the PieChart as a new class, and imported the pie chart file and used it as its own element in the rendering at the end. I hope this answer helps anyone who has come across this difficulty while using react native. If anyone still has any issues or comments, don't hesitate.

I originally found my solution using the following link: https://www.smashingmagazine.com/2015/12/generating-svg-with-react/

BarChart File ........................................................................................................................

import React from 'react';
import {
    select,
    selectAll,
    scaleBand,
    scaleLinear,
    axisBottom,
    max,
    sort,
    text,
    scaleOrdinal,
    shape,
    arc,
    pie,
} from 'd3';

import { Component } from 'react';
import { View, ScrollView, Button, Text } from 'react-native';
import PieChart from '../screens/pieChart';

// hoc that wraps a component inside another component with lifecycle
// events
function Responsive(Component) {
    return class extends React.Component {
        constructor() {
            super();
            this.state = { width: undefined, height: undefined };
            this.resize = this.resize.bind(this);
        }

        componentDidMount() {
            window.addEventListener('resize', this.resize);
            this.resize();
        }

        resize() {
            const node = this.node;
            const bounds = node.getBoundingClientRect();
            const width = bounds.height;
            const height = bounds.width;
            this.setState({ width, height });
        }

        componentWillMount() {
            window.removeEventListener('resize', this.resize);
        }

        render() {
            const { width, height } = this.state;
            const { props } = this;
            return (
                <div
                    style={{ width: '100%', height: '100%' }}
                    ref={node => this.node = node}
                    id = "divBox">
                    {
                        width && <Component
                            width={width}
                            height={height}
                            {...props}
                        />
                    }
                </div>
            );
        }
    }
}

class BarChart extends React.Component {
    constructor() {
        super();

        this.state = [

            {dishName:"Hamburger/CBJ",price:50,"freq":10,"rating":4.8,"visits":7,"deliveries":3},
            {dishName:"Hamburger/CB",price:35,"freq":8,"rating":4.8,"visits":4,"deliveries":4},
            {dishName:"chickenburger/CBJ",price:30,"freq":7,"rating":3.8,"visits":2,"deliveries":5},
            {dishName:"hummus/KBJI",price:25,"freq":5,"rating":3.6,"visits":3,"deliveries":2},
            {dishName:"Meat/Abu Adel",price:24,"freq":4,"rating":2.7,"visits":2,"deliveries":2},
            {dishName:"Rocket/S Ou Nos",price:22,"freq":2,"rating":1.8,"visits":1,"deliveries":1},
            {dishName:"Hamburger/CBB",price:20,"freq":10,"rating":4.8,"visits":3,"deliveries":7},
            {dishName:"Hamburger/kq",price:19,"freq":8,"rating":4.8,"visits":5,"deliveries":3},
            {dishName:"chickenburger/dairyboys",price:33,"freq":7,"rating":3.8,"visits":4,"deliveries":3},
            {dishName:"hummus/KMB",price:21,"freq":5,"rating":3.6,"visits":3,"deliveries":2},
        ];
    this.draw = this.draw.bind(this);
}

    componentDidMount() {
        this.draw();
    }

    draw() {
        const node = select(this.node);
        node.selectAll("*").remove();
        var {
            width: w,
            height: h,
        } = this.props;

        var data = this.state;
        var data2 = this.state2;
        data = data.sort(function(a,b){
            if(numberOfClicks % 3 == 0){
                return b["price"] - a["price"];
            }
            else if(numberOfClicks % 3 == 1){
                return b["rating"] - a["rating"];
            }
            else{
                return b["freq"] - a["freq"];
            }
        });

        const yscale = scaleBand();
        yscale.domain(data.map(d => d.dishName));
        yscale.padding(0.2);
        yscale.range([0,(document.getElementById("divBox").offsetHeight*0.8)]);
        const xscale = scaleLinear();
        xscale.domain([0, max(data,function(d){
            if(numberOfClicks % 3 == 0){
                return Math.max(d.price)+50;
            }
            else if(numberOfClicks % 3 == 1){
                return Math.max(d.rating)+7;
            }
            else{
                return Math.max(d.freq)+12;
            }
        })]);
        xscale.range([0, w]);

        const upd = node.selectAll('rect');

        upd.data(data).enter()
            .append('rect')
            .merge(upd)
            // .attr("d", rightRoundedRect(-240, -120, 480, 240, 20))
            .attr('x', 20)
            .attr('y', d => yscale(d.dishName)+20)
            .attr('height', yscale.bandwidth()/3)
            .attr('width',0)
            .style('fill','powderblue')
            .transition()
            .duration(1000)
            .attr('width', function(d){
                if(numberOfClicks % 3 == 0){
                    return xscale(d.price);
                }
                else if(numberOfClicks % 3 == 1){
                    return xscale(d.rating);
                }
                else{
                    return xscale(d.freq);
                }
            })
            .style('fill', 'skyblue')
            .transition()
            .duration(1000)
            .style('fill','steelblue')
            .style("opacity",0.7);

        upd.data(data).enter()
            .append("text")
            .text(function(d){
                if(numberOfClicks % 3 == 0){
                    return "$"+d.price;
                }
                else if(numberOfClicks % 3 == 1){
                    return d.rating + " Stars";
                }
                else{
                    return d.freq + " Visits";
                }
            })
            .style('font-family','monospace')
            .attr('transform',function(d){
                if(numberOfClicks % 3 == 0){
                    return "translate("+ (xscale(d.price) + 30) +"," + (yscale(d.dishName)+32)+")";
                }
                else if(numberOfClicks % 3 == 1){
                    return "translate("+ (xscale(d.rating) + 30) +"," + (yscale(d.dishName)+32)+")";
                }
                else{
                    return "translate("+ (xscale(d.freq) + 30) +"," + (yscale(d.dishName)+32)+")";
                }
            });

        upd.on('click',function(d){
            select(this).style('opacity',0.3)
            .transition()
            .delay(10)
            .style('opacity',0.7);
        });

        upd.data(data)
            .enter()    
            .append("text")
            .text(function(d,i){
                return data[i].dishName;
            })
            .attr("y",function(d,i){
                return yscale(data[i].dishName)+15;
            })
            .attr('x',function(d,i){
                //return h - xscale(data[i].price) - data[i].dishName.length;
                return 20;
            })
            .attr('class','textBar')
            .style('stroke','black')
            .style('opacity',0.7)
            .style('font-family','monospace')
            .style('font-size',13)
            .style('stroke-width',0.5);

    }

    componentDidUpdate() {
        this.draw();
    }


    render() {
        //make svg stretch fully in width and height of parent node
        return (

             <ScrollView style={{ height:document.getElementById('divBox').offsetHeight}}>  
                 {/* style={{ height:500 }}> */}
                <Text style={{alignSelf:'center',paddingTop:40,opacity:0.7,fontSize:20, fontFamily:'monospace' }}>
                    Top 10 Dishes</Text> 
                    <View style={{flex: 2, flexDirection: 'column'} }>
                        <View style={{flex: 2, flexDirection: 'row',alignSelf:'center',padding:20} }>
                            <View style ={{paddingRight:10,height:20}}>
                                <Button
                                    onPress={() => {
                                        numberOfClicks=0;
                                        this.draw();
                                    }}
                                    title="Prices"
                                    />
                            </View>

                            <View style ={{paddingRight:10,height:20}}>
                                <Button
                                    onPress={() => {
                                        numberOfClicks=1;
                                        this.draw();
                                    }}
                                    title="Ratings"
                                    />
                            </View>

                            <View style ={{paddingRight:10,height:20}}>
                            <Button
                                onPress={() => {
                                    numberOfClicks =2;
                                    this.draw();
                                }}
                                title="Portions"
                                />
                            </View>
                        </View>
                        <svg
                            style={{ width: '100%', height: document.getElementById("divBox").offsetHeight*1.5, paddingTop:40 }}
                            ref={node => {
                                this.node = node;
                            }}
                                >
                        </svg>

                        <View style={{flex: 2, flexDirection: 'row',alignSelf:'center',padding:20} }>
                            <View style ={{paddingRight:10,height:20}}>
                                <Button
                                    onPress={() => {
                                        numberOfClicks=0;
                                        this.draw();
                                    }}
                                    title="Prices"
                                    />
                            </View>

                            <View style ={{paddingRight:10,height:20}}>
                                <Button
                                    onPress={() => {
                                        numberOfClicks=1;
                                        this.draw();
                                    }}
                                    title="Ratings"
                                    />
                            </View>
                        </View>

                        <PieChart data={this.state} style={{ padding:20}} />

                </View>

             </ScrollView>
        );
    }
}

var numberOfClicks = 0;
export default Responsive(BarChart);

................................................................................. Pie Chart File .................................................................................

import React from 'react';
import {
    select,
    selectAll,
    scaleBand,
    scaleLinear,
    axisBottom,
    max,
    sort,
    text,
    scaleOrdinal,
    shape,
    arc,
    pie,
} from 'd3';

import { Component } from 'react';
import { View, ScrollView, Button, Text } from 'react-native';


function Responsive(Component) {
    return class extends React.Component {
        constructor() {
            super();
            this.state = { width: undefined, height: undefined };
            this.resize = this.resize.bind(this);
        }

        componentDidMount() {
            window.addEventListener('resize', this.resize);
            this.resize();
        }

        resize() {
            const node = this.node;
            const bounds = node.getBoundingClientRect();
            const width = bounds.height;
            const height = bounds.width;
            this.setState({ width, height });
        }

        componentWillMount() {
            window.removeEventListener('resize', this.resize);
        }

        render() {
            const { width, height } = this.state;
            const { props } = this;
            return (
                <div
                    style={{ width: '100%', height: '100%' }}
                    ref={node => this.node = node}
                    id = "divBox">
                    {
                        width && <Component
                            width={width}
                            height={height}
                            {...props}
                        />
                    }
                </div>
            );
        }
    }
}

class PieChart extends React.Component {
    constructor() {
        super();

        this.state = [
            {resto:"CBJ",visits: 10, deliveries: 3},
            {resto:"Kababji",visits:15,deliveries:5},
            {resto:"Abu Adel",visits:10,deliveries:6},
            {resto:"Bliss House",visits:20,deliveries:17},
            {resto:"Sandwich ou Nos",visits:10,deliveries:21},
        ];

    this.draw = this.draw.bind(this);
}

    componentDidMount() {
        this.draw();
    }

    draw() {
        const node = select(this.node);
        node.selectAll("*").remove();
        var {
            width: w,
            height: h,
        } = this.props;

        var data = this.state;

        const sectionAngles = pie().value(d => d.visits)(data)

        node.selectAll('path')
            .data(sectionAngles)
            .enter()
            .append('path')
            .attr('d', 
                arc().innerRadius(100)
                .outerRadius(150)
            )
            .attr('fill','steelblue')
            .attr('stroke','white')
            .attr('stroke-width',15)
            .attr('transform','translate('+(h/2)+","+200+")");

            node.selectAll('path')
            .data(sectionAngles)
            .enter()
            .append('path')
            .attr('d', 
                arc().innerRadius(50)
                .outerRadius(100)
            )
            .attr('fill','steelblue')
            .attr('stroke','white')
            .attr('stroke-width',15)
            .attr('transform','translate('+(h/2)+","+200+")");
    }

    componentDidUpdate() {
        this.draw();
    }


    render() {
        //make svg stretch fully in width and height of parent node
        return (
            <View>
                <svg
                    style={{ width: '100%', height: document.getElementById("divBox").offsetHeight }}
                    ref={node => {
                        this.node = node;
                    }}
                        >
                </svg>
            </View>
        );
    }
}

export default Responsive(PieChart);
Ad
source: stackoverflow.com
Ad