1. /**
    
  2.  * Copyright (c) Meta Platforms, Inc. and affiliates.
    
  3.  *
    
  4.  * This source code is licensed under the MIT license found in the
    
  5.  * LICENSE file in the root directory of this source tree.
    
  6.  */
    
  7. 'use strict';
    
  8. 
    
  9. var Circle = require('react-art/Circle');
    
  10. var React = require('react');
    
  11. var ReactART = require('react-art');
    
  12. var Group = ReactART.Group;
    
  13. var Shape = ReactART.Shape;
    
  14. var Surface = ReactART.Surface;
    
  15. var Transform = ReactART.Transform;
    
  16. 
    
  17. var MOUSE_UP_DRAG = 0.978;
    
  18. var MOUSE_DOWN_DRAG = 0.9;
    
  19. var MAX_VEL = 11;
    
  20. var CLICK_ACCEL = 3;
    
  21. var BASE_VEL = 0.15;
    
  22. 
    
  23. /**
    
  24.  * An animated SVG component.
    
  25.  */
    
  26. class VectorWidget extends React.Component {
    
  27.   /**
    
  28.    * Initialize state members.
    
  29.    */
    
  30.   state = {degrees: 0, velocity: 0, drag: MOUSE_UP_DRAG};
    
  31. 
    
  32.   /**
    
  33.    * When the component is mounted into the document - this is similar to a
    
  34.    * constructor, but invoked when the instance is actually mounted into the
    
  35.    * document. Here, we'll just set up an animation loop that invokes our
    
  36.    * method. Binding of `this.onTick` is not needed because all React methods
    
  37.    * are automatically bound before being mounted.
    
  38.    */
    
  39.   componentDidMount() {
    
  40.     this._interval = window.setInterval(this.onTick, 20);
    
  41.   }
    
  42. 
    
  43.   componentWillUnmount() {
    
  44.     window.clearInterval(this._interval);
    
  45.   }
    
  46. 
    
  47.   onTick = () => {
    
  48.     var nextDegrees = this.state.degrees + BASE_VEL + this.state.velocity;
    
  49.     var nextVelocity = this.state.velocity * this.state.drag;
    
  50.     this.setState({degrees: nextDegrees, velocity: nextVelocity});
    
  51.   };
    
  52. 
    
  53.   /**
    
  54.    * When mousing down, we increase the friction down the velocity.
    
  55.    */
    
  56.   handleMouseDown = () => {
    
  57.     this.setState({drag: MOUSE_DOWN_DRAG});
    
  58.   };
    
  59. 
    
  60.   /**
    
  61.    * Cause the rotation to "spring".
    
  62.    */
    
  63.   handleMouseUp = () => {
    
  64.     var nextVelocity = Math.min(this.state.velocity + CLICK_ACCEL, MAX_VEL);
    
  65.     this.setState({velocity: nextVelocity, drag: MOUSE_UP_DRAG});
    
  66.   };
    
  67. 
    
  68.   /**
    
  69.    * This is the "main" method for any component. The React API allows you to
    
  70.    * describe the structure of your UI component at *any* point in time.
    
  71.    */
    
  72.   render() {
    
  73.     return (
    
  74.       <Surface width={700} height={700} style={{cursor: 'pointer'}}>
    
  75.         {this.renderGraphic(this.state.degrees)}
    
  76.       </Surface>
    
  77.     );
    
  78.   }
    
  79. 
    
  80.   /**
    
  81.    * Better SVG support for React coming soon.
    
  82.    */
    
  83.   renderGraphic = rotation => {
    
  84.     return (
    
  85.       <Group onMouseDown={this.handleMouseDown} onMouseUp={this.handleMouseUp}>
    
  86.         <Group x={210} y={135}>
    
  87.           <Shape fill="rgba(0,0,0,0.1)" d={BORDER_PATH} />
    
  88.           <Shape fill="#7BC7BA" d={BG_PATH} />
    
  89.           <Shape fill="#DCDCDC" d={BAR_PATH} />
    
  90.           <Shape fill="#D97B76" d={RED_DOT_PATH} />
    
  91.           <Shape fill="#DBBB79" d={YELLOW_DOT_PATH} />
    
  92.           <Shape fill="#A6BD8A" d={GREEN_DOT_PATH} />
    
  93.           <Group x={55} y={29}>
    
  94.             <Group rotation={rotation} originX={84} originY={89}>
    
  95.               <Group x={84} y={89}>
    
  96.                 <Circle fill="#FFFFFF" radius={16} />
    
  97.               </Group>
    
  98.               <Group>
    
  99.                 <Shape d={RING_ONE_PATH} stroke="#FFFFFF" strokeWidth={8} />
    
  100.                 <Shape
    
  101.                   d={RING_TWO_PATH}
    
  102.                   transform={RING_TWO_ROTATE}
    
  103.                   stroke="#FFFFFF"
    
  104.                   strokeWidth={8}
    
  105.                 />
    
  106.                 <Shape
    
  107.                   d={RING_THREE_PATH}
    
  108.                   transform={RING_THREE_ROTATE}
    
  109.                   stroke="#FFFFFF"
    
  110.                   strokeWidth={8}
    
  111.                 />
    
  112.               </Group>
    
  113.             </Group>
    
  114.           </Group>
    
  115.         </Group>
    
  116.       </Group>
    
  117.     );
    
  118.   };
    
  119. }
    
  120. 
    
  121. var BORDER_PATH =
    
  122.   'M3.00191459,4 C1.34400294,4 0,5.34785514 0,7.00550479 L0,220.994495 C0,222.65439 1.34239483,224 3.00191459,224 L276.998085,224 C278.655997,224 280,222.652145 280,220.994495 L280,7.00550479 C280,5.34561033 278.657605,4 276.998085,4 L3.00191459,4 Z M3.00191459,4';
    
  123. var BG_PATH =
    
  124.   'M3.00191459,1 C1.34400294,1 0,2.34785514 0,4.00550479 L0,217.994495 C0,219.65439 1.34239483,221 3.00191459,221 L276.998085,221 C278.655997,221 280,219.652145 280,217.994495 L280,4.00550479 C280,2.34561033 278.657605,1 276.998085,1 L3.00191459,1 Z M3.00191459,1';
    
  125. var BAR_PATH =
    
  126.   'M3.00191459,0 C1.34400294,0 0,1.34559019 0,3.00878799 L0,21 C0,21 0,21 0,21 L280,21 C280,21 280,21 280,21 L280,3.00878799 C280,1.34708027 278.657605,0 276.998085,0 L3.00191459,0 Z M3.00191459,0';
    
  127. var RED_DOT_PATH =
    
  128.   'M12.5,17 C16.0898511,17 19,14.0898511 19,10.5 C19,6.91014895 16.0898511,4 12.5,4 C8.91014895,4 6,6.91014895 6,10.5 C6,14.0898511 8.91014895,17 12.5,17 Z M12.5,17';
    
  129. var YELLOW_DOT_PATH =
    
  130.   'M31.5,17 C35.0898511,17 38,14.0898511 38,10.5 C38,6.91014895 35.0898511,4 31.5,4 C27.9101489,4 25,6.91014895 25,10.5 C25,14.0898511 27.9101489,17 31.5,17 Z M31.5,17';
    
  131. var GREEN_DOT_PATH =
    
  132.   'M50.5,17 C54.0898511,17 57,14.0898511 57,10.5 C57,6.91014895 54.0898511,4 50.5,4 C46.9101489,4 44,6.91014895 44,10.5 C44,14.0898511 46.9101489,17 50.5,17 Z M50.5,17';
    
  133. var RING_ONE_PATH =
    
  134.   'M84,121 C130.391921,121 168,106.673113 168,89 C168,71.3268871 130.391921,57 84,57 C37.6080787,57 0,71.3268871 0,89 C0,106.673113 37.6080787,121 84,121 Z M84,121';
    
  135. var RING_TWO_PATH =
    
  136.   'M84,121 C130.391921,121 168,106.673113 168,89 C168,71.3268871 130.391921,57 84,57 C37.6080787,57 0,71.3268871 0,89 C0,106.673113 37.6080787,121 84,121 Z M84,121';
    
  137. var RING_THREE_PATH =
    
  138.   'M84,121 C130.391921,121 168,106.673113 168,89 C168,71.3268871 130.391921,57 84,57 C37.6080787,57 0,71.3268871 0,89 C0,106.673113 37.6080787,121 84,121 Z M84,121';
    
  139. var RING_TWO_ROTATE = new Transform()
    
  140.   .translate(84.0, 89.0)
    
  141.   .rotate(-240.0)
    
  142.   .translate(-84.0, -89.0);
    
  143. var RING_THREE_ROTATE = new Transform()
    
  144.   .translate(84.0, 89.0)
    
  145.   .rotate(-300.0)
    
  146.   .translate(-84.0, -89.0);
    
  147. 
    
  148. module.exports = VectorWidget;