이 React Native Chart에 Gradient Color를 어떻게 추가합니까?
현재 구현 :
이것은 도구 설명이 추가 된 react-native-svg 라이브러리를 사용하는 차트입니다. 선의 색을 단색이 아닌 그라데이션으로 만들고 싶습니다
암호:
import React, { useState } from 'react'
import { View, Text, Dimensions } from 'react-native'
import { LineChart } from 'react-native-chart-kit'
import { Rect, Text as TextSVG, Svg } from "react-native-svg";
const Charts = () => {
let [tooltipPos, setTooltipPos] = useState({ x: 0, y: 0, visible: false, value: 0 })
return (
<View>
<LineChart
data={{
labels: ["January", "February", "March", "April", "May", "June"],
datasets: [
{
data: [
100, 110, 90, 130, 80, 103
]
}
]
}}
width={Dimensions.get("window").width}
height={250}
yAxisLabel="$" yAxisSuffix="k" yAxisInterval={1} chartConfig={{ backgroundColor: "white", backgroundGradientFrom: "#fbfbfb", backgroundGradientTo: "#fbfbfb", decimalPlaces: 2, color: (opacity = 1) => `rgba(0, 0, 0, ${opacity})`,
labelColor: (opacity = 1) => `rgba(0, 0, 0, ${opacity})`,
style: {
borderRadius: 0
},
propsForDots: {
r: "6",
strokeWidth: "0",
stroke: "#fbfbfb"
}
}}
bezier
style={{
marginVertical: 8,
borderRadius: 6
}}
decorator={() => {
return tooltipPos.visible ? <View>
<Svg>
<Rect x={tooltipPos.x - 15}
y={tooltipPos.y + 10}
width="40"
height="30"
fill="black" />
<TextSVG
x={tooltipPos.x + 5}
y={tooltipPos.y + 30}
fill="white"
fontSize="16"
fontWeight="bold"
textAnchor="middle">
{tooltipPos.value}
</TextSVG>
</Svg>
</View> : null
}}
onDataPointClick={(data) => {
let isSamePoint = (tooltipPos.x === data.x
&& tooltipPos.y === data.y)
isSamePoint ? setTooltipPos((previousState) => {
return {
...previousState,
value: data.value,
visible: !previousState.visible
}
})
:
setTooltipPos({ x: data.x, value: data.value, y: data.y, visible: true });
}}
/>
</View>
)
}
export default Charts
질문 : 차트가 회색으로 표시되는 대신 특정 임계 값을 초과하면 차트의 색상을 빨간색으로, 다른 값은 노란색으로, 가장 낮은 값은 녹색으로 표시합니다.
다소 이렇게 :
내가 찾은 것 :
render() {
const data = [ 50, 10, 40, 95, -4, -24, 85, 91, 35, 53, -53, 24, 50, -20, -80 ]
const Gradient = () => (
<Defs key={'gradient'}>
<LinearGradient id={'gradient'} x1={'0'} y={'0%'} x2={'100%'} y2={'0%'}>
<Stop offset={'0%'} stopColor={'rgb(134, 65, 244)'}/>
<Stop offset={'100%'} stopColor={'rgb(66, 194, 244)'}/>
</LinearGradient>
</Defs>
)
return (
<LineChart
style={ { height: 200 } }
data={ data }
contentInset={ { top: 20, bottom: 20 } }
svg={{
strokeWidth: 2,
stroke: 'url(#gradient)',
}}
>
<Grid/>
<Gradient/>
</LineChart>
)
}
두 가지를 통합 할 수 없습니다. 도와주세요.
답변
상당히 관련이 있지만 react-native-chart-kit이 제공 CustomLineChart하는 자체 구성 요소를 만들 수 있습니다 LineChart.
class CustomLineChart extends LineChart {
render() {
const {
width,
height,
data,
withScrollableDot = false,
withShadow = true,
withDots = true,
withInnerLines = true,
withOuterLines = true,
withHorizontalLines = true,
withVerticalLines = true,
withHorizontalLabels = true,
withVerticalLabels = true,
style = {},
decorator,
onDataPointClick,
verticalLabelRotation = 0,
horizontalLabelRotation = 0,
formatYLabel = (yLabel) => yLabel,
formatXLabel = (xLabel) => xLabel,
segments,
transparent = false,
chartConfig,
} = this.props;
const {scrollableDotHorizontalOffset} = this.state;
const {labels = []} = data;
const {
borderRadius = 0,
paddingTop = 16,
paddingRight = 64,
margin = 0,
marginRight = 0,
paddingBottom = 0,
} = style;
const config = {
width,
height,
verticalLabelRotation,
horizontalLabelRotation,
};
const datas = this.getDatas(data.datasets);
let count = Math.min(...datas) === Math.max(...datas) ? 1 : 4;
if (segments) {
count = segments;
}
const legendOffset = this.props.data.legend ? height * 0.15 : 0;
return (
<View style={style}>
<Svg
height={height + paddingBottom + legendOffset}
width={width - margin * 2 - marginRight}>
<Defs>
<LinearGradient id="grad" x1="0" y1="0" x2="0" y2="1">
<Stop offset="0" stopColor="red" stopOpacity="1" />
<Stop offset="1" stopColor="blue" stopOpacity="1" />
</LinearGradient>
</Defs>
<Rect
width="100%"
height={height + legendOffset}
rx={borderRadius}
ry={borderRadius}
fill="white"
fillOpacity={transparent ? 0 : 1}
/>
{this.props.data.legend &&
this.renderLegend(config.width, legendOffset)}
<G x="0" y={legendOffset}>
<G>
{withHorizontalLines &&
(withInnerLines
? this.renderHorizontalLines({
...config,
count: count,
paddingTop,
paddingRight,
})
: withOuterLines
? this.renderHorizontalLine({
...config,
paddingTop,
paddingRight,
})
: null)}
</G>
<G>
{withHorizontalLabels &&
this.renderHorizontalLabels({
...config,
count: count,
data: datas,
paddingTop: paddingTop,
paddingRight: paddingRight,
formatYLabel,
decimalPlaces: chartConfig.decimalPlaces,
})}
</G>
<G>
{withVerticalLines &&
(withInnerLines
? this.renderVerticalLines({
...config,
data: data.datasets[0].data,
paddingTop: paddingTop,
paddingRight: paddingRight,
})
: withOuterLines
? this.renderVerticalLine({
...config,
paddingTop: paddingTop,
paddingRight: paddingRight,
})
: null)}
</G>
<G>
{withVerticalLabels &&
this.renderVerticalLabels({
...config,
labels,
paddingTop: paddingTop,
paddingRight: paddingRight,
formatXLabel,
})}
</G>
<G>
{this.renderLine({
...config,
...chartConfig,
paddingRight: paddingRight,
paddingTop: paddingTop,
data: data.datasets,
})}
</G>
<G>
{withDots &&
this.renderDots({
...config,
data: data.datasets,
paddingTop: paddingTop,
paddingRight: paddingRight,
onDataPointClick,
})}
</G>
<G>
{withScrollableDot &&
this.renderScrollableDot({
...config,
...chartConfig,
data: data.datasets,
paddingTop: paddingTop,
paddingRight: paddingRight,
onDataPointClick,
scrollableDotHorizontalOffset,
})}
</G>
<G>
{decorator &&
decorator({
...config,
data: data.datasets,
paddingTop,
paddingRight,
})}
</G>
</G>
</Svg>
{withScrollableDot && (
<ScrollView
style={StyleSheet.absoluteFill}
contentContainerStyle={{width: width * 2}}
showsHorizontalScrollIndicator={false}
scrollEventThrottle={16}
onScroll={Animated.event([
{
nativeEvent: {
contentOffset: {x: scrollableDotHorizontalOffset},
},
},
])}
horizontal
bounces={false}
/>
)}
</View>
);
}
}
function App() {
return (
<CustomLineChart
data={{
labels: ['January', 'February', 'March', 'April', 'May', 'June'],
datasets: [
{
data: [100, 110, 90, 130, 80, 103],
},
],
}}
width={Dimensions.get('window').width}
height={250}
chartConfig={{
backgroundGradientFrom: '#fbfbfb',
backgroundGradientTo: '#fbfbfb',
color: (opacity = 1) => 'url(#grad)',
labelColor: (opacity = 1) => `rgba(0, 0, 0, ${opacity})`,
}}
bezier
withInnerLines={false}
withOuterLines={false}
/>
);
}
렌더링에 포함 된 대부분의 코드는 공식 LineChart구성 요소 (https://github.com/indiespirit/react-native-chart-kit/blob/master/src/line-chart/LineChart.tsx).
이 코드에서 중요한 부분은 추가되는 선형 그래디언트와이 줄입니다 chartConfig.
color: (opacity = 1) => 'url(#grad)'
색상은 LinearGradientid로 정의한를 나타 grad냅니다.
결과는 다음과 같습니다.
더 많은 색상을 추가하고 offset각각 의 소품을 가지고 놀 수도 있습니다 .
그라디언트에 백분율을 사용할 수도 있지만 설명서에 따라 백분율을 사용하는 것보다 성능 이점이 있으므로 정확한 값을 사용하는 것이 좋습니다. https://github.com/react-native-community/react-native-svg#lineargradient.
주목해야 할 중요한 것은이 구현에는 fillShadowGradient배경이없고 그림자를 구현하지 않는다는 것입니다. 질문과 관련이없는 툴팁 코드와 같은 다른 코드도 생략했습니다.