Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RN实现长屏截图 #3

Open
ljunb opened this issue Oct 11, 2017 · 4 comments
Open

RN实现长屏截图 #3

ljunb opened this issue Oct 11, 2017 · 4 comments
Labels

Comments

@ljunb
Copy link
Owner

ljunb commented Oct 11, 2017

当前参与的项目中,个别RN界面需要生成长屏图片进行分享,目前是使用了 react-native-view-shot 。安装之后,简单使用方法:

import ViewShot, {captureRef} from 'react-native-view-shot';

export default class SomeView extends Component {
  render() {
    return(
      <View style={styles.container}>
        <ViewShot>
          <ScrollView ref={r => this.scrollView = r}>
            ...
          </ScrollView>
        </ViewShot>
      </View>
    )
  }
}

调用方法:

handleCaptureImage = () => captureRef(this.scrollView, {snapshotContentContainer: true}).then(uri => this.setState({uri}));

文档中对snapshotContentContainer 有说明,具体可参阅 captureRef(view, options) ,注意这个参数其实是属于options里面的,文档罗列参数的层级容易让人误会,我在尝试时就以为它跟options是同层级关系,导致长屏截图无果。

因为其他原生界面也有截屏需求,且同事已经实现相应界面,所以计划在RN界面截图之后,就将图片uri发送到原生,由UIScrollView配合UIImageView来展示图片,同事的实现代码中,contentSize由截图的size决定。

一切都按部就班的进行,但是图片展示出来之后,发现宽度居然是屏幕两倍,导致UIScrollVeiw可以左右滑动,并且高度值也比预想的大,总之问题表现就是图片变大了。于是断点调试打印下图片对象:

(lldb) po shotImage
<UIImage: 0x1c04b8180> size {750, 2211} orientation 0 scale 1.000000

可以看到图片sizewidth750,而自己手机是iPhone 6s,截图宽度是375才正确,这里明显放大了一倍。把展示图片的contentSizewidth改为屏幕宽度,图片明显被压缩了,这不是合适的处理方法。

当对一个组件有疑问的时候,自然是去查看源码实现了。见 源码line67源码line92 ,当没有在options中设置宽高时,且截图内容组件为RCTScrollView子类,则截图size为该可滚动组件的contentSize,这没毛病。再看 源码line108,此行即为实际绘制截图的代码,为何导致当前问题,基本可以在该行代码找到答案了。

这里涉及一个绘图方法UIGraphicsBeginImageContextWithOptions(CGSize size, BOOL opaque, CGFloat scale),各参数说明:

  • size:很明显,该参数用于设置想要渲染的图片的尺寸
  • opaque:指定所生成图片的背景是否为不透明,YES为黑色,NO为透明
  • scale:表示位图的缩放比例,如果设置为0,则让图片的缩放因子根据屏幕的分辨率而变化

再看组件的实现代码:

UIGraphicsBeginImageContextWithOptions(size, NO, 0);

所以组件在绘制时,位图的缩放比例是由屏幕分辨率决定的,而自己的手机的[UIScreen mainScreen].scale2,所以图片实际被放大了一倍。注意不要被上面lldb输出的scale给搞混了,那个是生成之后的图片比例。

既然图片被放大,那么显示之前,再做个缩放好了:

  ...
  // 由截图uri生成UIImage
  UIImage *shotImage = [[UIImage alloc] initWithContentsOfFile:uri];
  CGFloat shotImgW = shotImage.size.width;
  CGFloat shotImgH = shotImage.size.height;
  CGFloat targetW = SCREEN_WIDTH;
  CGFloat targetH =(shotImgH * targetW) / shotImgW;
  CGSize targetSize = CGSizeMake(targetW, targetH);

  // scale不为1时,采用该方法,否则缩放后不清晰
  // 为避免内存占用过高,scale为2或3时,统一设置缩放比例为2
  if ([[UIScreen mainScreen] scale] == 2.0 || [[UIScreen mainScreen] scale] == 3.0) {
    UIGraphicsBeginImageContextWithOptions(targetSize, NO, 2.0);
  } else {
    UIGraphicsBeginImageContext(targetSize);
  }
  [shotImage drawInRect:CGRectMake(0, 0, targetW, targetH)];

  // 最终图片
  UIImage *scaledImage = UIGraphicsGetImageFromCurrentImageContext();
  UIGraphicsEndImageContext();
  ...

至此,由RN生成长屏截图,再由原生UIImageView正确展示图片的功能,就完成了☕️。

@ljunb ljunb added the 笔记 label Oct 12, 2017
@ljunb ljunb changed the title RN长屏截图组件简单记录 RN实现长屏截图 Oct 12, 2017
@jun58
Copy link

jun58 commented Oct 17, 2019

你好,你这个是iOS平台的,Android平台的有用过吗?会不会出现截图很模糊,是怎么处理的?

@ljunb
Copy link
Owner Author

ljunb commented Oct 23, 2019

@jun58 这个是跨平台的,没有遇到截图模糊的情况

@jun58
Copy link

jun58 commented Oct 23, 2019

@ljunb 现状是,图越长越模糊

@ljunb
Copy link
Owner Author

ljunb commented Oct 23, 2019

@jun58 看来那年的业务场景,还没覆盖到这个。你可以在issue列表找找看吧,或者反馈下给作者

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants