mirror of
https://github.com/zhigang1992/react-native.git
synced 2026-04-26 13:25:51 +08:00
Improve RCTImageView resizing logic
Summary: @public It's less important to reload for downscaling than upscaling, so increase the threshold in that direction. Also, this now considers each dimension separately, and a big enough change either way should result in a reload. Finally, this considers both the current image size and the inflight target size, so we don't reload if either is already good. Reviewed By: @tadeuzagallo Differential Revision: D2470911
This commit is contained in:
committed by
facebook-github-bot-8
parent
de85bcab0b
commit
bcd2ef5dfc
@@ -18,6 +18,21 @@
|
|||||||
|
|
||||||
#import "UIView+React.h"
|
#import "UIView+React.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines whether an image of `currentSize` should be reloaded for display
|
||||||
|
* at `idealSize`.
|
||||||
|
*/
|
||||||
|
static BOOL RCTShouldReloadImageForSizeChange(CGSize currentSize, CGSize idealSize) {
|
||||||
|
static const CGFloat upscaleThreshold = 1.2;
|
||||||
|
static const CGFloat downscaleThreshold = 0.5;
|
||||||
|
|
||||||
|
CGFloat widthMultiplier = idealSize.width / currentSize.width;
|
||||||
|
CGFloat heightMultiplier = idealSize.height / currentSize.height;
|
||||||
|
|
||||||
|
return widthMultiplier > upscaleThreshold || widthMultiplier < downscaleThreshold ||
|
||||||
|
heightMultiplier > upscaleThreshold || heightMultiplier < downscaleThreshold;
|
||||||
|
}
|
||||||
|
|
||||||
@interface RCTImageView ()
|
@interface RCTImageView ()
|
||||||
|
|
||||||
@property (nonatomic, copy) RCTDirectEventBlock onLoadStart;
|
@property (nonatomic, copy) RCTDirectEventBlock onLoadStart;
|
||||||
@@ -146,8 +161,7 @@ RCT_NOT_IMPLEMENTED(- (instancetype)init)
|
|||||||
{
|
{
|
||||||
[self cancelImageLoad];
|
[self cancelImageLoad];
|
||||||
|
|
||||||
if (_src && !CGSizeEqualToSize(self.frame.size, CGSizeZero)) {
|
if (_src && self.frame.size.width > 0 && self.frame.size.height > 0) {
|
||||||
|
|
||||||
if (_onLoadStart) {
|
if (_onLoadStart) {
|
||||||
_onLoadStart(nil);
|
_onLoadStart(nil);
|
||||||
}
|
}
|
||||||
@@ -199,15 +213,20 @@ RCT_NOT_IMPLEMENTED(- (instancetype)init)
|
|||||||
_targetSize = frame.size;
|
_targetSize = frame.size;
|
||||||
[self reloadImage];
|
[self reloadImage];
|
||||||
} else if ([RCTImageView srcNeedsReload:_src]) {
|
} else if ([RCTImageView srcNeedsReload:_src]) {
|
||||||
CGSize idealSize = RCTTargetSize(self.image.size, self.image.scale, frame.size,
|
CGSize imageSize = self.image.size;
|
||||||
RCTScreenScale(), self.contentMode, YES);
|
CGSize idealSize = RCTTargetSize(imageSize, self.image.scale, frame.size, RCTScreenScale(), self.contentMode, YES);
|
||||||
CGFloat widthChangeFraction = ABS(_targetSize.width - idealSize.width) / _targetSize.width;
|
|
||||||
CGFloat heightChangeFraction = ABS(_targetSize.height - idealSize.height) / _targetSize.height;
|
|
||||||
|
|
||||||
// If the combined change is more than 20%, reload the asset in case there is a better size.
|
if (RCTShouldReloadImageForSizeChange(imageSize, idealSize)) {
|
||||||
if (widthChangeFraction + heightChangeFraction > 0.2) {
|
if (RCTShouldReloadImageForSizeChange(_targetSize, idealSize)) {
|
||||||
_targetSize = idealSize;
|
// If the existing image or an image being loaded are not the right size, reload the asset in case there is a
|
||||||
[self reloadImage];
|
// better size available.
|
||||||
|
_targetSize = idealSize;
|
||||||
|
[self reloadImage];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Our existing image is good enough.
|
||||||
|
[self cancelImageLoad];
|
||||||
|
_targetSize = imageSize;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user