mirror of
https://github.com/zoriya/react-native-svg.git
synced 2025-12-19 21:45:10 +00:00
Add preserveAspectRatio prop for Image
Add preserveAspectRatio prop for Image. Fix touch events for Image on Android. Fix viewBox slice bug on Android.
This commit is contained in:
@@ -7,24 +7,48 @@ import Svg, {
|
||||
Defs,
|
||||
Circle,
|
||||
ClipPath,
|
||||
Rect,
|
||||
Text
|
||||
} from 'react-native-svg';
|
||||
|
||||
class ImageExample extends Component{
|
||||
static title = 'Image';
|
||||
static title = 'Draw Image with preserveAspectRatio prop';
|
||||
|
||||
render() {
|
||||
return <Svg
|
||||
height="100"
|
||||
width="100"
|
||||
style={{backgroundColor: 'red'}}
|
||||
>
|
||||
<Defs>
|
||||
<ClipPath id="clip">
|
||||
<Circle cx="50%" cy="50%" r="40%"/>
|
||||
</ClipPath>
|
||||
</Defs>
|
||||
<Rect
|
||||
x="5%"
|
||||
y="5%"
|
||||
width="50%"
|
||||
height="90%"
|
||||
/>
|
||||
<Image
|
||||
x="5%"
|
||||
y="5%"
|
||||
width="90%"
|
||||
width="50%"
|
||||
height="90%"
|
||||
preserveAspectRatio="xMidYMid slice"
|
||||
opacity="0.5"
|
||||
href={require('../image.jpg')}
|
||||
clipPath="url(#clip)"
|
||||
/>
|
||||
<Text
|
||||
x="50"
|
||||
y="50"
|
||||
textAnchor="middle"
|
||||
fontWeight="bold"
|
||||
fontSize="16"
|
||||
fill="blue"
|
||||
>HOGWARTS</Text>
|
||||
</Svg>;
|
||||
}
|
||||
}
|
||||
@@ -43,6 +67,7 @@ class ClipImage extends Component{
|
||||
</ClipPath>
|
||||
</Defs>
|
||||
<Image
|
||||
onPress={() => alert('press on Image')}
|
||||
x="5%"
|
||||
y="5%"
|
||||
width="90%"
|
||||
|
||||
@@ -579,7 +579,7 @@ npm install
|
||||
2. more Text features support (textPath, tref, tspan)
|
||||
3. Pattern element
|
||||
4. implement Animated elements
|
||||
5. more Image features support
|
||||
5. load Image from url
|
||||
|
||||
#### Thanks:
|
||||
|
||||
|
||||
@@ -12,10 +12,16 @@ package com.horcrux.svg;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Matrix;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Path;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
import android.graphics.Region;
|
||||
import android.net.Uri;
|
||||
import android.util.Log;
|
||||
|
||||
import com.facebook.common.executors.UiThreadImmediateExecutorService;
|
||||
import com.facebook.common.logging.FLog;
|
||||
import com.facebook.common.references.CloseableReference;
|
||||
@@ -45,6 +51,9 @@ public class RNSVGImageShadowNode extends RNSVGPathShadowNode {
|
||||
private String mW;
|
||||
private String mH;
|
||||
private Uri mUri;
|
||||
private float mImageRatio;
|
||||
private String mAlign;
|
||||
private int mMeetOrSlice;
|
||||
private AtomicBoolean mLoading = new AtomicBoolean(false);
|
||||
|
||||
@ReactProp(name = "x")
|
||||
@@ -81,12 +90,29 @@ public class RNSVGImageShadowNode extends RNSVGPathShadowNode {
|
||||
return;
|
||||
}
|
||||
|
||||
mImageRatio = (float)src.getInt("width") / (float)src.getInt("height");
|
||||
mUri = Uri.parse(uriString);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ReactProp(name = "align")
|
||||
public void setAlign(String align) {
|
||||
mAlign = align;
|
||||
markUpdated();
|
||||
}
|
||||
|
||||
@ReactProp(name = "meetOrSlice")
|
||||
public void setMeetOrSlice(int meetOrSlice) {
|
||||
mMeetOrSlice = meetOrSlice;
|
||||
markUpdated();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(final Canvas canvas, final Paint paint, final float opacity) {
|
||||
mPath = new Path();
|
||||
mPath.addRect(new RectF(getRect()), Path.Direction.CW);
|
||||
|
||||
if (!mLoading.get()) {
|
||||
final ImageRequest request = ImageRequestBuilder.newBuilderWithSource(mUri).build();
|
||||
|
||||
@@ -140,14 +166,70 @@ public class RNSVGImageShadowNode extends RNSVGPathShadowNode {
|
||||
|
||||
private void doRender(@Nonnull final Canvas canvas, @Nonnull final Paint paint, @Nonnull final Bitmap bitmap, final float opacity) {
|
||||
final int count = saveAndSetupCanvas(canvas);
|
||||
|
||||
clip(canvas, paint);
|
||||
canvas.concat(mMatrix);
|
||||
|
||||
Paint alphaPaint = new Paint();
|
||||
alphaPaint.setAlpha((int) (opacity * 255));
|
||||
|
||||
canvas.drawBitmap(bitmap, null, getRect(), alphaPaint);
|
||||
// apply viewBox transform on Image render.
|
||||
Rect rect = getRect();
|
||||
float rectWidth = (float)rect.width();
|
||||
float rectHeight = (float)rect.height();
|
||||
float rectX = (float)rect.left;
|
||||
float rectY = (float)rect.top;
|
||||
float rectRatio = rectWidth / rectHeight;
|
||||
RectF renderRect;
|
||||
|
||||
if (mImageRatio == rectRatio) {
|
||||
renderRect = new RectF(rect);
|
||||
} else if (mImageRatio < rectRatio) {
|
||||
renderRect = new RectF(0, 0, (int)(rectHeight * mImageRatio), (int)rectHeight);
|
||||
} else {
|
||||
renderRect = new RectF(0, 0, (int)rectWidth, (int)(rectWidth / mImageRatio));
|
||||
}
|
||||
|
||||
RNSVGViewBoxShadowNode viewBox = new RNSVGViewBoxShadowNode();
|
||||
viewBox.setMinX("0");
|
||||
viewBox.setMinY("0");
|
||||
viewBox.setVbWidth(renderRect.width() / mScale + "");
|
||||
viewBox.setVbHeight(renderRect.height() / mScale + "");
|
||||
viewBox.setWidth(rectWidth / mScale);
|
||||
viewBox.setHeight(rectHeight / mScale);
|
||||
viewBox.setAlign(mAlign);
|
||||
viewBox.setMeetOrSlice(mMeetOrSlice);
|
||||
viewBox.setupDimensions(new Rect(0, 0, (int) rectWidth, (int) rectHeight));
|
||||
Matrix transform = viewBox.getTransform();
|
||||
|
||||
transform.mapRect(renderRect);
|
||||
Matrix translation = new Matrix();
|
||||
translation.postTranslate(rectX, rectY);
|
||||
translation.mapRect(renderRect);
|
||||
|
||||
Path clip = new Path();
|
||||
|
||||
Path clipPath = getClipPath(canvas, paint);
|
||||
|
||||
if (clipPath != null) {
|
||||
// clip by the common area of clipPath and mPath
|
||||
clip.setFillType(Path.FillType.INVERSE_EVEN_ODD);
|
||||
|
||||
Path inverseWindingPath = new Path();
|
||||
inverseWindingPath.setFillType(Path.FillType.INVERSE_WINDING);
|
||||
inverseWindingPath.addPath(mPath);
|
||||
inverseWindingPath.addPath(clipPath);
|
||||
|
||||
Path evenOddPath = new Path();
|
||||
evenOddPath.setFillType(Path.FillType.EVEN_ODD);
|
||||
evenOddPath.addPath(mPath);
|
||||
evenOddPath.addPath(clipPath);
|
||||
|
||||
canvas.clipPath(evenOddPath, Region.Op.DIFFERENCE);
|
||||
canvas.clipPath(inverseWindingPath, Region.Op.DIFFERENCE);
|
||||
} else {
|
||||
canvas.clipPath(mPath, Region.Op.REPLACE);
|
||||
}
|
||||
|
||||
canvas.drawBitmap(bitmap, null, renderRect, alphaPaint);
|
||||
restoreCanvas(canvas, count);
|
||||
markUpdateSeen();
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
package com.horcrux.svg;
|
||||
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Matrix;
|
||||
import android.graphics.Paint;
|
||||
|
||||
import com.facebook.react.bridge.ReadableArray;
|
||||
@@ -85,8 +86,13 @@ public class RNSVGViewBoxShadowNode extends RNSVGGroupShadowNode {
|
||||
|
||||
@Override
|
||||
public void draw(Canvas canvas, Paint paint, float opacity) {
|
||||
// based on https://svgwg.org/svg2-draft/coords.html#ComputingAViewportsTransform
|
||||
setupDimensions(canvas);
|
||||
mMatrix = getTransform();
|
||||
super.draw(canvas, paint, opacity);
|
||||
}
|
||||
|
||||
public Matrix getTransform() {
|
||||
// based on https://svgwg.org/svg2-draft/coords.html#ComputingAViewportsTransform
|
||||
|
||||
// Let vb-x, vb-y, vb-width, vb-height be the min-x, min-y, width and height values of the viewBox attribute respectively.
|
||||
float vbX = PropHelper.fromPercentageToFloat(mMinX, mCanvasWidth, 0, mScale);
|
||||
@@ -134,7 +140,7 @@ public class RNSVGViewBoxShadowNode extends RNSVGGroupShadowNode {
|
||||
if (!mAlign.equals("none") && mMeetOrSlice == MOS_MEET) {
|
||||
scaleX = scaleY = Math.min(scaleX, scaleY);
|
||||
} else if (!mAlign.equals("none") && mMeetOrSlice == MOS_SLICE) {
|
||||
scaleX = scaleY = Math.min(scaleX, scaleY);
|
||||
scaleX = scaleY = Math.max(scaleX, scaleY);
|
||||
}
|
||||
|
||||
// If align contains 'xMid', minus (e-width / scale-x - vb-width) / 2 from transform-x.
|
||||
@@ -161,10 +167,10 @@ public class RNSVGViewBoxShadowNode extends RNSVGGroupShadowNode {
|
||||
|
||||
// The transform applied to content contained by the element is given by
|
||||
// translate(translate-x, translate-y) scale(scale-x, scale-y).
|
||||
mMatrix.reset();
|
||||
mMatrix.postTranslate(-translateX * (mFromSymbol ? scaleX : 1), -translateY * (mFromSymbol ? scaleY : 1));
|
||||
mMatrix.postScale(scaleX, scaleY);
|
||||
super.draw(canvas, paint, opacity);
|
||||
Matrix transform = new Matrix();
|
||||
transform.postTranslate(-translateX * (mFromSymbol ? scaleX : 1), -translateY * (mFromSymbol ? scaleY : 1));
|
||||
transform.postScale(scaleX, scaleY);
|
||||
return transform;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -236,16 +236,21 @@ public abstract class RNSVGVirtualNode extends LayoutShadowNode {
|
||||
}
|
||||
}
|
||||
|
||||
protected void clip(Canvas canvas, Paint paint) {
|
||||
protected @Nullable Path getClipPath(Canvas canvas, Paint paint) {
|
||||
Path clip = mClipPath;
|
||||
if (clip == null && mClipPathRef != null) {
|
||||
RNSVGVirtualNode node = getSvgShadowNode().getDefinedClipPath(mClipPathRef);
|
||||
clip = node.getPath(canvas, paint);
|
||||
}
|
||||
|
||||
return clip;
|
||||
}
|
||||
|
||||
protected void clip(Canvas canvas, Paint paint) {
|
||||
Path clip = getClipPath(canvas, paint);
|
||||
|
||||
if (clip != null) {
|
||||
canvas.clipPath(clip, Region.Op.REPLACE);
|
||||
canvas.saveLayer(0f, 0f, 0f, 0f, paint, Canvas.CLIP_SAVE_FLAG);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -286,6 +291,13 @@ public abstract class RNSVGVirtualNode extends LayoutShadowNode {
|
||||
mCanvasHeight = canvas.getHeight();
|
||||
}
|
||||
|
||||
protected void setupDimensions(Rect rect) {
|
||||
mCanvasX = rect.left;
|
||||
mCanvasY = rect.top;
|
||||
mCanvasWidth = rect.width();
|
||||
mCanvasHeight = rect.height();
|
||||
}
|
||||
|
||||
protected void saveDefinition() {
|
||||
if (mName != null) {
|
||||
getSvgShadowNode().defineTemplate(this, mName);
|
||||
|
||||
@@ -4,7 +4,8 @@ import {ImageAttributes} from '../lib/attributes';
|
||||
import {numberProp, touchableProps, responderProps} from '../lib/props';
|
||||
import Shape from './Shape';
|
||||
import resolveAssetSource from 'react-native/Libraries/Image/resolveAssetSource';
|
||||
|
||||
import {meetOrSliceTypes, alignEnum} from './ViewBox';
|
||||
const spacesRegExp = /\s+/;
|
||||
|
||||
class Image extends Shape {
|
||||
static displayName = 'Image';
|
||||
@@ -15,15 +16,16 @@ class Image extends Shape {
|
||||
y: numberProp,
|
||||
width: numberProp.isRequired,
|
||||
height: numberProp.isRequired,
|
||||
href: PropTypes.number.isRequired
|
||||
//preserveAspectRatio: PropTypes.string
|
||||
href: PropTypes.number.isRequired,
|
||||
preserveAspectRatio: PropTypes.string
|
||||
};
|
||||
|
||||
static defaultProps = {
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: 0,
|
||||
height: 0
|
||||
height: 0,
|
||||
preserveAspectRatio: 'xMidYMid meet'
|
||||
};
|
||||
|
||||
setNativeProps = (...args) => {
|
||||
@@ -32,6 +34,10 @@ class Image extends Shape {
|
||||
|
||||
render() {
|
||||
let {props} = this;
|
||||
let modes = props.preserveAspectRatio.trim().split(spacesRegExp);
|
||||
let meetOrSlice = meetOrSliceTypes[modes[1]] || 0;
|
||||
let align = alignEnum[modes[0]] || 'xMidYMid';
|
||||
|
||||
return <RNSVGImage
|
||||
ref={ele => {this.root = ele;}}
|
||||
{...this.extractProps({...props, x: null, y: null}, {responder: true, transform: true})}
|
||||
@@ -39,6 +45,8 @@ class Image extends Shape {
|
||||
y={props.y.toString()}
|
||||
width={props.width.toString()}
|
||||
height={props.height.toString()}
|
||||
meetOrSlice={meetOrSlice}
|
||||
align={align}
|
||||
src={resolveAssetSource(props.href)}
|
||||
/>;
|
||||
}
|
||||
|
||||
@@ -73,3 +73,8 @@ const RNSVGViewBox = createReactNativeComponentClass({
|
||||
|
||||
|
||||
export default ViewBox;
|
||||
|
||||
export {
|
||||
meetOrSliceTypes,
|
||||
alignEnum
|
||||
}
|
||||
|
||||
@@ -9,12 +9,16 @@
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "RNSVGRenderable.h"
|
||||
#import "RNSVGVBMOS.h"
|
||||
|
||||
@interface RNSVGImage : RNSVGRenderable
|
||||
|
||||
@property (nonatomic, assign) id src;
|
||||
@property (nonatomic, strong) NSString* x;
|
||||
@property (nonatomic, strong) NSString* y;
|
||||
@property (nonatomic, strong) NSString* width;
|
||||
@property (nonatomic, strong) NSString* height;
|
||||
@property (nonatomic, strong) NSString *align;
|
||||
@property (nonatomic, assign) RNSVGVBMOS meetOrSlice;
|
||||
|
||||
@end
|
||||
|
||||
@@ -7,12 +7,15 @@
|
||||
*/
|
||||
|
||||
#import "RNSVGImage.h"
|
||||
#import "RCTImageSource.h"
|
||||
#import "RCTConvert+RNSVG.h"
|
||||
#import "RCTLog.h"
|
||||
#import "RNSVGViewBox.h"
|
||||
|
||||
@implementation RNSVGImage
|
||||
{
|
||||
CGImageRef image;
|
||||
CGImageRef _image;
|
||||
CGFloat _imageRatio;
|
||||
}
|
||||
|
||||
- (void)setSrc:(id)src
|
||||
@@ -21,8 +24,10 @@
|
||||
return;
|
||||
}
|
||||
_src = src;
|
||||
CGImageRelease(image);
|
||||
image = CGImageRetain([RCTConvert CGImage:src]);
|
||||
CGImageRelease(_image);
|
||||
RCTImageSource *source = [RCTConvert RCTImageSource:src];
|
||||
_imageRatio = source.size.width / source.size.height;
|
||||
_image = CGImageRetain([RCTConvert CGImage:src]);
|
||||
[self invalidate];
|
||||
}
|
||||
|
||||
@@ -62,29 +67,80 @@
|
||||
_height = height;
|
||||
}
|
||||
|
||||
- (void)setAlign:(NSString *)align
|
||||
{
|
||||
if (align == _align) {
|
||||
return;
|
||||
}
|
||||
[self invalidate];
|
||||
_align = align;
|
||||
}
|
||||
|
||||
- (void)setMeetOrSlice:(RNSVGVBMOS)meetOrSlice
|
||||
{
|
||||
if (meetOrSlice == _meetOrSlice) {
|
||||
return;
|
||||
}
|
||||
[self invalidate];
|
||||
_meetOrSlice = meetOrSlice;
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
CGImageRelease(image);
|
||||
CGImageRelease(_image);
|
||||
}
|
||||
|
||||
- (void)renderLayerTo:(CGContextRef)context
|
||||
{
|
||||
CGRect rect = [self getRect:context];
|
||||
// add hit area
|
||||
self.hitArea = CGPathCreateWithRect(rect, nil);
|
||||
self.hitArea = CFAutorelease(CGPathCreateWithRect(rect, nil));
|
||||
[self clip:context];
|
||||
|
||||
CGContextSaveGState(context);
|
||||
CGContextTranslateCTM(context, 0, rect.size.height);
|
||||
CGContextScaleCTM(context, 1.0, -1.0);
|
||||
CGContextDrawImage(context, rect, image);
|
||||
CGContextTranslateCTM(context, 0, rect.size.height + 2 * rect.origin.y);
|
||||
CGContextScaleCTM(context, 1, -1);
|
||||
|
||||
// apply viewBox transform on Image render.
|
||||
CGFloat imageRatio = _imageRatio;
|
||||
CGFloat rectWidth = rect.size.width;
|
||||
CGFloat rectHeight = rect.size.height;
|
||||
CGFloat rectX = rect.origin.x;
|
||||
CGFloat rectY = rect.origin.y;
|
||||
CGFloat rectRatio = rectWidth / rectHeight;
|
||||
CGRect renderRect;
|
||||
|
||||
if (imageRatio == rectRatio) {
|
||||
renderRect = rect;
|
||||
} else if (imageRatio < rectRatio) {
|
||||
renderRect = CGRectMake(0, 0, rectHeight * imageRatio, rectHeight);
|
||||
} else {
|
||||
renderRect = CGRectMake(0, 0, rectWidth, rectWidth / imageRatio);
|
||||
}
|
||||
|
||||
RNSVGViewBox *viewBox = [[RNSVGViewBox alloc] init];
|
||||
viewBox.minX = viewBox.minY = @"0";
|
||||
viewBox.vbWidth = [NSString stringWithFormat:@"%f", renderRect.size.width];
|
||||
viewBox.vbHeight = [NSString stringWithFormat:@"%f", renderRect.size.height];
|
||||
viewBox.width = [NSString stringWithFormat:@"%f", rectWidth];
|
||||
viewBox.height = [NSString stringWithFormat:@"%f", rectHeight];
|
||||
viewBox.align = self.align;
|
||||
viewBox.meetOrSlice = self.meetOrSlice;
|
||||
[viewBox setBoundingBox:CGRectMake(0, 0, rectWidth, rectHeight)];
|
||||
CGAffineTransform transform = [viewBox getTransform];
|
||||
|
||||
renderRect = CGRectApplyAffineTransform(renderRect, transform);
|
||||
renderRect = CGRectApplyAffineTransform(renderRect, CGAffineTransformMakeTranslation(rectX, rectY));
|
||||
|
||||
CGContextClipToRect(context, rect);
|
||||
CGContextDrawImage(context, renderRect, _image);
|
||||
CGContextRestoreGState(context);
|
||||
|
||||
}
|
||||
|
||||
- (CGRect)getRect:(CGContextRef)context
|
||||
{
|
||||
[self setBoundingBox:context];
|
||||
[self setBoundingBox:CGContextGetClipBoundingBox(context)];
|
||||
CGFloat x = [self getWidthRelatedValue:self.x];
|
||||
CGFloat y = [self getHeightRelatedValue:self.y];
|
||||
CGFloat width = [self getWidthRelatedValue:self.width];
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
@property (nonatomic, assign) CGPathRef hitArea;
|
||||
@property (nonatomic, copy) NSArray<NSString *> *propList;
|
||||
|
||||
- (void)setBoundingBox:(CGContextRef)context;
|
||||
- (void)setBoundingBox:(CGRect)boundingBox;
|
||||
- (CGFloat)getWidthRelatedValue:(NSString *)string;
|
||||
- (CGFloat)getHeightRelatedValue:(NSString *)string;
|
||||
- (CGFloat)getContextWidth;
|
||||
|
||||
@@ -205,11 +205,11 @@
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setBoundingBox:(CGContextRef)context
|
||||
- (void)setBoundingBox:(CGRect)boundingBox
|
||||
{
|
||||
_boundingBox = CGContextGetClipBoundingBox(context);
|
||||
_widthConverter = [[RNSVGPercentageConverter alloc] initWithRelativeAndOffset:CGRectGetWidth(_boundingBox) offset:0];
|
||||
_heightConverter = [[RNSVGPercentageConverter alloc] initWithRelativeAndOffset:CGRectGetHeight(_boundingBox) offset:0];
|
||||
_boundingBox = boundingBox;
|
||||
_widthConverter = [[RNSVGPercentageConverter alloc] initWithRelativeAndOffset:boundingBox.size.width offset:0];
|
||||
_heightConverter = [[RNSVGPercentageConverter alloc] initWithRelativeAndOffset:boundingBox.size.height offset:0];
|
||||
}
|
||||
|
||||
- (CGFloat)getWidthRelatedValue:(NSString *)string
|
||||
|
||||
@@ -20,4 +20,6 @@
|
||||
@property (nonatomic, strong) NSString *width;
|
||||
@property (nonatomic, strong) NSString *height;
|
||||
|
||||
- (CGAffineTransform)getTransform;
|
||||
|
||||
@end
|
||||
|
||||
@@ -70,9 +70,15 @@
|
||||
}
|
||||
|
||||
- (void)renderTo:(CGContextRef)context
|
||||
{
|
||||
[self setBoundingBox:CGContextGetClipBoundingBox(context)];
|
||||
self.matrix = [self getTransform];
|
||||
[super renderTo:context];
|
||||
}
|
||||
|
||||
- (CGAffineTransform)getTransform
|
||||
{
|
||||
// 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];
|
||||
@@ -150,9 +156,8 @@
|
||||
}
|
||||
}
|
||||
|
||||
self.matrix = CGAffineTransformMakeScale(scaleX, scaleY);
|
||||
self.matrix = CGAffineTransformTranslate(self.matrix, -translateX * (_fromSymbol ? scaleX : 1), -translateY * (_fromSymbol ? scaleY : 1));
|
||||
[super renderTo:context];
|
||||
CGAffineTransform transform = CGAffineTransformMakeScale(scaleX, scaleY);
|
||||
return CGAffineTransformTranslate(transform, -translateX * (_fromSymbol ? scaleX : 1), -translateY * (_fromSymbol ? scaleY : 1));
|
||||
}
|
||||
|
||||
- (void)mergeProperties:(__kindof RNSVGNode *)target mergeList:(NSArray<NSString *> *)mergeList
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
|
||||
- (CGPathRef)getPath:(CGContextRef)context
|
||||
{
|
||||
[self setBoundingBox:context];
|
||||
[self setBoundingBox:CGContextGetClipBoundingBox(context)];
|
||||
CGMutablePathRef path = CGPathCreateMutable();
|
||||
RNSVGPercentageConverter* convert = [[RNSVGPercentageConverter alloc] init];
|
||||
CGFloat cx = [self getWidthRelatedValue:self.cx];
|
||||
|
||||
@@ -49,7 +49,7 @@
|
||||
|
||||
- (CGPathRef)getPath:(CGContextRef)context
|
||||
{
|
||||
[self setBoundingBox:context];
|
||||
[self setBoundingBox:CGContextGetClipBoundingBox(context)];
|
||||
CGMutablePathRef path = CGPathCreateMutable();
|
||||
CGFloat cx = [self getWidthRelatedValue:self.cx];
|
||||
CGFloat cy = [self getHeightRelatedValue:self.cy];
|
||||
|
||||
@@ -49,7 +49,7 @@
|
||||
|
||||
- (CGPathRef)getPath:(CGContextRef)context
|
||||
{
|
||||
[self setBoundingBox:context];
|
||||
[self setBoundingBox:CGContextGetClipBoundingBox(context)];
|
||||
CGMutablePathRef path = CGPathCreateMutable();
|
||||
CGFloat x1 = [self getWidthRelatedValue:self.x1];
|
||||
CGFloat y1 = [self getHeightRelatedValue:self.y1];
|
||||
|
||||
@@ -67,7 +67,7 @@
|
||||
|
||||
- (CGPathRef)getPath:(CGContextRef)context
|
||||
{
|
||||
[self setBoundingBox:context];
|
||||
[self setBoundingBox:CGContextGetClipBoundingBox(context)];
|
||||
CGMutablePathRef path = CGPathCreateMutable();
|
||||
CGFloat x = [self getWidthRelatedValue:self.x];
|
||||
CGFloat y = [self getHeightRelatedValue:self.y];
|
||||
|
||||
@@ -25,5 +25,7 @@ RCT_EXPORT_VIEW_PROPERTY(y, NSString)
|
||||
RCT_EXPORT_VIEW_PROPERTY(width, NSString)
|
||||
RCT_EXPORT_VIEW_PROPERTY(height, NSString)
|
||||
RCT_EXPORT_VIEW_PROPERTY(src, id)
|
||||
RCT_EXPORT_VIEW_PROPERTY(align, NSString)
|
||||
RCT_EXPORT_VIEW_PROPERTY(meetOrSlice, RNSVGVBMOS)
|
||||
|
||||
@end
|
||||
|
||||
@@ -160,7 +160,9 @@ const ImageAttributes = merge({
|
||||
y: true,
|
||||
width: true,
|
||||
height: true,
|
||||
src: true
|
||||
src: true,
|
||||
align: true,
|
||||
meetOrSlice: true
|
||||
}, RenderableAttributes);
|
||||
|
||||
const LineAttributes = merge({
|
||||
|
||||
Reference in New Issue
Block a user