4 * Copyright 2016 RIFT.IO Inc
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
19 var React
= require('react');
20 var mixin
= require('../mixins/ButtonEventListener.js')
21 //TODO: Many values are hard coded, need to make bullet "smarter"
23 * A bullet graph component.
24 * It's props values and a brief description below
26 * vertical: If true, the bar rises and falls vertically
27 * value: The value displayed
28 * min: The minimum value expected
29 * max: The maximum value expected
30 * bulletColor: The fill color of the value section of the graph
31 * radius: Radius of graph corners.
32 * containerMarginX: Container's margin along x-axis
33 * containerMarginY: Container's margin along y-axis
34 * width: Width of bullet graph in pixels
35 * height: Height of bullet graph in pixels
36 * fontSize: Font size of text in pixels
37 * textMarginX: margin for text on x-axis
38 * textMarginY: Margin for text on y-axis
39 * units: units displayed. Also changes whether a max value is displayed.
41 module
.exports
= React
.createClass({
42 displayName
: 'Bullet',
45 vertical
: React
.PropTypes
.bool
,
46 value
: React
.PropTypes
.number
,
47 min
: React
.PropTypes
.number
,
48 max
: React
.PropTypes
.number
,
49 bulletColor
: React
.PropTypes
.string
,
50 radius
: React
.PropTypes
.number
,
51 containerMarginX
: React
.PropTypes
.number
,
52 containerMarginY
: React
.PropTypes
.number
,
53 bulletMargin
: React
.PropTypes
.number
,
54 width
: React
.PropTypes
.number
,
55 height
: React
.PropTypes
.number
,
56 markerX
: React
.PropTypes
.number
,
57 fontSize
: React
.PropTypes
.number
,
58 textMarginX
: React
.PropTypes
.number
,
59 textMarginY
: React
.PropTypes
.number
,
60 units
: React
.PropTypes
.string
63 getDefaultProps: function() {
85 * Defines default state.
86 * value: The value displayed
88 getInitialState: function() {
90 value
: this.props
.value
95 * Called when the props are updated.
96 * Syncs the state value with the prop value.
99 componentWillReceiveProps: function(nextProps
) {
100 this.setState({value
:nextProps
.value
|| this.state
.value
})
104 * Before the component will mount, the width value is recalculed based on browser.
106 componentWillMount: function() {
107 var isIE
= false || !!document
.documentMode
;
108 var range
= this.props
.max
- this.props
.min
;
109 var normalizedValue
= (this.state
.value
- this.props
.min
) / range
;
110 this.isPercent
= (!this.props
.units
|| this.props
.units
== '')? true:false
112 this.bulletWidth
= String(Math
.round(100 * normalizedValue
)) + "%";
114 this.bulletWidth
= this.props
.width
- (2 * this.props
.containerMarginX
);
116 this.displayValue
= (this.isPercent
)? String(Math
.round(normalizedValue
* 100)) + "%" : this.props
.value
121 * When the component mounts, this function sets the animation for smooth transition on value change. This only
122 * happens if the user's browser is not IE.
124 componentDidMount: function() {
125 var isIE
= false || !!document
.documentMode
;
126 var range
= this.props
.max
- this.props
.min
;
127 var normalizedValue
= (this.state
.value
- this.props
.min
) / range
;
129 var transform
= "scaleX(" + normalizedValue
+ ")";
130 var bullet
= React
.findDOMNode(this.refs
.bulletRef
);
131 bullet
.style
.transform
= transform
;
132 bullet
.style
["-webkit-transform"] = transform
;
137 * On update, reaplies transformation and width changes made in componentWillMount and componentDidMount
142 shouldComponentUpdate: function(nextProps
, nextState
) {
144 if (String(this.state
.value
) == String(nextState
.value
)) {
147 var isIE
= false || !!document
.documentMode
;
148 var range
= this.props
.max
- this.props
.min
;
149 var normalizedValue
= (nextState
.value
- this.props
.min
) / range
;
152 this.bulletWidth
= String(Math
.round(100 * normalizedValue
)) + "%";
154 this.bulletWidth
= this.props
.width
- (2 * this.props
.containerMarginX
);
155 var transform
= "scaleX(" + normalizedValue
+ ")";
156 var bullet
= React
.findDOMNode(this.refs
.bulletRef
);
157 bullet
.style
.transform
= transform
;
158 bullet
.style
["-webkit-transform"] = transform
;
160 this.displayValue
= (this.isPercent
)? String(Math
.round(normalizedValue
* 100)) + "%" : nextState
.value
169 * Renders the Bullet Component
174 // The text element that displays the difference between the max value and the current value.
175 var maxDOMEl
= (!this.isPercent
)? null : React
.createElement("text", {
176 //X needs better logic
177 // x: this.props.width - this.props.height * 1.25,
178 x
: this.props
.width
- (130 - this.props
.textMarginX
),
179 y
: this.props
.textMarginY
,
180 fontFamily
: "Verdana",
181 fontSize
: this.props
.fontSize
,
182 fill
: "#ffffff"}, String(this.props
.max
- this.state
.value
) + "%");
185 // The main bullet element. Made up of a static black rect in the background,
186 // a moving colored rect overlayed on top and a text element for the current value.
187 var bulletDOM
= React
.createElement("svg", {
190 viewBox
: "0 0 512 " + this.props
.height
,
191 preserveAspectRatio
: "none"},
192 React
.createElement("rect", {className
: "bullet-container",
193 width
: this.props
.width
- (2 * this.props
.containerMarginX
),
194 height
: this.props
.height
- (2 * this.props
.containerMarginY
),
195 x
: this.props
.containerMarginX
,
196 y
: this.props
.containerMarginY
,
197 rx
: this.props
.radius
,
198 ry
: this.props
.radius
}, null),
199 React
.createElement("svg", {
200 x
: this.props
.containerMarginX
,
201 y
: this.props
.bulletMargin
},
202 React
.createElement("rect", {
205 fill
: this.props
.bulletColor
,
206 width
: this.bulletWidth
,
207 height
: this.props
.height
- (2 * this.props
.bulletMargin
),
208 rx
: this.props
.radius
,
209 ry
: this.props
.radius
212 React
.createElement("line", {className
: "bullet-marker",
213 x1
: this.props
.markerX
,
214 x2
: this.props
.markerX
,
215 y1
: this.props
.markerY1
,
216 y2
: this.props
.markerY2
}),
217 React
.createElement("text", {
218 x
: this.props
.textMarginX
,
219 y
: this.props
.textMarginY
,
220 "fontFamily": "Verdana",
221 "fontSize": this.props
.fontSize
,
222 fill
: "#ffffff"}, this.displayValue