Guest User

Untitled

a guest
Apr 24th, 2018
80
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.86 KB | None | 0 0
  1. import React, { Component } from "react";
  2. import DownloadButton from "./mini/DownloadButton.js";
  3. import {
  4. VictoryPie,
  5. VictoryLegend,
  6. VictorySharedEvents,
  7. VictoryLabel,
  8. VictoryContainer,
  9. VictoryGroup,
  10. Point
  11. } from "victory";
  12.  
  13. class Pie extends Component {
  14. constructor(props) {
  15. super(props);
  16. this.state = {
  17. data: this.props.data.data,
  18. title: this.props.data.chart_title,
  19. subtitle: this.props.data.chart_subtitle,
  20. currentPercent: 0,
  21. activeColor: this.props.theme.interactions.active,
  22. clicked: false,
  23. activeKey: undefined,
  24. svgrefs: []
  25. };
  26. }
  27.  
  28. makeLegend(data) {
  29. let sum = 0;
  30. data.map(item => {
  31. sum += Number(item.y);
  32. return true;
  33. });
  34.  
  35. let legData = data.map((item, idx) => {
  36. let percent = Number(item.y) / sum * 100;
  37. let activeStyle = () => {
  38. if (idx === Number(this.state.activeKey)) {
  39. return {
  40. fill: this.state.activeColor,
  41. fontWeight: "bold",
  42. fontSize: 20,
  43. fontColor: this.state.activeColor
  44. };
  45. } else {
  46. return {
  47. fill: this.props.colorscale[idx],
  48. fontWeight: "normal",
  49. fontColor: "#555"
  50. };
  51. }
  52. };
  53. return {
  54. name: item.x,
  55. percent: percent.toFixed(1),
  56. symbol: { fill: activeStyle().fill },
  57. labels: {
  58. fontWeight: activeStyle().fontWeight,
  59. fontSize: activeStyle().fontSize,
  60. fill: activeStyle().fontColor
  61. }
  62. };
  63. });
  64. return legData;
  65. }
  66.  
  67. getData(data) {
  68. return data;
  69. }
  70.  
  71. componentDidMount() {
  72. this.setState({
  73. svgrefs: [this.viewBox, this.legendref]
  74. });
  75. }
  76.  
  77. render() {
  78. const percentPortal = () => {
  79. if (this.state.currentPercent !== 0) {
  80. return this.state.currentPercent + "%";
  81. }
  82. };
  83.  
  84. const piecolor = key => {
  85. if (Number(this.state.activeKey) === key) {
  86. return this.state.activeColor;
  87. } else {
  88. return this.props.colorscale[key];
  89. }
  90. };
  91.  
  92. const clicked = key => {
  93. if (
  94. this.state.clicked === true &&
  95. Number(this.state.activeKey) === Number(key)
  96. ) {
  97. return false;
  98. } else {
  99. return true;
  100. }
  101. };
  102. return (
  103. <div className="Pie chart-widget">
  104. <div style={{ padding: "5px" }}>
  105. <p
  106. style={{
  107. fontFamily: "Asap",
  108. fontSize: 14,
  109. display: "block",
  110. margin: 0
  111. }}
  112. >
  113. {this.state.title.toUpperCase()}
  114. </p>
  115. <p
  116. style={{
  117. margin: 0,
  118. fontFamily: "Asap",
  119. fontSize: 12,
  120. fontWeight: "normal",
  121. display: "block"
  122. }}
  123. >
  124. {this.state.subtitle}
  125. </p>
  126. </div>
  127. <VictorySharedEvents
  128. className="pieWrapper"
  129. events={[
  130. {
  131. childName: ["pie", "legend"],
  132. target: "data",
  133. eventHandlers: {
  134. onMouseOver: (evt, obj, key) => {
  135. if (this.state.clicked === false) {
  136. return [
  137. {
  138. childName: ["pie", "legend"],
  139. mutation: props => {
  140. this.setState({
  141. currentPercent:
  142. props.datum.percent,
  143. activeKey: key
  144. });
  145. }
  146. }
  147. ];
  148. }
  149. },
  150. onMouseOut: () => {
  151. if (this.state.clicked === false) {
  152. return [
  153. {
  154. childName: ["pie", "legend"],
  155. mutation: () => {
  156. this.setState({
  157. currentPercent: 0,
  158. activeKey: undefined
  159. });
  160. return null;
  161. }
  162. }
  163. ];
  164. }
  165. },
  166. onClick: (evt, obj, key) => {
  167. return [
  168. {
  169. childName: ["pie", "legend"],
  170. mutation: props => {
  171. this.setState({
  172. currentPercent:
  173. props.datum.percent,
  174. clicked: clicked(key),
  175. activeKey: Number(key)
  176. });
  177. }
  178. }
  179. ];
  180. }
  181. }
  182. }
  183. ]}
  184. >
  185. <div
  186. style={{
  187. display: "flex",
  188. flexWrap: "wrap"
  189. }}
  190. >
  191. <VictoryGroup
  192. style={{
  193. parent: { maxWidth: "65%", marginTop: 12 }
  194. }}
  195. >
  196. <svg viewBox={"0 0 400 400"}>
  197. <VictoryPie
  198. ref={Pie => (this.Pie = Pie)}
  199. theme={this.props.theme}
  200. name="pie"
  201. style={{
  202. data: {
  203. fill: d => piecolor(d.eventKey)
  204. }
  205. }}
  206. padAngle={0}
  207. innerRadius={85}
  208. data={this.getData(this.state.data)}
  209. standalone={false}
  210. labels={d => ""}
  211. containerComponent={
  212. <VictoryContainer
  213. containerRef={pieref =>
  214. (this.pieref = pieref)
  215. }
  216. />
  217. }
  218. />
  219.  
  220. <VictoryLabel
  221. className="percent"
  222. theme={this.props.theme}
  223. animate={{ duration: 500 }}
  224. text={percentPortal()}
  225. textAnchor="middle"
  226. verticalAnchor="middle"
  227. x={200}
  228. y={200}
  229. style={{
  230. fontSize: 42,
  231. fill: this.state.activeColor,
  232. fontFamily: "Asap",
  233. fontWeight: "bold"
  234. }}
  235. ref={percent => (this.percent = percent)}
  236. />
  237. </svg>
  238. </VictoryGroup>
  239. <VictoryLegend
  240. theme={this.props.theme}
  241. name="legend"
  242. centerTitle
  243. orientation="vertical"
  244. borderPadding={{ top: 40 }}
  245. width={300}
  246. height={450}
  247. rowGutter={-15}
  248. style={{
  249. labels: {
  250. fontFamily: "Asap",
  251. fontSize: 20
  252. },
  253. parent: { maxWidth: "35%" }
  254. }}
  255. data={this.makeLegend(this.state.data)}
  256. dataComponent={<Point size={10} />}
  257. containerComponent={
  258. <VictoryContainer
  259. containerRef={legendref =>
  260. (this.legendref = legendref)
  261. }
  262. />
  263. }
  264. />
  265. </div>
  266. </VictorySharedEvents>
  267. <DownloadButton
  268. type="pie"
  269. data={this.props.data}
  270. fields={[
  271. { label: "Tipo", value: "x" },
  272. { label: "Porcentaje", value: "y" }
  273. ]}
  274. unwind={["data"]}
  275. />
  276. </div>
  277. );
  278. }
  279. }
  280.  
  281. export default Pie;
Add Comment
Please, Sign In to add comment