[英]How do I put multiple SVGs in one render (React Native)?
我是本機反應的新手,我想知道是否有任何方法可以在同一頁面中包含兩個 SVG。 到目前為止,我已經能夠通過一個 SVG 渲染我的兩個圖形,但是,我想添加多個 SVG。 以下是我到目前為止的代碼。 我希望有人可以伸出援助之手。 謝謝。 ..................................................... …………………………………………………………………………………………
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);
為了正確回答這個問題,我將代碼拆分為具有類似設置的兩個文件,然后將 PieChart 添加為新的 class,並導入餅圖文件並在最后的渲染中將其用作自己的元素。 我希望這個答案可以幫助任何在使用 react native 時遇到這個困難的人。 如果有人仍有任何問題或意見,請不要猶豫。
我最初使用以下鏈接找到了我的解決方案: https://www.smashingmagazine.com/2015/12/generating-svg-with-react/
條形圖文件.................................................. ..................................................... ……………………………………………………………………………………………………………………
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);
..................................................... ................................餅圖文件...... ..................................................... …………………………………………………………………………
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);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.