mirror of
https://github.com/zoriya/react-native-svg.git
synced 2025-12-20 14:05:09 +00:00
refactor viewBox for svg
This commit is contained in:
@@ -89,7 +89,6 @@
|
|||||||
"no-caller": 1, // disallow use of arguments.caller or arguments.callee
|
"no-caller": 1, // disallow use of arguments.caller or arguments.callee
|
||||||
"no-div-regex": 1, // disallow division operators explicitly at beginning of regular expression (off by default)
|
"no-div-regex": 1, // disallow division operators explicitly at beginning of regular expression (off by default)
|
||||||
"no-else-return": 0, // disallow else after a return in an if (off by default)
|
"no-else-return": 0, // disallow else after a return in an if (off by default)
|
||||||
"no-empty-label": 1, // disallow use of labels for anything other then loops and switches
|
|
||||||
"no-eq-null": 0, // disallow comparisons to null without a type-checking operator (off by default)
|
"no-eq-null": 0, // disallow comparisons to null without a type-checking operator (off by default)
|
||||||
"no-eval": 1, // disallow use of eval()
|
"no-eval": 1, // disallow use of eval()
|
||||||
"no-extend-native": 1, // disallow adding to native types
|
"no-extend-native": 1, // disallow adding to native types
|
||||||
@@ -184,7 +183,7 @@
|
|||||||
"quote-props": 0, // require quotes around object literal property names (off by default)
|
"quote-props": 0, // require quotes around object literal property names (off by default)
|
||||||
"semi": 1, // require or disallow use of semicolons instead of ASI
|
"semi": 1, // require or disallow use of semicolons instead of ASI
|
||||||
"sort-vars": 0, // sort variables within the same declaration block (off by default)
|
"sort-vars": 0, // sort variables within the same declaration block (off by default)
|
||||||
"space-after-keywords": 1, // require a space after certain keywords (off by default)
|
"keyword-spacing": 1, // require a space after certain keywords (off by default)
|
||||||
"space-in-brackets": 0, // require or disallow spaces inside brackets (off by default)
|
"space-in-brackets": 0, // require or disallow spaces inside brackets (off by default)
|
||||||
"space-in-parens": 0, // require or disallow spaces inside parentheses (off by default)
|
"space-in-parens": 0, // require or disallow spaces inside parentheses (off by default)
|
||||||
"space-infix-ops": 1, // require spaces around operators
|
"space-infix-ops": 1, // require spaces around operators
|
||||||
|
|||||||
@@ -78,7 +78,6 @@ const icon = <Svg
|
|||||||
</Svg>;
|
</Svg>;
|
||||||
|
|
||||||
const samples = [CircleExample, StrokeCircle, StrokeOpacityCircle];
|
const samples = [CircleExample, StrokeCircle, StrokeOpacityCircle];
|
||||||
|
|
||||||
export {
|
export {
|
||||||
icon,
|
icon,
|
||||||
samples
|
samples
|
||||||
|
|||||||
@@ -23,7 +23,8 @@ import Svg, {
|
|||||||
Circle,
|
Circle,
|
||||||
Rect,
|
Rect,
|
||||||
Path,
|
Path,
|
||||||
Line
|
Line,
|
||||||
|
G
|
||||||
} from 'react-native-svg';
|
} from 'react-native-svg';
|
||||||
|
|
||||||
class SvgExample extends Component{
|
class SvgExample extends Component{
|
||||||
@@ -84,19 +85,21 @@ class SvgOpacity extends Component{
|
|||||||
}
|
}
|
||||||
|
|
||||||
class SvgViewbox extends Component{
|
class SvgViewbox extends Component{
|
||||||
static title = 'SVG with `viewbox="40 20 100 40"`';
|
static title = 'SVG with `viewBox="40 20 100 40" and preserveAspectRatio="none"`';
|
||||||
render() {
|
render() {
|
||||||
return <Svg
|
return <Svg
|
||||||
height="100"
|
height="100"
|
||||||
width="100"
|
width="100"
|
||||||
viewbox="40 20 100 40"
|
viewBox="40 20 100 40"
|
||||||
preserveAspectRatio="none"
|
preserveAspectRatio="none"
|
||||||
>
|
>
|
||||||
<Rect x="0" y="0" width="100" height="100" fill="black" />
|
<G>
|
||||||
<Circle cx="50" cy="50" r="30" fill="yellow" />
|
<Rect x="0" y="0" width="100" height="100" fill="red" />
|
||||||
<Circle cx="40" cy="40" r="4" fill="black" />
|
<Circle cx="50" cy="50" r="30" fill="yellow" />
|
||||||
<Circle cx="60" cy="40" r="4" fill="black" />
|
<Circle cx="40" cy="40" r="4" fill="black" />
|
||||||
<Path d="M 40 60 A 10 10 0 0 0 60 60" stroke="black" />
|
<Circle cx="60" cy="40" r="4" fill="black" />
|
||||||
|
<Path d="M 40 60 A 10 10 0 0 0 60 60" stroke="black" />
|
||||||
|
</G>
|
||||||
</Svg>;
|
</Svg>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,11 +18,9 @@ class Svg extends Component{
|
|||||||
opacity: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
opacity: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
||||||
width: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
width: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
||||||
height: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
height: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
||||||
viewbox: PropTypes.string,
|
// more detail https://svgwg.org/svg2-draft/coords.html#ViewBoxAttribute
|
||||||
// TODO: complete other values of preserveAspectRatio
|
viewBox: PropTypes.string,
|
||||||
// http://www.justinmccandless.com/demos/viewbox/index.html
|
preserveAspectRatio: PropTypes.string
|
||||||
// http://tutorials.jenkov.com/svg/svg-viewport-view-box.html
|
|
||||||
preserveAspectRatio: PropTypes.string // preserveAspectRatio only supports 'none' for now
|
|
||||||
};
|
};
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
@@ -51,13 +49,25 @@ class Svg extends Component{
|
|||||||
let opacity = +props.opacity;
|
let opacity = +props.opacity;
|
||||||
let width = +props.width;
|
let width = +props.width;
|
||||||
let height = +props.height;
|
let height = +props.height;
|
||||||
let flexLayout = isNaN(width) || isNaN(height);
|
let viewBox = props.viewBox;
|
||||||
|
let dimensions;
|
||||||
|
|
||||||
let content = (props.viewbox && !flexLayout) ? <ViewBox
|
if (width && height) {
|
||||||
viewbox={props.viewbox}
|
dimensions = {
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
flex: 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (props.viewbox) {
|
||||||
|
viewBox = props.viewbox;
|
||||||
|
console.warn('Prop `viewbox` is deprecated. please use `viewBox` instead.');
|
||||||
|
}
|
||||||
|
|
||||||
|
let content = viewBox ? <ViewBox
|
||||||
|
viewBox={viewBox}
|
||||||
preserveAspectRatio={props.preserveAspectRatio}
|
preserveAspectRatio={props.preserveAspectRatio}
|
||||||
width={props.width}
|
|
||||||
height={props.height}
|
|
||||||
>{props.children}</ViewBox> : props.children;
|
>{props.children}</ViewBox> : props.children;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -66,7 +76,7 @@ class Svg extends Component{
|
|||||||
opacity={null}
|
opacity={null}
|
||||||
width={null}
|
width={null}
|
||||||
height={null}
|
height={null}
|
||||||
viewbox={null}
|
viewBox={null}
|
||||||
preserveAspectRatio={null}
|
preserveAspectRatio={null}
|
||||||
ref={ele => this.root = ele}
|
ref={ele => this.root = ele}
|
||||||
style={[
|
style={[
|
||||||
@@ -75,11 +85,7 @@ class Svg extends Component{
|
|||||||
!isNaN(opacity) && {
|
!isNaN(opacity) && {
|
||||||
opacity
|
opacity
|
||||||
},
|
},
|
||||||
!flexLayout && {
|
dimensions
|
||||||
width,
|
|
||||||
height,
|
|
||||||
flex: 0
|
|
||||||
}
|
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
{content}
|
{content}
|
||||||
|
|||||||
@@ -1,38 +1,73 @@
|
|||||||
import React, {Component} from 'react';
|
import React, {Component, PropTypes} from 'react';
|
||||||
|
import createReactNativeComponentClass from 'react/lib/createReactNativeComponentClass';
|
||||||
|
import {ViewBoxAttributes} from '../lib/attributes';
|
||||||
import G from './G';
|
import G from './G';
|
||||||
import extractViewbox from '../lib/extract/extractViewbox';
|
import _ from 'lodash';
|
||||||
|
|
||||||
|
const meetOrSliceTypes = {
|
||||||
|
meet: 0,
|
||||||
|
slice: 1,
|
||||||
|
none: 2
|
||||||
|
};
|
||||||
|
|
||||||
|
const alignEnum = _.reduce([
|
||||||
|
'xMinMin', 'xMidYMin', 'xMaxYMin',
|
||||||
|
'xMinYMid', 'xMidYMid', 'xMaxYMid',
|
||||||
|
'xMinYMax', 'xMidYMax', 'xMaxYMax',
|
||||||
|
'none'
|
||||||
|
], (prev, name) => {
|
||||||
|
prev[name] = name;
|
||||||
|
return prev;
|
||||||
|
}, {});
|
||||||
|
|
||||||
|
const numberRegExp = /^\d*\.?\d*%?$/;
|
||||||
|
const spacesRegExp = /\s+/;
|
||||||
|
|
||||||
class ViewBox extends Component{
|
class ViewBox extends Component{
|
||||||
static displayName = 'ViewBox';
|
static displayName = 'ViewBox';
|
||||||
|
|
||||||
|
static propTypes = {
|
||||||
|
viewBox: PropTypes.string.isRequired,
|
||||||
|
preserveAspectRatio: PropTypes.string
|
||||||
|
};
|
||||||
|
|
||||||
|
static defaultProps = {
|
||||||
|
preserveAspectRatio: 'xMidYMid meet'
|
||||||
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
let viewbox = extractViewbox(this.props);
|
let {viewBox, preserveAspectRatio} = this.props;
|
||||||
let scaleX = 1;
|
|
||||||
let scaleY = 1;
|
let params = viewBox.trim().split(spacesRegExp);
|
||||||
let x = 0;
|
|
||||||
let y = 0;
|
if (params.length !== 4 || !_.some(params, param => param && numberRegExp.test(param))) {
|
||||||
if (viewbox) {
|
console.warn('`viewBox` expected a string like `minX minY width height`, but got:' + viewBox);
|
||||||
scaleX = viewbox.scaleX;
|
return <G>
|
||||||
scaleY = viewbox.scaleY;
|
{this.props.children}
|
||||||
x = viewbox.x;
|
</G>
|
||||||
y = viewbox.y;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let modes = preserveAspectRatio.trim().split(spacesRegExp);
|
||||||
|
|
||||||
console.log(viewbox);
|
let meetOrSlice = meetOrSliceTypes[modes[1]] || 0;
|
||||||
return <G
|
let align = alignEnum[modes[0]] || 'xMidYMid';
|
||||||
{...this.props}
|
return <RNSVGViewBox
|
||||||
x={x}
|
minX={params[0]}
|
||||||
y={y}
|
minY={params[1]}
|
||||||
scaleX={scaleX}
|
vbWidth={params[2]}
|
||||||
scaleY={scaleY}
|
vbHeight={params[3]}
|
||||||
preserveAspectRatio={null}
|
align={align}
|
||||||
viewbox={null}
|
meetOrSlice={meetOrSlice}
|
||||||
id={null}
|
|
||||||
>
|
>
|
||||||
{(!scaleX || !scaleY) ? null : this.props.children}
|
{this.props.children}
|
||||||
</G>;
|
</RNSVGViewBox>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const RNSVGViewBox = createReactNativeComponentClass({
|
||||||
|
validAttributes: ViewBoxAttributes,
|
||||||
|
uiViewClassName: 'RNSVGViewBox'
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
export default ViewBox;
|
export default ViewBox;
|
||||||
|
|||||||
@@ -7,7 +7,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#import "RNSVGGroup.h"
|
#import "RNSVGGroup.h"
|
||||||
#import <objc/runtime.h>
|
|
||||||
|
|
||||||
@implementation RNSVGGroup
|
@implementation RNSVGGroup
|
||||||
|
|
||||||
|
|||||||
@@ -69,33 +69,37 @@
|
|||||||
|
|
||||||
- (void)renderLayerTo:(CGContextRef)context
|
- (void)renderLayerTo:(CGContextRef)context
|
||||||
{
|
{
|
||||||
CGRect box = CGContextGetClipBoundingBox(context);
|
CGRect rect = [self getRect:context];
|
||||||
float height = CGRectGetHeight(box);
|
|
||||||
float width = CGRectGetWidth(box);
|
|
||||||
|
|
||||||
RNSVGPercentageConverter* convert = [[RNSVGPercentageConverter alloc] init];
|
|
||||||
CGFloat x = [convert stringToFloat:self.x relative:width offset:0];
|
|
||||||
CGFloat y = [convert stringToFloat:self.y relative:height offset:0];
|
|
||||||
CGFloat w = [convert stringToFloat:self.width relative:width offset:0];
|
|
||||||
CGFloat h = [convert stringToFloat:self.height relative:height offset:0];
|
|
||||||
|
|
||||||
// add hit area
|
// add hit area
|
||||||
self.hitArea = CGPathCreateMutable();
|
self.hitArea = CGPathCreateMutable();
|
||||||
CGPathRef rect = CGPathCreateWithRect(CGRectMake(x, y, w, h), nil);
|
CGPathRef path = CGPathCreateWithRect(rect, nil);
|
||||||
CGPathAddPath(self.hitArea, nil, rect);
|
CGPathAddPath(self.hitArea, nil, path);
|
||||||
CGPathRelease(rect);
|
CGPathRelease(path);
|
||||||
|
|
||||||
if (self.opacity == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
[self clip:context];
|
[self clip:context];
|
||||||
|
|
||||||
CGContextSaveGState(context);
|
CGContextSaveGState(context);
|
||||||
CGContextTranslateCTM(context, 0, h);
|
CGContextTranslateCTM(context, 0, rect.size.height);
|
||||||
CGContextScaleCTM(context, 1.0, -1.0);
|
CGContextScaleCTM(context, 1.0, -1.0);
|
||||||
CGContextDrawImage(context, CGRectMake(x, -y, w, h), image);
|
CGContextDrawImage(context, rect, image);
|
||||||
CGContextRestoreGState(context);
|
CGContextRestoreGState(context);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (CGRect)getRect:(CGContextRef)context
|
||||||
|
{
|
||||||
|
[self setBoundingBox:context];
|
||||||
|
CGFloat x = [self getWidthRelatedValue:self.x];
|
||||||
|
CGFloat y = [self getHeightRelatedValue:self.y];
|
||||||
|
CGFloat width = [self getWidthRelatedValue:self.width];
|
||||||
|
CGFloat height = [self getHeightRelatedValue:self.height];
|
||||||
|
return CGRectMake(x, y, width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (CGPathRef)getPath:(CGContextRef)context
|
||||||
|
{
|
||||||
|
CGMutablePathRef path = CGPathCreateMutable();
|
||||||
|
CGPathAddRect(path, nil, [self getRect:context]);
|
||||||
|
return (CGPathRef)CFAutorelease(path);
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -23,6 +23,8 @@
|
|||||||
1039D2951CE71EC2001E90A8 /* RNSVGText.m in Sources */ = {isa = PBXBuildFile; fileRef = 1039D2901CE71EC2001E90A8 /* RNSVGText.m */; };
|
1039D2951CE71EC2001E90A8 /* RNSVGText.m in Sources */ = {isa = PBXBuildFile; fileRef = 1039D2901CE71EC2001E90A8 /* RNSVGText.m */; };
|
||||||
1039D2A01CE72177001E90A8 /* RCTConvert+RNSVG.m in Sources */ = {isa = PBXBuildFile; fileRef = 1039D29C1CE72177001E90A8 /* RCTConvert+RNSVG.m */; };
|
1039D2A01CE72177001E90A8 /* RCTConvert+RNSVG.m in Sources */ = {isa = PBXBuildFile; fileRef = 1039D29C1CE72177001E90A8 /* RCTConvert+RNSVG.m */; };
|
||||||
1039D2B01CE72F27001E90A8 /* RNSVGPercentageConverter.m in Sources */ = {isa = PBXBuildFile; fileRef = 1039D2AF1CE72F27001E90A8 /* RNSVGPercentageConverter.m */; };
|
1039D2B01CE72F27001E90A8 /* RNSVGPercentageConverter.m in Sources */ = {isa = PBXBuildFile; fileRef = 1039D2AF1CE72F27001E90A8 /* RNSVGPercentageConverter.m */; };
|
||||||
|
10ABC7331D435915006CCF6E /* RNSVGViewBoxManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 10ABC7321D435915006CCF6E /* RNSVGViewBoxManager.m */; };
|
||||||
|
10ABC7361D43595E006CCF6E /* RNSVGViewBox.m in Sources */ = {isa = PBXBuildFile; fileRef = 10ABC7351D43595E006CCF6E /* RNSVGViewBox.m */; };
|
||||||
10BA0D341CE74E3100887C2B /* RNSVGCircleManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 10BA0D1D1CE74E3100887C2B /* RNSVGCircleManager.m */; };
|
10BA0D341CE74E3100887C2B /* RNSVGCircleManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 10BA0D1D1CE74E3100887C2B /* RNSVGCircleManager.m */; };
|
||||||
10BA0D351CE74E3100887C2B /* RNSVGEllipseManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 10BA0D1F1CE74E3100887C2B /* RNSVGEllipseManager.m */; };
|
10BA0D351CE74E3100887C2B /* RNSVGEllipseManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 10BA0D1F1CE74E3100887C2B /* RNSVGEllipseManager.m */; };
|
||||||
10BA0D361CE74E3100887C2B /* RNSVGGroupManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 10BA0D211CE74E3100887C2B /* RNSVGGroupManager.m */; };
|
10BA0D361CE74E3100887C2B /* RNSVGGroupManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 10BA0D211CE74E3100887C2B /* RNSVGGroupManager.m */; };
|
||||||
@@ -94,11 +96,16 @@
|
|||||||
1039D2911CE71EC2001E90A8 /* RNSVGTextFrame.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RNSVGTextFrame.h; path = Text/RNSVGTextFrame.h; sourceTree = "<group>"; };
|
1039D2911CE71EC2001E90A8 /* RNSVGTextFrame.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RNSVGTextFrame.h; path = Text/RNSVGTextFrame.h; sourceTree = "<group>"; };
|
||||||
1039D29B1CE72177001E90A8 /* RCTConvert+RNSVG.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "RCTConvert+RNSVG.h"; path = "Utils/RCTConvert+RNSVG.h"; sourceTree = "<group>"; };
|
1039D29B1CE72177001E90A8 /* RCTConvert+RNSVG.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "RCTConvert+RNSVG.h"; path = "Utils/RCTConvert+RNSVG.h"; sourceTree = "<group>"; };
|
||||||
1039D29C1CE72177001E90A8 /* RCTConvert+RNSVG.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "RCTConvert+RNSVG.m"; path = "Utils/RCTConvert+RNSVG.m"; sourceTree = "<group>"; };
|
1039D29C1CE72177001E90A8 /* RCTConvert+RNSVG.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "RCTConvert+RNSVG.m"; path = "Utils/RCTConvert+RNSVG.m"; sourceTree = "<group>"; };
|
||||||
1039D29D1CE72177001E90A8 /* RNSVGCGFCRule.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RNSVGCGFCRule.h; path = Utils/RNSVGCGFCRule.h; sourceTree = "<group>"; };
|
|
||||||
1039D29E1CE72177001E90A8 /* RNSVGCGFloatArray.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RNSVGCGFloatArray.h; path = Utils/RNSVGCGFloatArray.h; sourceTree = "<group>"; };
|
1039D29E1CE72177001E90A8 /* RNSVGCGFloatArray.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RNSVGCGFloatArray.h; path = Utils/RNSVGCGFloatArray.h; sourceTree = "<group>"; };
|
||||||
1039D2A11CE721A7001E90A8 /* RNSVGContainer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNSVGContainer.h; sourceTree = "<group>"; };
|
1039D2A11CE721A7001E90A8 /* RNSVGContainer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNSVGContainer.h; sourceTree = "<group>"; };
|
||||||
1039D2AE1CE72F27001E90A8 /* RNSVGPercentageConverter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RNSVGPercentageConverter.h; path = Utils/RNSVGPercentageConverter.h; sourceTree = "<group>"; };
|
1039D2AE1CE72F27001E90A8 /* RNSVGPercentageConverter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RNSVGPercentageConverter.h; path = Utils/RNSVGPercentageConverter.h; sourceTree = "<group>"; };
|
||||||
1039D2AF1CE72F27001E90A8 /* RNSVGPercentageConverter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = RNSVGPercentageConverter.m; path = Utils/RNSVGPercentageConverter.m; sourceTree = "<group>"; };
|
1039D2AF1CE72F27001E90A8 /* RNSVGPercentageConverter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = RNSVGPercentageConverter.m; path = Utils/RNSVGPercentageConverter.m; sourceTree = "<group>"; };
|
||||||
|
10ABC7311D435915006CCF6E /* RNSVGViewBoxManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNSVGViewBoxManager.h; sourceTree = "<group>"; };
|
||||||
|
10ABC7321D435915006CCF6E /* RNSVGViewBoxManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNSVGViewBoxManager.m; sourceTree = "<group>"; };
|
||||||
|
10ABC7341D43595E006CCF6E /* RNSVGViewBox.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNSVGViewBox.h; sourceTree = "<group>"; };
|
||||||
|
10ABC7351D43595E006CCF6E /* RNSVGViewBox.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNSVGViewBox.m; sourceTree = "<group>"; };
|
||||||
|
10ABC7371D439779006CCF6E /* RNSVGCGFCRule.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RNSVGCGFCRule.h; path = Utils/RNSVGCGFCRule.h; sourceTree = "<group>"; };
|
||||||
|
10ABC7381D43982B006CCF6E /* RNSVGVBMOS.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RNSVGVBMOS.h; path = Utils/RNSVGVBMOS.h; sourceTree = "<group>"; };
|
||||||
10BA0D1C1CE74E3100887C2B /* RNSVGCircleManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNSVGCircleManager.h; sourceTree = "<group>"; };
|
10BA0D1C1CE74E3100887C2B /* RNSVGCircleManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNSVGCircleManager.h; sourceTree = "<group>"; };
|
||||||
10BA0D1D1CE74E3100887C2B /* RNSVGCircleManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNSVGCircleManager.m; sourceTree = "<group>"; };
|
10BA0D1D1CE74E3100887C2B /* RNSVGCircleManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNSVGCircleManager.m; sourceTree = "<group>"; };
|
||||||
10BA0D1E1CE74E3100887C2B /* RNSVGEllipseManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNSVGEllipseManager.h; sourceTree = "<group>"; };
|
10BA0D1E1CE74E3100887C2B /* RNSVGEllipseManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNSVGEllipseManager.h; sourceTree = "<group>"; };
|
||||||
@@ -175,6 +182,8 @@
|
|||||||
10ED4AA11CF078830078BC02 /* RNSVGNode.m */,
|
10ED4AA11CF078830078BC02 /* RNSVGNode.m */,
|
||||||
0CF68AE11AF0549300FF9E5C /* RNSVGRenderable.h */,
|
0CF68AE11AF0549300FF9E5C /* RNSVGRenderable.h */,
|
||||||
0CF68AE21AF0549300FF9E5C /* RNSVGRenderable.m */,
|
0CF68AE21AF0549300FF9E5C /* RNSVGRenderable.m */,
|
||||||
|
10ABC7341D43595E006CCF6E /* RNSVGViewBox.h */,
|
||||||
|
10ABC7351D43595E006CCF6E /* RNSVGViewBox.m */,
|
||||||
0CF68AC21AF0540F00FF9E5C /* Products */,
|
0CF68AC21AF0540F00FF9E5C /* Products */,
|
||||||
);
|
);
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@@ -208,6 +217,8 @@
|
|||||||
0CF68AF81AF0549300FF9E5C /* ViewManagers */ = {
|
0CF68AF81AF0549300FF9E5C /* ViewManagers */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
10ABC7311D435915006CCF6E /* RNSVGViewBoxManager.h */,
|
||||||
|
10ABC7321D435915006CCF6E /* RNSVGViewBoxManager.m */,
|
||||||
10BEC1BE1D3F680F00FDCB19 /* RNSVGLinearGradientManager.h */,
|
10BEC1BE1D3F680F00FDCB19 /* RNSVGLinearGradientManager.h */,
|
||||||
10BEC1BF1D3F680F00FDCB19 /* RNSVGLinearGradientManager.m */,
|
10BEC1BF1D3F680F00FDCB19 /* RNSVGLinearGradientManager.m */,
|
||||||
10BEC1C01D3F680F00FDCB19 /* RNSVGRadialGradientManager.h */,
|
10BEC1C01D3F680F00FDCB19 /* RNSVGRadialGradientManager.h */,
|
||||||
@@ -299,11 +310,12 @@
|
|||||||
1039D29A1CE7212C001E90A8 /* Utils */ = {
|
1039D29A1CE7212C001E90A8 /* Utils */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
10ABC7381D43982B006CCF6E /* RNSVGVBMOS.h */,
|
||||||
|
10ABC7371D439779006CCF6E /* RNSVGCGFCRule.h */,
|
||||||
1039D2AE1CE72F27001E90A8 /* RNSVGPercentageConverter.h */,
|
1039D2AE1CE72F27001E90A8 /* RNSVGPercentageConverter.h */,
|
||||||
1039D2AF1CE72F27001E90A8 /* RNSVGPercentageConverter.m */,
|
1039D2AF1CE72F27001E90A8 /* RNSVGPercentageConverter.m */,
|
||||||
1039D29B1CE72177001E90A8 /* RCTConvert+RNSVG.h */,
|
1039D29B1CE72177001E90A8 /* RCTConvert+RNSVG.h */,
|
||||||
1039D29C1CE72177001E90A8 /* RCTConvert+RNSVG.m */,
|
1039D29C1CE72177001E90A8 /* RCTConvert+RNSVG.m */,
|
||||||
1039D29D1CE72177001E90A8 /* RNSVGCGFCRule.h */,
|
|
||||||
1039D29E1CE72177001E90A8 /* RNSVGCGFloatArray.h */,
|
1039D29E1CE72177001E90A8 /* RNSVGCGFloatArray.h */,
|
||||||
);
|
);
|
||||||
name = Utils;
|
name = Utils;
|
||||||
@@ -365,12 +377,14 @@
|
|||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
10BA0D3F1CE74E3100887C2B /* RNSVGTextManager.m in Sources */,
|
10BA0D3F1CE74E3100887C2B /* RNSVGTextManager.m in Sources */,
|
||||||
|
10ABC7361D43595E006CCF6E /* RNSVGViewBox.m in Sources */,
|
||||||
1039D28A1CE71EB7001E90A8 /* RNSVGImage.m in Sources */,
|
1039D28A1CE71EB7001E90A8 /* RNSVGImage.m in Sources */,
|
||||||
10BA0D4B1CE74E3D00887C2B /* RNSVGRect.m in Sources */,
|
10BA0D4B1CE74E3D00887C2B /* RNSVGRect.m in Sources */,
|
||||||
10BA0D341CE74E3100887C2B /* RNSVGCircleManager.m in Sources */,
|
10BA0D341CE74E3100887C2B /* RNSVGCircleManager.m in Sources */,
|
||||||
10BEC1BC1D3F66F500FDCB19 /* RNSVGLinearGradient.m in Sources */,
|
10BEC1BC1D3F66F500FDCB19 /* RNSVGLinearGradient.m in Sources */,
|
||||||
1039D2B01CE72F27001E90A8 /* RNSVGPercentageConverter.m in Sources */,
|
1039D2B01CE72F27001E90A8 /* RNSVGPercentageConverter.m in Sources */,
|
||||||
10BA0D491CE74E3D00887C2B /* RNSVGEllipse.m in Sources */,
|
10BA0D491CE74E3D00887C2B /* RNSVGEllipse.m in Sources */,
|
||||||
|
10ABC7331D435915006CCF6E /* RNSVGViewBoxManager.m in Sources */,
|
||||||
1039D28B1CE71EB7001E90A8 /* RNSVGPath.m in Sources */,
|
1039D28B1CE71EB7001E90A8 /* RNSVGPath.m in Sources */,
|
||||||
0CF68B0D1AF0549300FF9E5C /* RNSVGPattern.m in Sources */,
|
0CF68B0D1AF0549300FF9E5C /* RNSVGPattern.m in Sources */,
|
||||||
1023B4931D3DF5060051496D /* RNSVGUse.m in Sources */,
|
1023B4931D3DF5060051496D /* RNSVGUse.m in Sources */,
|
||||||
|
|||||||
@@ -29,6 +29,19 @@
|
|||||||
@property (nonatomic, assign) CGMutablePathRef hitArea;
|
@property (nonatomic, assign) CGMutablePathRef hitArea;
|
||||||
@property (nonatomic, copy) NSArray<NSString *> *propList;
|
@property (nonatomic, copy) NSArray<NSString *> *propList;
|
||||||
|
|
||||||
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event;
|
- (void)setBoundingBox:(CGContextRef)context;
|
||||||
|
|
||||||
|
- (CGFloat)getWidthRelatedValue:(NSString *)string;
|
||||||
|
|
||||||
|
- (CGFloat)getHeightRelatedValue:(NSString *)string;
|
||||||
|
|
||||||
|
- (CGFloat)getContextWidth;
|
||||||
|
|
||||||
|
- (CGFloat)getContextHeight;
|
||||||
|
|
||||||
|
- (CGFloat)getContextX;
|
||||||
|
|
||||||
|
- (CGFloat)getContextY;
|
||||||
|
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -7,11 +7,17 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#import "RNSVGRenderable.h"
|
#import "RNSVGRenderable.h"
|
||||||
|
#import "RNSVGPercentageConverter.h"
|
||||||
|
|
||||||
@implementation RNSVGRenderable
|
@implementation RNSVGRenderable
|
||||||
{
|
{
|
||||||
NSMutableDictionary *originProperties;
|
NSMutableDictionary *_originProperties;
|
||||||
NSArray *changedList;
|
NSArray *_changedList;
|
||||||
|
RNSVGPercentageConverter *_widthConverter;
|
||||||
|
RNSVGPercentageConverter *_heightConverter;
|
||||||
|
CGFloat _contextWidth;
|
||||||
|
CGFloat _contextHeight;
|
||||||
|
CGRect _boundingBox;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (id)init
|
- (id)init
|
||||||
@@ -137,6 +143,44 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
- (void)setBoundingBox:(CGContextRef)context
|
||||||
|
{
|
||||||
|
_boundingBox = CGContextGetClipBoundingBox(context);
|
||||||
|
_widthConverter = [[RNSVGPercentageConverter alloc] initWithRelativeAndOffset:CGRectGetWidth(_boundingBox) offset:0];
|
||||||
|
_heightConverter = [[RNSVGPercentageConverter alloc] initWithRelativeAndOffset:CGRectGetHeight(_boundingBox) offset:0];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (CGFloat)getWidthRelatedValue:(NSString *)string
|
||||||
|
{
|
||||||
|
return [_widthConverter stringToFloat:string];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (CGFloat)getHeightRelatedValue:(NSString *)string
|
||||||
|
{
|
||||||
|
return [_heightConverter stringToFloat:string];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (CGFloat)getContextWidth
|
||||||
|
{
|
||||||
|
return CGRectGetWidth(_boundingBox);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (CGFloat)getContextHeight
|
||||||
|
{
|
||||||
|
return CGRectGetHeight(_boundingBox);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (CGFloat)getContextX
|
||||||
|
{
|
||||||
|
return CGRectGetMinX(_boundingBox);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (CGFloat)getContextY
|
||||||
|
{
|
||||||
|
return CGRectGetMinY(_boundingBox);
|
||||||
|
}
|
||||||
|
|
||||||
- (void)mergeProperties:(__kindof RNSVGNode *)target mergeList:(NSArray<NSString *> *)mergeList
|
- (void)mergeProperties:(__kindof RNSVGNode *)target mergeList:(NSArray<NSString *> *)mergeList
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -150,15 +194,15 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!inherited) {
|
if (!inherited) {
|
||||||
originProperties = [[NSMutableDictionary alloc] init];
|
_originProperties = [[NSMutableDictionary alloc] init];
|
||||||
changedList = mergeList;
|
_changedList = mergeList;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (NSString *key in mergeList) {
|
for (NSString *key in mergeList) {
|
||||||
if (inherited) {
|
if (inherited) {
|
||||||
[self inheritProperty:target propName:key];
|
[self inheritProperty:target propName:key];
|
||||||
} else {
|
} else {
|
||||||
[originProperties setValue:[self valueForKey:key] forKey:key];
|
[_originProperties setValue:[self valueForKey:key] forKey:key];
|
||||||
[self setValue:[target valueForKey:key] forKey:key];
|
[self setValue:[target valueForKey:key] forKey:key];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -166,13 +210,13 @@
|
|||||||
|
|
||||||
- (void)resetProperties
|
- (void)resetProperties
|
||||||
{
|
{
|
||||||
if (changedList) {
|
if (_changedList) {
|
||||||
for (NSString *key in changedList) {
|
for (NSString *key in _changedList) {
|
||||||
[self setValue:[originProperties valueForKey:key] forKey:key];
|
[self setValue:[_originProperties valueForKey:key] forKey:key];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
[super resetProperties];
|
[super resetProperties];
|
||||||
changedList = nil;
|
_changedList = nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)inheritProperty:(__kindof RNSVGNode *)parent propName:(NSString *)propName
|
- (void)inheritProperty:(__kindof RNSVGNode *)parent propName:(NSString *)propName
|
||||||
|
|||||||
21
ios/RNSVGViewBox.h
Normal file
21
ios/RNSVGViewBox.h
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2015-present, Horcrux.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT-style license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#import "RNSVGGroup.h"
|
||||||
|
#import "RNSVGVBMOS.h"
|
||||||
|
|
||||||
|
@interface RNSVGViewBox : RNSVGGroup
|
||||||
|
|
||||||
|
@property (nonatomic, strong) NSString *minX;
|
||||||
|
@property (nonatomic, strong) NSString *minY;
|
||||||
|
@property (nonatomic, strong) NSString *vbWidth;
|
||||||
|
@property (nonatomic, strong) NSString *vbHeight;
|
||||||
|
@property (nonatomic, strong) NSString *align;
|
||||||
|
@property (nonatomic, assign) RNSVGVBMOS meetOrSlice;
|
||||||
|
|
||||||
|
@end
|
||||||
102
ios/RNSVGViewBox.m
Normal file
102
ios/RNSVGViewBox.m
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2015-present, Horcrux.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT-style license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#import <math.h>
|
||||||
|
#import "RNSVGViewBox.h"
|
||||||
|
|
||||||
|
@implementation RNSVGViewBox
|
||||||
|
|
||||||
|
- (void)renderTo:(CGContextRef)context
|
||||||
|
{
|
||||||
|
// based on https://svgwg.org/svg2-draft/coords.html#ComputingAViewportsTransform
|
||||||
|
[self setBoundingBox:context];
|
||||||
|
|
||||||
|
// Let vb-x, vb-y, vb-width, vb-height be the min-x, min-y, width and height values of the viewBox attribute respectively.
|
||||||
|
CGFloat vbX = [self getWidthRelatedValue:self.minX];
|
||||||
|
CGFloat vbY = [self getHeightRelatedValue:self.minY];
|
||||||
|
CGFloat vbWidth = [self getWidthRelatedValue:self.vbWidth];
|
||||||
|
CGFloat vbHeight = [self getHeightRelatedValue:self.vbHeight];
|
||||||
|
|
||||||
|
// Let e-x, e-y, e-width, e-height be the position and size of the element respectively.
|
||||||
|
CGFloat eX = [self getContextX];
|
||||||
|
CGFloat eY = [self getContextY];
|
||||||
|
CGFloat eWidth = [self getContextWidth];
|
||||||
|
CGFloat eHeight = [self getContextHeight];
|
||||||
|
|
||||||
|
// Let align be the align value of preserveAspectRatio, or 'xMidyMid' if preserveAspectRatio is not defined.
|
||||||
|
NSString *align = self.align;
|
||||||
|
|
||||||
|
// Let meetOrSlice be the meetOrSlice value of preserveAspectRatio, or 'meet' if preserveAspectRatio is not defined or if meetOrSlice is missing from this value.
|
||||||
|
RNSVGVBMOS meetOrSlice = self.meetOrSlice;
|
||||||
|
|
||||||
|
// Initialize scale-x to e-width/vb-width.
|
||||||
|
CGFloat scaleX = eWidth / vbWidth;
|
||||||
|
|
||||||
|
// Initialize scale-y to e-height/vb-height.
|
||||||
|
CGFloat scaleY = eHeight / vbHeight;
|
||||||
|
|
||||||
|
|
||||||
|
// Initialize translate-x to vb-x - e-x.
|
||||||
|
// Initialize translate-y to vb-y - e-y.
|
||||||
|
CGFloat translateX = vbX - eX;
|
||||||
|
CGFloat translateY = vbY - eY;
|
||||||
|
|
||||||
|
// If align is 'none'
|
||||||
|
if (meetOrSlice == kRNSVGVBMOSNone) {
|
||||||
|
// Let scale be set the smaller value of scale-x and scale-y.
|
||||||
|
// Assign scale-x and scale-y to scale.
|
||||||
|
CGFloat scale = scaleX = scaleY = fmin(scaleX, scaleY);
|
||||||
|
|
||||||
|
// If scale is greater than 1
|
||||||
|
if (scale > 1) {
|
||||||
|
// Minus translateX by (eWidth / scale - vbWidth) / 2
|
||||||
|
// Minus translateY by (eHeight / scale - vbHeight) / 2
|
||||||
|
translateX -= (eWidth / scale - vbWidth) / 2;
|
||||||
|
translateY -= (eHeight / scale - vbHeight) / 2;
|
||||||
|
} else {
|
||||||
|
translateX -= (eWidth - vbWidth * scale) / 2;
|
||||||
|
translateY -= (eHeight - vbHeight * scale) / 2;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// If align is not 'none' and meetOrSlice is 'meet', set the larger of scale-x and scale-y to the smaller.
|
||||||
|
// Otherwise, if align is not 'none' and meetOrSlice is 'slice', set the smaller of scale-x and scale-y to the larger.
|
||||||
|
if (![align isEqualToString: @"none"] && meetOrSlice == kRNSVGVBMOSMeet) {
|
||||||
|
scaleX = scaleY = fmin(scaleX, scaleY);
|
||||||
|
} else if (![align isEqualToString: @"none"] && meetOrSlice == kRNSVGVBMOSSlice) {
|
||||||
|
scaleX = scaleY = fmax(scaleX, scaleY);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If align contains 'xMid', minus (e-width / scale-x - vb-width) / 2 from transform-x.
|
||||||
|
if ([align containsString:@"xMid"]) {
|
||||||
|
translateX -= (eWidth / scaleX - vbWidth) / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If align contains 'xMax', minus (e-width / scale-x - vb-width) from transform-x.
|
||||||
|
if ([align containsString:@"xMax"]) {
|
||||||
|
translateX -= eWidth / scaleX - vbWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If align contains 'yMid', minus (e-height / scale-y - vb-height) / 2 from transform-y.
|
||||||
|
if ([align containsString:@"YMid"]) {
|
||||||
|
translateY -= (eHeight / scaleY - vbHeight) / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If align contains 'yMax', minus (e-height / scale-y - vb-height) from transform-y.
|
||||||
|
if ([align containsString:@"YMax"]) {
|
||||||
|
translateY -= eHeight / scaleY - vbHeight;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CGAffineTransform transform = CGAffineTransformMakeScale(scaleX, scaleY);
|
||||||
|
transform = CGAffineTransformTranslate(transform, -translateX, -translateY);
|
||||||
|
|
||||||
|
CGContextConcatCTM(context, transform);
|
||||||
|
[super renderTo:context];
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
@@ -46,22 +46,18 @@
|
|||||||
|
|
||||||
- (CGPathRef)getPath:(CGContextRef)context
|
- (CGPathRef)getPath:(CGContextRef)context
|
||||||
{
|
{
|
||||||
|
[self setBoundingBox:context];
|
||||||
CGMutablePathRef path = CGPathCreateMutable();
|
CGMutablePathRef path = CGPathCreateMutable();
|
||||||
CGRect box = CGContextGetClipBoundingBox(context);
|
|
||||||
float height = CGRectGetHeight(box);
|
|
||||||
float width = CGRectGetWidth(box);
|
|
||||||
|
|
||||||
RNSVGPercentageConverter* convert = [[RNSVGPercentageConverter alloc] init];
|
RNSVGPercentageConverter* convert = [[RNSVGPercentageConverter alloc] init];
|
||||||
CGFloat cx = [convert stringToFloat:self.cx relative:width offset:0];
|
CGFloat cx = [self getWidthRelatedValue:self.cx];
|
||||||
CGFloat cy = [convert stringToFloat:self.cy relative:height offset:0];
|
CGFloat cy = [self getHeightRelatedValue:self.cy];
|
||||||
CGFloat r;
|
CGFloat r;
|
||||||
|
|
||||||
// radius percentage calculate formula:
|
// radius percentage calculate formula:
|
||||||
// radius = sqrt(pow((width*percent), 2) + pow((height*percent), 2)) / sqrt(2)
|
// radius = sqrt(pow((width*percent), 2) + pow((height*percent), 2)) / sqrt(2)
|
||||||
|
|
||||||
if ([convert isPercentage:self.r]) {
|
if ([convert isPercentage:self.r]) {
|
||||||
CGFloat radiusPercent = [convert percentageToFloat:self.r relative:1 offset:0];
|
CGFloat radiusPercent = [convert percentageToFloat:self.r relative:1 offset:0];
|
||||||
r = sqrt(pow((width * radiusPercent), 2) + pow((height * radiusPercent), 2)) / sqrt(2);
|
r = sqrt(pow(([self getContextWidth] * radiusPercent), 2) + pow(([self getContextHeight] * radiusPercent), 2)) / sqrt(2);
|
||||||
} else {
|
} else {
|
||||||
r = [self.r floatValue];
|
r = [self.r floatValue];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -55,17 +55,12 @@
|
|||||||
|
|
||||||
- (CGPathRef)getPath:(CGContextRef)context
|
- (CGPathRef)getPath:(CGContextRef)context
|
||||||
{
|
{
|
||||||
|
[self setBoundingBox:context];
|
||||||
CGMutablePathRef path = CGPathCreateMutable();
|
CGMutablePathRef path = CGPathCreateMutable();
|
||||||
CGRect box = CGContextGetClipBoundingBox(context);
|
CGFloat cx = [self getWidthRelatedValue:self.cx];
|
||||||
float height = CGRectGetHeight(box);
|
CGFloat cy = [self getHeightRelatedValue:self.cy];
|
||||||
float width = CGRectGetWidth(box);
|
CGFloat rx = [self getWidthRelatedValue:self.rx];
|
||||||
|
CGFloat ry = [self getHeightRelatedValue:self.ry];
|
||||||
RNSVGPercentageConverter* convert = [[RNSVGPercentageConverter alloc] init];
|
|
||||||
CGFloat cx = [convert stringToFloat:self.cx relative:width offset:0];
|
|
||||||
CGFloat cy = [convert stringToFloat:self.cy relative:height offset:0];
|
|
||||||
CGFloat rx = [convert stringToFloat:self.rx relative:width offset:0];
|
|
||||||
CGFloat ry = [convert stringToFloat:self.ry relative:height offset:0];
|
|
||||||
CGPathAddEllipseInRect(path, nil, CGRectMake(cx - rx, cy - ry, rx * 2, ry * 2));
|
CGPathAddEllipseInRect(path, nil, CGRectMake(cx - rx, cy - ry, rx * 2, ry * 2));
|
||||||
return (CGPathRef)CFAutorelease(path);
|
return (CGPathRef)CFAutorelease(path);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -55,17 +55,12 @@
|
|||||||
|
|
||||||
- (CGPathRef)getPath:(CGContextRef)context
|
- (CGPathRef)getPath:(CGContextRef)context
|
||||||
{
|
{
|
||||||
|
[self setBoundingBox:context];
|
||||||
CGMutablePathRef path = CGPathCreateMutable();
|
CGMutablePathRef path = CGPathCreateMutable();
|
||||||
CGRect box = CGContextGetClipBoundingBox(context);
|
CGFloat x1 = [self getWidthRelatedValue:self.x1];
|
||||||
float height = CGRectGetHeight(box);
|
CGFloat y1 = [self getHeightRelatedValue:self.y1];
|
||||||
float width = CGRectGetWidth(box);
|
CGFloat x2 = [self getWidthRelatedValue:self.x2];
|
||||||
|
CGFloat y2 = [self getHeightRelatedValue:self.y2];
|
||||||
RNSVGPercentageConverter* convert = [[RNSVGPercentageConverter alloc] init];
|
|
||||||
CGFloat x1 = [convert stringToFloat:self.x1 relative:width offset:0];
|
|
||||||
CGFloat y1 = [convert stringToFloat:self.y1 relative:height offset:0];
|
|
||||||
CGFloat x2 = [convert stringToFloat:self.x2 relative:width offset:0];
|
|
||||||
CGFloat y2 = [convert stringToFloat:self.y2 relative:height offset:0];
|
|
||||||
CGPathMoveToPoint(path, nil, x1, y1);
|
CGPathMoveToPoint(path, nil, x1, y1);
|
||||||
CGPathAddLineToPoint(path, nil, x2, y2);
|
CGPathAddLineToPoint(path, nil, x2, y2);
|
||||||
|
|
||||||
|
|||||||
@@ -73,21 +73,14 @@
|
|||||||
|
|
||||||
- (CGPathRef)getPath:(CGContextRef)context
|
- (CGPathRef)getPath:(CGContextRef)context
|
||||||
{
|
{
|
||||||
|
[self setBoundingBox:context];
|
||||||
CGMutablePathRef path = CGPathCreateMutable();
|
CGMutablePathRef path = CGPathCreateMutable();
|
||||||
|
CGFloat x = [self getWidthRelatedValue:self.x];
|
||||||
CGRect box = CGContextGetClipBoundingBox(context);
|
CGFloat y = [self getHeightRelatedValue:self.y];
|
||||||
float height = CGRectGetHeight(box);
|
CGFloat width = [self getWidthRelatedValue:self.width];
|
||||||
float width = CGRectGetWidth(box);
|
CGFloat height = [self getHeightRelatedValue:self.height];
|
||||||
|
CGFloat rx = [self getWidthRelatedValue:self.rx];
|
||||||
RNSVGPercentageConverter* convert = [[RNSVGPercentageConverter alloc] init];
|
CGFloat ry = [self getHeightRelatedValue:self.ry];
|
||||||
CGFloat x = [convert stringToFloat:self.x relative:width offset:0];
|
|
||||||
CGFloat y = [convert stringToFloat:self.y relative:height offset:0];
|
|
||||||
CGFloat w = [convert stringToFloat:self.width relative:width offset:0];
|
|
||||||
CGFloat h = [convert stringToFloat:self.height relative:height offset:0];
|
|
||||||
CGFloat rx = [convert stringToFloat:self.rx relative:width offset:0];
|
|
||||||
CGFloat ry = [convert stringToFloat:self.ry relative:height offset:0];
|
|
||||||
|
|
||||||
|
|
||||||
if (rx != 0 || ry != 0) {
|
if (rx != 0 || ry != 0) {
|
||||||
if (rx == 0) {
|
if (rx == 0) {
|
||||||
@@ -96,17 +89,17 @@
|
|||||||
ry = rx;
|
ry = rx;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rx > w / 2) {
|
if (rx > width / 2) {
|
||||||
rx = w / 2;
|
rx = width / 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ry > h / 2) {
|
if (ry > height / 2) {
|
||||||
ry = h / 2;
|
ry = height / 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
CGPathAddRoundedRect(path, nil, CGRectMake(x, y, w, h), rx, ry);
|
CGPathAddRoundedRect(path, nil, CGRectMake(x, y, width, height), rx, ry);
|
||||||
} else {
|
} else {
|
||||||
CGPathAddRect(path, nil, CGRectMake(x, y, w, h));
|
CGPathAddRect(path, nil, CGRectMake(x, y, width, height));
|
||||||
}
|
}
|
||||||
|
|
||||||
return (CGPathRef)CFAutorelease(path);
|
return (CGPathRef)CFAutorelease(path);
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* based on
|
* based on CurvyText by iosptl: https://github.com/iosptl/ios7ptl/blob/master/ch21-Text/CurvyText/CurvyText/CurvyTextView.m
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#import "RNSVGBezierPath.h"
|
#import "RNSVGBezierPath.h"
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
#import "RNSVGSolidColorBrush.h"
|
#import "RNSVGSolidColorBrush.h"
|
||||||
#import "RCTLog.h"
|
#import "RCTLog.h"
|
||||||
#import "RNSVGCGFCRule.h"
|
#import "RNSVGCGFCRule.h"
|
||||||
|
#import "RNSVGVBMOS.h"
|
||||||
|
|
||||||
@implementation RCTConvert (RNSVG)
|
@implementation RCTConvert (RNSVG)
|
||||||
|
|
||||||
@@ -73,6 +74,13 @@ RCT_ENUM_CONVERTER(RNSVGCGFCRule, (@{
|
|||||||
@"nonzero": @(kRNSVGCGFCRuleNonzero),
|
@"nonzero": @(kRNSVGCGFCRuleNonzero),
|
||||||
}), kRNSVGCGFCRuleNonzero, intValue)
|
}), kRNSVGCGFCRuleNonzero, intValue)
|
||||||
|
|
||||||
|
RCT_ENUM_CONVERTER(RNSVGVBMOS, (@{
|
||||||
|
@"meet": @(kRNSVGVBMOSMeet),
|
||||||
|
@"slice": @(kRNSVGVBMOSSlice),
|
||||||
|
@"none": @(kRNSVGVBMOSNone)
|
||||||
|
}), kRNSVGVBMOSMeet, intValue)
|
||||||
|
|
||||||
|
|
||||||
// This takes a tuple of text lines and a font to generate a CTLine for each text line.
|
// This takes a tuple of text lines and a font to generate a CTLine for each text line.
|
||||||
// This prepares everything for rendering a frame of text in RNSVGText.
|
// This prepares everything for rendering a frame of text in RNSVGText.
|
||||||
+ (RNSVGTextFrame)RNSVGTextFrame:(id)json
|
+ (RNSVGTextFrame)RNSVGTextFrame:(id)json
|
||||||
|
|||||||
@@ -7,14 +7,21 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#import <Foundation/Foundation.h>
|
#import <Foundation/Foundation.h>
|
||||||
|
#import <QuartzCore/QuartzCore.h>
|
||||||
|
|
||||||
@interface RNSVGPercentageConverter : NSObject
|
@interface RNSVGPercentageConverter : NSObject
|
||||||
|
|
||||||
- (NSRegularExpression *) getPercentageRegularExpression;
|
- (NSRegularExpression *) getPercentageRegularExpression;
|
||||||
|
|
||||||
- (float) percentageToFloat:(NSString *)percentage relative:(float)relative offset:(float)offset;
|
- (instancetype) initWithRelativeAndOffset:(CGFloat)relative offset:(CGFloat)offset;
|
||||||
|
|
||||||
- (float) stringToFloat:(NSString *)string relative:(float)relative offset:(float)offset;
|
- (CGFloat) percentageToFloat:(NSString *)percentage relative:(CGFloat)relative offset:(CGFloat)offset;
|
||||||
|
|
||||||
|
- (CGFloat) percentageToFloat:(NSString *)percentage;
|
||||||
|
|
||||||
|
- (CGFloat) stringToFloat:(NSString *)string relative:(CGFloat)relative offset:(CGFloat)offset;
|
||||||
|
|
||||||
|
- (CGFloat) stringToFloat:(NSString *)string;
|
||||||
|
|
||||||
- (BOOL) isPercentage:(NSString *) string;
|
- (BOOL) isPercentage:(NSString *) string;
|
||||||
|
|
||||||
|
|||||||
@@ -10,13 +10,24 @@
|
|||||||
|
|
||||||
@implementation RNSVGPercentageConverter
|
@implementation RNSVGPercentageConverter
|
||||||
{
|
{
|
||||||
|
CGFloat _relative;
|
||||||
|
CGFloat _offset;
|
||||||
NSRegularExpression *percentageRegularExpression;
|
NSRegularExpression *percentageRegularExpression;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (instancetype) initWithRelativeAndOffset:(CGFloat)relative offset:(CGFloat)offset
|
||||||
|
{
|
||||||
|
if (self = [super init]) {
|
||||||
|
_relative = relative;
|
||||||
|
_offset = offset;
|
||||||
|
percentageRegularExpression = [[NSRegularExpression alloc] initWithPattern:@"^(\\-?\\d+(?:\\.\\d+)?)%$" options:0 error:nil];
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
- (id)init
|
- (id)init
|
||||||
{
|
{
|
||||||
self = [super init];
|
if (self = [super init]) {
|
||||||
if (self) {
|
|
||||||
percentageRegularExpression = [[NSRegularExpression alloc] initWithPattern:@"^(\\-?\\d+(?:\\.\\d+)?)%$" options:0 error:nil];
|
percentageRegularExpression = [[NSRegularExpression alloc] initWithPattern:@"^(\\-?\\d+(?:\\.\\d+)?)%$" options:0 error:nil];
|
||||||
}
|
}
|
||||||
return self;
|
return self;
|
||||||
@@ -27,20 +38,29 @@
|
|||||||
return percentageRegularExpression;
|
return percentageRegularExpression;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (float) stringToFloat:(NSString *)percentage relative:(float)relative offset:(float)offset
|
- (CGFloat) stringToFloat:(NSString *)string
|
||||||
{
|
{
|
||||||
if ([self isPercentage:percentage] == NO) {
|
return [self stringToFloat:string relative:_relative offset:_offset];
|
||||||
return [percentage floatValue];
|
}
|
||||||
|
|
||||||
|
- (CGFloat) stringToFloat:(NSString *)string relative:(CGFloat)relative offset:(CGFloat)offset
|
||||||
|
{
|
||||||
|
if ([self isPercentage:string] == NO) {
|
||||||
|
return [string floatValue];
|
||||||
} else {
|
} else {
|
||||||
return [self percentageToFloat:percentage relative:relative offset:offset];
|
return [self percentageToFloat:string relative:relative offset:offset];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (float) percentageToFloat:(NSString *)percentage relative:(float)relative offset:(float)offset
|
- (CGFloat) percentageToFloat:(NSString *)percentage
|
||||||
{
|
{
|
||||||
|
return [self percentageToFloat:percentage relative:_relative offset:_offset];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (CGFloat) percentageToFloat:(NSString *)percentage relative:(CGFloat)relative offset:(CGFloat)offset
|
||||||
|
{
|
||||||
|
__block CGFloat matched;
|
||||||
|
|
||||||
__block float matched;
|
|
||||||
[percentageRegularExpression enumerateMatchesInString:percentage
|
[percentageRegularExpression enumerateMatchesInString:percentage
|
||||||
options:0
|
options:0
|
||||||
range:NSMakeRange(0, percentage.length)
|
range:NSMakeRange(0, percentage.length)
|
||||||
|
|||||||
13
ios/Utils/RNSVGVBMOS.h
Normal file
13
ios/Utils/RNSVGVBMOS.h
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2015-present, Horcrux.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT-style license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef CF_ENUM(int32_t, RNSVGVBMOS) {
|
||||||
|
kRNSVGVBMOSMeet,
|
||||||
|
kRNSVGVBMOSSlice,
|
||||||
|
kRNSVGVBMOSNone
|
||||||
|
};
|
||||||
13
ios/ViewManagers/RNSVGViewBoxManager.h
Normal file
13
ios/ViewManagers/RNSVGViewBoxManager.h
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2015-present, Horcrux.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT-style license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#import "RNSVGGroupManager.h"
|
||||||
|
|
||||||
|
@interface RNSVGViewBoxManager : RNSVGGroupManager
|
||||||
|
|
||||||
|
@end
|
||||||
29
ios/ViewManagers/RNSVGViewBoxManager.m
Normal file
29
ios/ViewManagers/RNSVGViewBoxManager.m
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2015-present, Horcrux.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT-style license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#import "RNSVGViewBoxManager.h"
|
||||||
|
#import "RNSVGViewBox.h"
|
||||||
|
#import "RNSVGVBMOS.h"
|
||||||
|
|
||||||
|
@implementation RNSVGViewBoxManager
|
||||||
|
|
||||||
|
RCT_EXPORT_MODULE()
|
||||||
|
|
||||||
|
- (RNSVGViewBox *)node
|
||||||
|
{
|
||||||
|
return [RNSVGViewBox new];
|
||||||
|
}
|
||||||
|
|
||||||
|
RCT_EXPORT_VIEW_PROPERTY(minX, NSString)
|
||||||
|
RCT_EXPORT_VIEW_PROPERTY(minY, NSString)
|
||||||
|
RCT_EXPORT_VIEW_PROPERTY(vbWidth, NSString)
|
||||||
|
RCT_EXPORT_VIEW_PROPERTY(vbHeight, NSString)
|
||||||
|
RCT_EXPORT_VIEW_PROPERTY(align, NSString)
|
||||||
|
RCT_EXPORT_VIEW_PROPERTY(meetOrSlice, RNSVGVBMOS)
|
||||||
|
|
||||||
|
@end
|
||||||
@@ -41,6 +41,15 @@ function fontAndLinesDiffer(a, b) {
|
|||||||
return arrayDiffer(a.lines, b.lines);
|
return arrayDiffer(a.lines, b.lines);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const ViewBoxAttributes = {
|
||||||
|
minX: true,
|
||||||
|
minY: true,
|
||||||
|
vbWidth: true,
|
||||||
|
vbHeight: true,
|
||||||
|
align: true,
|
||||||
|
meetOrSlice: true
|
||||||
|
};
|
||||||
|
|
||||||
const NodeAttributes = {
|
const NodeAttributes = {
|
||||||
name: true,
|
name: true,
|
||||||
transform: {
|
transform: {
|
||||||
@@ -180,5 +189,6 @@ export {
|
|||||||
UseAttributes,
|
UseAttributes,
|
||||||
RenderableOnlyAttributes,
|
RenderableOnlyAttributes,
|
||||||
LinearGradientAttributes,
|
LinearGradientAttributes,
|
||||||
RadialGradientAttributes
|
RadialGradientAttributes,
|
||||||
|
ViewBoxAttributes
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import SerializablePath from 'react-native/Libraries/ART/ARTSerializablePath';
|
import SerializablePath from '../SerializablePath';
|
||||||
import clipReg from './patternReg';
|
import clipReg from './patternReg';
|
||||||
|
|
||||||
const clipRules = {
|
const clipRules = {
|
||||||
|
|||||||
@@ -1,71 +0,0 @@
|
|||||||
export default function({viewbox, width, height, preserveAspectRatio, x: dx, y: dy, dScale, dScaleX, dScaleY}) {
|
|
||||||
if (!viewbox || !width || !height) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof viewbox === 'string') {
|
|
||||||
let parts = viewbox.trim().split(/\s+/);
|
|
||||||
let vw = +parts[2];
|
|
||||||
let vh = +parts[3];
|
|
||||||
|
|
||||||
// width or height can`t be negative
|
|
||||||
if (vw < 0 || vh < 0 || parts.length !== 4) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// width or height equals zero disable render
|
|
||||||
if (!vw || !vh) {
|
|
||||||
return {
|
|
||||||
x: 0,
|
|
||||||
y: 0,
|
|
||||||
scaleX: 0,
|
|
||||||
scaleY: 0
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
let vx = +parts[0] || 0;
|
|
||||||
let vy = +parts[1] || 0;
|
|
||||||
let preserve = preserveAspectRatio !== 'none';
|
|
||||||
let scaleX = 1;
|
|
||||||
let scaleY = 1;
|
|
||||||
let x = 0;
|
|
||||||
let y = 0;
|
|
||||||
let sx = width / vw;
|
|
||||||
let sy = height / vh;
|
|
||||||
if (preserve) {
|
|
||||||
scaleX = scaleY = Math.min(sx, sy);
|
|
||||||
x = width / 2 - Math.min(vw, vh) * scaleX / 2 - vx * scaleX;
|
|
||||||
y = 0 - vy * scaleX;
|
|
||||||
|
|
||||||
if (sx < sy) {
|
|
||||||
[x, y] = [y, x];
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
scaleX = sx;
|
|
||||||
scaleY = sy;
|
|
||||||
x = -vx * sx;
|
|
||||||
y = -vy * sy;
|
|
||||||
}
|
|
||||||
|
|
||||||
//if (shouldTransform) {
|
|
||||||
x += (+dx || 0);
|
|
||||||
y += (+dy || 0);
|
|
||||||
|
|
||||||
if (dScale) {
|
|
||||||
scaleX *= (+dScale || 1);
|
|
||||||
scaleY *= (+dScale || 1);
|
|
||||||
} else {
|
|
||||||
scaleX *= (+dScaleX || 1);
|
|
||||||
scaleY *= (+dScaleY || 1);
|
|
||||||
}
|
|
||||||
//}
|
|
||||||
|
|
||||||
return {
|
|
||||||
x,
|
|
||||||
y,
|
|
||||||
scaleX,
|
|
||||||
scaleY
|
|
||||||
};
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user