From 7ff922cf2a0be52941e5b033470d72c5ff81102e Mon Sep 17 00:00:00 2001 From: Sophie Alpert Date: Wed, 6 Sep 2017 15:10:14 -0700 Subject: [PATCH] Pull in react-art/lib/{Circle,Rectangle,Wedge}.art (#10629) * Import react-art/lib/{Circle,Rectangle,Wedge}.art Copied from react-art@0.15.1 built files. * Changes to built files to make ART shapes work Test Plan: Opened the fixture. React logo shows up with its normal dot, now rendered by a ``. --- .eslintignore | 1 + fixtures/art/VectorWidget.js | 7 +- packages/react-art/lib/Circle.art.js | 54 +++++++ packages/react-art/lib/Rectangle.art.js | 138 +++++++++++++++++ packages/react-art/lib/Wedge.art.js | 188 ++++++++++++++++++++++++ packages/react-art/package.json | 4 +- 6 files changed, 388 insertions(+), 4 deletions(-) create mode 100644 packages/react-art/lib/Circle.art.js create mode 100644 packages/react-art/lib/Rectangle.art.js create mode 100644 packages/react-art/lib/Wedge.art.js diff --git a/.eslintignore b/.eslintignore index 6804aa2019b8a..b8daf1c6063d0 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1,6 +1,7 @@ # We can probably lint these later but not important at this point src/renderers/art src/__mocks__/vendor +packages/react-art/lib # But not in docs/_js/examples/* docs/_js/*.js docs/js/ diff --git a/fixtures/art/VectorWidget.js b/fixtures/art/VectorWidget.js index 9c20ed3de269d..6b317aaa01f67 100644 --- a/fixtures/art/VectorWidget.js +++ b/fixtures/art/VectorWidget.js @@ -8,6 +8,7 @@ */ 'use strict'; +var Circle = require('react-art/lib/Circle.art'); var React = require('react'); var ReactART = require('react-art'); var Group = ReactART.Group; @@ -93,7 +94,9 @@ class VectorWidget extends React.Component { - + + + + * + */ + +var PropTypes = require('prop-types'); +var React = require('react'); +var ReactART = require('..'); + +var createReactClass = require('create-react-class'); + +var Path = ReactART.Path; +var Shape = ReactART.Shape; + +/** + * Circle is a React component for drawing circles. Like other ReactART + * components, it must be used in a . + */ +var Circle = createReactClass({ + displayName: 'Circle', + + propTypes: { + radius: PropTypes.number.isRequired + }, + + render: function render() { + var radius = this.props.radius; + + var path = Path().moveTo(0, -radius).arc(0, radius * 2, radius).arc(0, radius * -2, radius).close(); + return React.createElement(Shape, _extends({}, this.props, { d: path })); + } +}); + +module.exports = Circle; diff --git a/packages/react-art/lib/Rectangle.art.js b/packages/react-art/lib/Rectangle.art.js new file mode 100644 index 0000000000000..c82e4c51eed87 --- /dev/null +++ b/packages/react-art/lib/Rectangle.art.js @@ -0,0 +1,138 @@ +'use strict'; + +var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; + +/** + * Copyright (c) 2013-present Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * @providesModule Rectangle.art + * @typechecks + * + * Example usage: + * + * + * Additional optional properties: + * (Number) radius + * (Number) radiusTopLeft + * (Number) radiusTopRight + * (Number) radiusBottomLeft + * (Number) radiusBottomRight + * + */ + +var PropTypes = require('prop-types'); +var React = require('react'); +var ReactART = require('..'); + +var createReactClass = require('create-react-class'); + +var Shape = ReactART.Shape; +var Path = ReactART.Path; + +/** + * Rectangle is a React component for drawing rectangles. Like other ReactART + * components, it must be used in a . + */ +var Rectangle = createReactClass({ + displayName: 'Rectangle', + + propTypes: { + width: PropTypes.number.isRequired, + height: PropTypes.number.isRequired, + radius: PropTypes.number, + radiusTopLeft: PropTypes.number, + radiusTopRight: PropTypes.number, + radiusBottomRight: PropTypes.number, + radiusBottomLeft: PropTypes.number + }, + + render: function render() { + var width = this.props.width; + var height = this.props.height; + var radius = this.props.radius ? this.props.radius : 0; + + // if unspecified, radius(Top|Bottom)(Left|Right) defaults to the radius + // property + var tl = this.props.radiusTopLeft ? this.props.radiusTopLeft : radius; + var tr = this.props.radiusTopRight ? this.props.radiusTopRight : radius; + var br = this.props.radiusBottomRight ? this.props.radiusBottomRight : radius; + var bl = this.props.radiusBottomLeft ? this.props.radiusBottomLeft : radius; + + var path = Path(); + + // for negative width/height, offset the rectangle in the negative x/y + // direction. for negative radius, just default to 0. + if (width < 0) { + path.move(width, 0); + width = -width; + } + if (height < 0) { + path.move(0, height); + height = -height; + } + if (tl < 0) { + tl = 0; + } + if (tr < 0) { + tr = 0; + } + if (br < 0) { + br = 0; + } + if (bl < 0) { + bl = 0; + } + + // disable border radius if it doesn't fit within the specified + // width/height + if (tl + tr > width) { + tl = 0;tr = 0; + } + if (bl + br > width) { + bl = 0;br = 0; + } + if (tl + bl > height) { + tl = 0;bl = 0; + } + if (tr + br > height) { + tr = 0;br = 0; + } + + path.move(0, tl); + + if (tl > 0) { + path.arc(tl, -tl); + } + path.line(width - (tr + tl), 0); + + if (tr > 0) { + path.arc(tr, tr); + } + path.line(0, height - (tr + br)); + + if (br > 0) { + path.arc(-br, br); + } + path.line(-width + (br + bl), 0); + + if (bl > 0) { + path.arc(-bl, -bl); + } + path.line(0, -height + (bl + tl)); + + return React.createElement(Shape, _extends({}, this.props, { d: path })); + } + +}); + +module.exports = Rectangle; diff --git a/packages/react-art/lib/Wedge.art.js b/packages/react-art/lib/Wedge.art.js new file mode 100644 index 0000000000000..d1179d37a7bbe --- /dev/null +++ b/packages/react-art/lib/Wedge.art.js @@ -0,0 +1,188 @@ +'use strict'; + +var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; + +/** + * Copyright (c) 2013-present Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * @providesModule Wedge.art + * @typechecks + * + * Example usage: + * + * + * Additional optional property: + * (Int) innerRadius + * + */ + +var PropTypes = require('prop-types'); +var React = require('react'); +var ReactART = require('..'); + +var createReactClass = require('create-react-class'); + +var Shape = ReactART.Shape; +var Path = ReactART.Path; + +/** + * Wedge is a React component for drawing circles, wedges and arcs. Like other + * ReactART components, it must be used in a . + */ +var Wedge = createReactClass({ + displayName: 'Wedge', + + + propTypes: { + outerRadius: PropTypes.number.isRequired, + startAngle: PropTypes.number.isRequired, + endAngle: PropTypes.number.isRequired, + innerRadius: PropTypes.number + }, + + circleRadians: Math.PI * 2, + + radiansPerDegree: Math.PI / 180, + + /** + * _degreesToRadians(degrees) + * + * Helper function to convert degrees to radians + * + * @param {number} degrees + * @return {number} + */ + _degreesToRadians: function _degreesToRadians(degrees) { + if (degrees !== 0 && degrees % 360 === 0) { + // 360, 720, etc. + return this.circleRadians; + } else { + return degrees * this.radiansPerDegree % this.circleRadians; + } + }, + + /** + * _createCirclePath(or, ir) + * + * Creates the ReactART Path for a complete circle. + * + * @param {number} or The outer radius of the circle + * @param {number} ir The inner radius, greater than zero for a ring + * @return {object} + */ + _createCirclePath: function _createCirclePath(or, ir) { + var path = Path(); + + path.move(0, or).arc(or * 2, 0, or).arc(-or * 2, 0, or); + + if (ir) { + path.move(or - ir, 0).counterArc(ir * 2, 0, ir).counterArc(-ir * 2, 0, ir); + } + + path.close(); + + return path; + }, + + /** + * _createArcPath(sa, ea, ca, or, ir) + * + * Creates the ReactART Path for an arc or wedge. + * + * @param {number} startAngle The starting degrees relative to 12 o'clock + * @param {number} endAngle The ending degrees relative to 12 o'clock + * @param {number} or The outer radius in pixels + * @param {number} ir The inner radius in pixels, greater than zero for an arc + * @return {object} + */ + _createArcPath: function _createArcPath(startAngle, endAngle, or, ir) { + var path = Path(); + + // angles in radians + var sa = this._degreesToRadians(startAngle); + var ea = this._degreesToRadians(endAngle); + + // central arc angle in radians + var ca = sa > ea ? this.circleRadians - sa + ea : ea - sa; + + // cached sine and cosine values + var ss = Math.sin(sa); + var es = Math.sin(ea); + var sc = Math.cos(sa); + var ec = Math.cos(ea); + + // cached differences + var ds = es - ss; + var dc = ec - sc; + var dr = ir - or; + + // if the angle is over pi radians (180 degrees) + // we will need to let the drawing method know. + var large = ca > Math.PI; + + // TODO (sema) Please improve theses comments to make the math + // more understandable. + // + // Formula for a point on a circle at a specific angle with a center + // at (0, 0): + // x = radius * Math.sin(radians) + // y = radius * Math.cos(radians) + // + // For our starting point, we offset the formula using the outer + // radius because our origin is at (top, left). + // In typical web layout fashion, we are drawing in quadrant IV + // (a.k.a. Southeast) where x is positive and y is negative. + // + // The arguments for path.arc and path.counterArc used below are: + // (endX, endY, radiusX, radiusY, largeAngle) + + path.move(or + or * ss, or - or * sc) // move to starting point + .arc(or * ds, or * -dc, or, or, large) // outer arc + .line(dr * es, dr * -ec); // width of arc or wedge + + if (ir) { + path.counterArc(ir * -ds, ir * dc, ir, ir, large); // inner arc + } + + return path; + }, + + render: function render() { + // angles are provided in degrees + var startAngle = this.props.startAngle; + var endAngle = this.props.endAngle; + if (startAngle - endAngle === 0) { + return; + } + + // radii are provided in pixels + var innerRadius = this.props.innerRadius || 0; + var outerRadius = this.props.outerRadius; + + // sorted radii + var ir = Math.min(innerRadius, outerRadius); + var or = Math.max(innerRadius, outerRadius); + + var path; + if (endAngle >= startAngle + 360) { + path = this._createCirclePath(or, ir); + } else { + path = this._createArcPath(startAngle, endAngle, or, ir); + } + + return React.createElement(Shape, _extends({}, this.props, { d: path })); + } + +}); + +module.exports = Wedge; diff --git a/packages/react-art/package.json b/packages/react-art/package.json index 27b9908095852..2fba921407109 100644 --- a/packages/react-art/package.json +++ b/packages/react-art/package.json @@ -18,9 +18,11 @@ }, "homepage": "https://facebook.github.io/react/", "dependencies": { + "create-react-class": "^15.6.0", "fbjs": "^0.8.9", "loose-envify": "^1.1.0", - "object-assign": "^4.1.0" + "object-assign": "^4.1.0", + "prop-types": "^15.5.6" }, "peerDependencies": { "react": "^16.0.0-beta.5"