add support for text clipping and support for text fill pattern

This commit is contained in:
Horcrux
2016-04-22 22:21:44 +08:00
parent 74b5e82781
commit 2eda0e8ce2
4 changed files with 97 additions and 35 deletions

View File

@@ -138,6 +138,39 @@ class ClipPathElement extends Component{
} }
} }
class TextClipping extends Component{
static title = 'Transform the text';
render() {
return <Svg
height="60"
width="200"
>
<Defs>
<ClipPath id="clip">
<Circle cx="-60" cy="15" r="10"/>
<Circle cx="-40" cy="15" r="10"/>
<Circle cx="-20" cy="15" r="10"/>
<Circle cx="0" cy="15" r="10"/>
<Circle cx="20" cy="15" r="10"/>
<Circle cx="40" cy="15" r="10"/>
<Circle cx="60" cy="15" r="10"/>
</ClipPath>
</Defs>
<Text
x="100"
y="30"
fill="red"
fontSize="22"
fontWeight="bold"
fill="red"
stroke="blue"
textAnchor="center"
clipPath="url(#clip)"
>NOT THE FACE</Text>
</Svg>;
}
}
const icon = <Svg const icon = <Svg
height="20" height="20"
width="20" width="20"
@@ -180,7 +213,7 @@ const icon = <Svg
</G> </G>
</Svg>; </Svg>;
const samples = [ClipPathAttr, ClipRule, ClipPathElement]; const samples = [ClipPathAttr, ClipRule, ClipPathElement, TextClipping];
export { export {
icon, icon,

View File

@@ -9,7 +9,9 @@ import Svg, {
Defs, Defs,
Stop, Stop,
RadialGradient, RadialGradient,
Polyline Polyline,
ClipPath,
Circle
} from 'react-native-svg'; } from 'react-native-svg';
class StrokeExample extends Component{ class StrokeExample extends Component{
@@ -25,34 +27,21 @@ class StrokeExample extends Component{
} }
} }
class StrokeWidth extends Component{
static title = 'The stroke property defines the color of a line, text or outline of an element';
render() {
return <Svg height="80" width="225">
<G fill="none" stroke="black">
<Path strokeWidth="2" d="M5 20 l215 0" />
<Path strokeWidth="4" d="M5 40 l215 0" />
<Path strokeWidth="6" d="M5 60 l215 0" />
</G>
</Svg>;
}
}
class StrokeLinecap extends Component{ class StrokeLinecap extends Component{
static title = 'The stroke-linecap property defines different types of endings to an open path'; static title = 'The stroke-linecap property defines different types of endings to an open path';
render() { render() {
return <Svg height="80" width="225"> return <Svg height="80" width="225">
<G fill="none" stroke="black" strokeWidth="6"> <G fill="none" stroke="black">
<Path strokeLinecap="butt" d="M5 20 l215 0" /> <Path strokeLinecap="butt" strokeWidth="2" d="M5 20 l215 0" />
<Path strokeLinecap="round" d="M5 40 l215 0" /> <Path strokeLinecap="round" strokeWidth="4" d="M5 40 l215 0" />
<Path strokeLinecap="square" d="M5 60 l215 0" /> <Path strokeLinecap="square" strokeWidth="6" d="M5 60 l215 0" />
</G> </G>
</Svg>; </Svg>;
} }
} }
class StrokeDasharray extends Component{ class StrokeDasharray extends Component{
static title = 'The stroke-linecap property defines different types of endings to an open path'; static title = 'strokeDasharray';
render() { render() {
return <Svg height="80" width="225"> return <Svg height="80" width="225">
<G fill="none" stroke="black" strokeWidth="4"> <G fill="none" stroke="black" strokeWidth="4">
@@ -65,7 +54,7 @@ class StrokeDasharray extends Component{
} }
class StrokePattern extends Component{ class StrokePattern extends Component{
static title = 'Stroke with gradient.'; static title = 'Advanced stroke example.';
render() { render() {
return <Svg height="80" width="200"> return <Svg height="80" width="200">
<Defs> <Defs>
@@ -81,6 +70,9 @@ class StrokePattern extends Component{
stopOpacity="1" stopOpacity="1"
/> />
</RadialGradient> </RadialGradient>
<ClipPath id="clip">
<Circle r="96" cx="100" cy="40" />
</ClipPath>
</Defs> </Defs>
<Rect <Rect
x="5" x="5"
@@ -91,6 +83,7 @@ class StrokePattern extends Component{
stroke="url(#grad)" stroke="url(#grad)"
strokeWidth="5" strokeWidth="5"
strokeDasharray="10" strokeDasharray="10"
clipPath="url(#clip)"
/> />
<Polyline <Polyline
@@ -117,7 +110,7 @@ const icon = <Svg
</G> </G>
</Svg>; </Svg>;
const samples = [StrokeExample, StrokeWidth, StrokeLinecap, StrokeDasharray, StrokePattern]; const samples = [StrokeExample, StrokeLinecap, StrokeDasharray, StrokePattern];
export { export {
icon, icon,

View File

@@ -3,7 +3,11 @@ import React, {
} from 'react-native'; } from 'react-native';
import Svg, { import Svg, {
Text Text,
LinearGradient,
Stop,
Defs,
ClipPath
} from 'react-native-svg'; } from 'react-native-svg';
class TextExample extends Component{ class TextExample extends Component{
@@ -55,6 +59,34 @@ class TextRotate extends Component{
} }
} }
class TextFill extends Component{
static title = 'Fill the text with LinearGradient';
render() {
return <Svg
height="60"
width="200"
>
<Defs>
<LinearGradient id="grad" x1="0" y1="0" x2="200" y2="0">
<Stop offset="0%" stopColor="rgb(255,255,0)" stopOpacity="0" />
<Stop offset="100%" stopColor="red" stopOpacity="1" />
</LinearGradient>
</Defs>
<Text
fill="url(#grad)"
stroke="purple"
fontSize="20"
fontWeight="bold"
x="100"
y="20"
textAnchor="center"
>FILL TEXT</Text>
</Svg>;
}
}
// TODO: not supported
class TextStroke extends Component{ class TextStroke extends Component{
static title = 'Stroke the text'; static title = 'Stroke the text';
render() { render() {
@@ -62,21 +94,28 @@ class TextStroke extends Component{
height="60" height="60"
width="200" width="200"
> >
<Defs>
<LinearGradient id="grad" x1="0" y1="0" x2="100" y2="0">
<Stop offset="100%" stopColor="rgb(255,255,0)" stopOpacity="0" />
<Stop offset="0%" stopColor="red" stopOpacity="1" />
</LinearGradient>
</Defs>
<Text <Text
stroke="url(#grad)"
strokeWidth="4"
fill="none" fill="none"
stroke="purple"
fontSize="20" fontSize="20"
fontWeight="bold" fontWeight="bold"
x="100" x="100"
y="20" y="20"
alignment="center" textAnchor="center"
>STROKED TEXT</Text> >STROKE TEXT</Text>
</Svg>; </Svg>;
} }
} }
// TODO: wait for official done
class TextPath extends Component{ class TextPath extends Component{
static title = 'Transform the text'; static title = 'Transform the text';
render() { render() {
@@ -112,7 +151,7 @@ const icon = <Svg
></Text> ></Text>
</Svg>; </Svg>;
const samples = [TextExample, TextRotate, TextStroke, TextPath]; const samples = [TextExample, TextRotate, TextFill, TextPath];
export { export {
icon, icon,

View File

@@ -53,14 +53,13 @@ static void RNSVGFreeTextFrame(RNSVGTextFrame frame)
} }
// to-do: draw along a path // to-do: draw along a path
// to-do: fill-rule
// to-do: clip
CGTextDrawingMode mode = kCGTextStroke; CGTextDrawingMode mode = kCGTextStroke;
if (self.fill) { if (self.fill) {
if ([self.fill applyFillColor:context]) { if ([self.fill applyFillColor:context]) {
mode = kCGTextFill; mode = kCGTextFill;
} else { } else {
[self clip: context];
for (int i = 0; i < frame.count; i++) { for (int i = 0; i < frame.count; i++) {
CGContextSaveGState(context); CGContextSaveGState(context);
// Inverse the coordinate space since CoreText assumes a bottom-up coordinate space // Inverse the coordinate space since CoreText assumes a bottom-up coordinate space
@@ -80,9 +79,7 @@ static void RNSVGFreeTextFrame(RNSVGTextFrame frame)
} }
} }
if (self.stroke) { if (self.stroke) {
if ([self.stroke applyStrokeColor:context] == NO) { [self.stroke applyStrokeColor:context];
[self.stroke paint:context];
}
CGContextSetLineWidth(context, self.strokeWidth); CGContextSetLineWidth(context, self.strokeWidth);
CGContextSetLineCap(context, self.strokeLinecap); CGContextSetLineCap(context, self.strokeLinecap);
@@ -97,7 +94,7 @@ static void RNSVGFreeTextFrame(RNSVGTextFrame frame)
} }
CGContextSetTextDrawingMode(context, mode); CGContextSetTextDrawingMode(context, mode);
[self clip:context];
// Inverse the coordinate space since CoreText assumes a bottom-up coordinate space // Inverse the coordinate space since CoreText assumes a bottom-up coordinate space
CGContextScaleCTM(context, 1.0, -1.0); CGContextScaleCTM(context, 1.0, -1.0);
for (int i = 0; i < frame.count; i++) { for (int i = 0; i < frame.count; i++) {