drawRect 绘图“透明”文本?

发布于 2024-12-24 02:54:31 字数 367 浏览 3 评论 0原文

我希望绘制一个 UILabel (最好通过子类化)作为透明标签,但具有纯色背景。我写了一个简单的例子(抱歉,它很难看,但它很能说明问题:))。

基本上我有一个 UILabel,我希望背景是固定颜色,并且文本应该是透明的。我不想用视图背景为文本着色,而是让它 100% 透明,因为我在背景中有一个纹理,我想确保标签内部和外部对齐。

我整晚都在浏览 SO 并在 Google 上搜索,但没有找到有用的资源。我在 CG 绘图方面没有太多经验,所以我希望有任何链接、帮助、教程或示例代码(也许 Apple 有一些我需要看一下?)。

非常感谢!

在此处输入图像描述

I am looking to draw a UILabel (preferable through subclassing) as a transparent label, but with solid background. I draw up an quick example (sorry, it's ugly, but it gets the points across :)).

Basically I have a UILabel and I would like the background to be a set colour, and the text should be transparent. I do not want to colour the text with the views background, but instead have it be 100% transparent, since I have a texture in the background that I want to make sure lines up inside and outside of the label.

I've been spending the night browsing SO and searching on Google, but I have found no helpful sources. I don't have much experience with CG drawing, so I would appreciate any links, help, tutorial or sample code (maybe Apple has some I need to have a look at?).

Thanks a bunch!

enter image description here

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

浅沫记忆 2024-12-31 02:54:31

我几乎不使用任何代码将其重写为 UILabel 子类,并将其发布到 GitHub

其要点是你重写了drawRect,但是调用了[super drawRect:rect]来让UILabel正常渲染。使用白色标签颜色可以让您轻松地将标签本身用作蒙版。

- (void)drawRect:(CGRect)rect
{
    CGContextRef context = UIGraphicsGetCurrentContext();

    // let the superclass draw the label normally
    [super drawRect:rect];

    CGContextConcatCTM(context, CGAffineTransformMake(1, 0, 0, -1, 0, CGRectGetHeight(rect)));

    // create a mask from the normally rendered text
    CGImageRef image = CGBitmapContextCreateImage(context);
    CGImageRef mask = CGImageMaskCreate(CGImageGetWidth(image), CGImageGetHeight(image), CGImageGetBitsPerComponent(image), CGImageGetBitsPerPixel(image), CGImageGetBytesPerRow(image), CGImageGetDataProvider(image), CGImageGetDecode(image), CGImageGetShouldInterpolate(image));

    CFRelease(image); image = NULL;

    // wipe the slate clean
    CGContextClearRect(context, rect);

    CGContextSaveGState(context);
    CGContextClipToMask(context, rect, mask);

    CFRelease(mask);  mask = NULL;

    [self RS_drawBackgroundInRect:rect];

    CGContextRestoreGState(context);

}

I've rewritten it as a UILabel subclass using barely any code and posted it on GitHub

The gist of it is you override drawRect but call [super drawRect:rect] to let the UILabel render as normal. Using a white label color lets you easily use the label itself as a mask.

- (void)drawRect:(CGRect)rect
{
    CGContextRef context = UIGraphicsGetCurrentContext();

    // let the superclass draw the label normally
    [super drawRect:rect];

    CGContextConcatCTM(context, CGAffineTransformMake(1, 0, 0, -1, 0, CGRectGetHeight(rect)));

    // create a mask from the normally rendered text
    CGImageRef image = CGBitmapContextCreateImage(context);
    CGImageRef mask = CGImageMaskCreate(CGImageGetWidth(image), CGImageGetHeight(image), CGImageGetBitsPerComponent(image), CGImageGetBitsPerPixel(image), CGImageGetBytesPerRow(image), CGImageGetDataProvider(image), CGImageGetDecode(image), CGImageGetShouldInterpolate(image));

    CFRelease(image); image = NULL;

    // wipe the slate clean
    CGContextClearRect(context, rect);

    CGContextSaveGState(context);
    CGContextClipToMask(context, rect, mask);

    CFRelease(mask);  mask = NULL;

    [self RS_drawBackgroundInRect:rect];

    CGContextRestoreGState(context);

}
一个人的夜不怕黑 2024-12-31 02:54:31

使用 CALayer 掩模解决。创建标准蒙版(例如壁纸文本)很简单。为了创建挖空文本,我必须反转蒙版的 Alpha 通道,这涉及将标签渲染到 CGImageRef,然后进行一些像素推送。

sample mask

示例应用程序可在此处获取:https://github.com/robinsenior/RSMaskedLabel

相关代码位于此处以避免将来的链接腐烂:

#import "RSMaskedLabel.h"
#import <QuartzCore/QuartzCore.h>

@interface UIImage (RSAdditions)
+ (UIImage *) imageWithView:(UIView *)view;
- (UIImage *) invertAlpha;
@end

@interface RSMaskedLabel ()
{
    CGImageRef invertedAlphaImage;
}
@property (nonatomic, retain) UILabel *knockoutLabel;
@property (nonatomic, retain) CALayer *textLayer;
- (void) RS_commonInit;
@end

@implementation RSMaskedLabel
@synthesize knockoutLabel, textLayer;

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) 
    {
        [self RS_commonInit];
    }
    return self;
}

- (id)initWithCoder:(NSCoder *)aDecoder
{
    self = [super initWithCoder:aDecoder];
    if (self) 
    {
        [self RS_commonInit];
    }
    return self;
}

+ (Class)layerClass
{
    return [CAGradientLayer class];
}

- (void) RS_commonInit
{
    [self setBackgroundColor:[UIColor clearColor]];

    // create the UILabel for the text
    knockoutLabel = [[UILabel alloc] initWithFrame:[self frame]];
    [knockoutLabel setText:@"booyah"];
    [knockoutLabel setTextAlignment:UITextAlignmentCenter];
    [knockoutLabel setFont:[UIFont boldSystemFontOfSize:72.0]];
    [knockoutLabel setNumberOfLines:1];
    [knockoutLabel setBackgroundColor:[UIColor clearColor]];
    [knockoutLabel setTextColor:[UIColor whiteColor]];

    // create our filled area (in this case a gradient)
    NSArray *colors = [[NSArray arrayWithObjects:
                        (id)[[UIColor colorWithRed:0.349 green:0.365 blue:0.376 alpha:1.000] CGColor],
                        (id)[[UIColor colorWithRed:0.455 green:0.490 blue:0.518 alpha:1.000] CGColor],
                        (id)[[UIColor colorWithRed:0.412 green:0.427 blue:0.439 alpha:1.000] CGColor],
                        (id)[[UIColor colorWithRed:0.208 green:0.224 blue:0.235 alpha:1.000] CGColor],
                        nil] retain];

    NSArray *gradientLocations = [NSArray arrayWithObjects:
                                  [NSNumber numberWithFloat:0.0],
                                  [NSNumber numberWithFloat:0.54],
                                  [NSNumber numberWithFloat:0.55],
                                  [NSNumber numberWithFloat:1], nil];

    // render our label to a UIImage
    // if you remove the call to invertAlpha it will mask the text
    invertedAlphaImage = [[[UIImage imageWithView:knockoutLabel] invertAlpha] CGImage];

    // create a new CALayer to use as the mask
    textLayer = [CALayer layer];
    // stick the image in the layer
    [textLayer setContents:(id)invertedAlphaImage];

    // create a nice gradient layer to use as our fill
    CAGradientLayer *gradientLayer = (CAGradientLayer *)[self layer];

    [gradientLayer setBackgroundColor:[[UIColor clearColor] CGColor]];
    [gradientLayer setColors: colors];
    [gradientLayer setLocations:gradientLocations];
    [gradientLayer setStartPoint:CGPointMake(0.0, 0.0)];
    [gradientLayer setEndPoint:CGPointMake(0.0, 1.0)];
    [gradientLayer setCornerRadius:10];

    // mask the text layer onto our gradient
    [gradientLayer setMask:textLayer];
}

- (void)layoutSubviews
{
    // resize the text layer
    [textLayer setFrame:[self bounds]];
}

- (void)dealloc 
{
    CGImageRelease(invertedAlphaImage);
    [knockoutLabel release];
    [textLayer     release];
    [super         dealloc];
}

@end

@implementation UIImage (RSAdditions)

/*
 create a UIImage from a UIView
 */
+ (UIImage *) imageWithView:(UIView *)view
{
    UIGraphicsBeginImageContextWithOptions(view.bounds.size, NO, 0.0);
    [view.layer renderInContext:UIGraphicsGetCurrentContext()];

    UIImage * img = UIGraphicsGetImageFromCurrentImageContext();

    UIGraphicsEndImageContext();

    return img;
}

/*
 get the image to invert its alpha channel
 */
- (UIImage *)invertAlpha
{
    // scale is needed for retina devices
    CGFloat scale = [self scale];
    CGSize size = self.size;
    int width = size.width * scale;
    int height = size.height * scale;

    CGColorSpaceRef colourSpace = CGColorSpaceCreateDeviceRGB();

    unsigned char *memoryPool = (unsigned char *)calloc(width*height*4, 1);

    CGContextRef context = CGBitmapContextCreate(memoryPool, width, height, 8, width * 4, colourSpace, kCGBitmapByteOrderDefault | kCGImageAlphaPremultipliedLast);

    CGColorSpaceRelease(colourSpace);

    CGContextDrawImage(context, CGRectMake(0, 0, width, height), [self CGImage]);

    for(int y = 0; y < height; y++)
    {
        unsigned char *linePointer = &memoryPool[y * width * 4];

        for(int x = 0; x < width; x++)
        {
            linePointer[3] = 255-linePointer[3];
            linePointer += 4;
        }
    }

    // get a CG image from the context, wrap that into a
    CGImageRef cgImage = CGBitmapContextCreateImage(context);
    UIImage *returnImage = [UIImage imageWithCGImage:cgImage scale:scale orientation:UIImageOrientationUp];

    // clean up
    CGImageRelease(cgImage);
    CGContextRelease(context);
    free(memoryPool);

    // and return
    return returnImage;
}
@end

Solved using CALayer masks. Creating a standard mask (wallpapered text, for example) is simple. To create the knocked-out text, I had to invert the alpha channel of my mask, which involved rendering a label to a CGImageRef and then doing some pixel-pushing.

sample mask

Sample application is available here: https://github.com/robinsenior/RSMaskedLabel

Relevant code is here to avoid future link-rot:

#import "RSMaskedLabel.h"
#import <QuartzCore/QuartzCore.h>

@interface UIImage (RSAdditions)
+ (UIImage *) imageWithView:(UIView *)view;
- (UIImage *) invertAlpha;
@end

@interface RSMaskedLabel ()
{
    CGImageRef invertedAlphaImage;
}
@property (nonatomic, retain) UILabel *knockoutLabel;
@property (nonatomic, retain) CALayer *textLayer;
- (void) RS_commonInit;
@end

@implementation RSMaskedLabel
@synthesize knockoutLabel, textLayer;

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) 
    {
        [self RS_commonInit];
    }
    return self;
}

- (id)initWithCoder:(NSCoder *)aDecoder
{
    self = [super initWithCoder:aDecoder];
    if (self) 
    {
        [self RS_commonInit];
    }
    return self;
}

+ (Class)layerClass
{
    return [CAGradientLayer class];
}

- (void) RS_commonInit
{
    [self setBackgroundColor:[UIColor clearColor]];

    // create the UILabel for the text
    knockoutLabel = [[UILabel alloc] initWithFrame:[self frame]];
    [knockoutLabel setText:@"booyah"];
    [knockoutLabel setTextAlignment:UITextAlignmentCenter];
    [knockoutLabel setFont:[UIFont boldSystemFontOfSize:72.0]];
    [knockoutLabel setNumberOfLines:1];
    [knockoutLabel setBackgroundColor:[UIColor clearColor]];
    [knockoutLabel setTextColor:[UIColor whiteColor]];

    // create our filled area (in this case a gradient)
    NSArray *colors = [[NSArray arrayWithObjects:
                        (id)[[UIColor colorWithRed:0.349 green:0.365 blue:0.376 alpha:1.000] CGColor],
                        (id)[[UIColor colorWithRed:0.455 green:0.490 blue:0.518 alpha:1.000] CGColor],
                        (id)[[UIColor colorWithRed:0.412 green:0.427 blue:0.439 alpha:1.000] CGColor],
                        (id)[[UIColor colorWithRed:0.208 green:0.224 blue:0.235 alpha:1.000] CGColor],
                        nil] retain];

    NSArray *gradientLocations = [NSArray arrayWithObjects:
                                  [NSNumber numberWithFloat:0.0],
                                  [NSNumber numberWithFloat:0.54],
                                  [NSNumber numberWithFloat:0.55],
                                  [NSNumber numberWithFloat:1], nil];

    // render our label to a UIImage
    // if you remove the call to invertAlpha it will mask the text
    invertedAlphaImage = [[[UIImage imageWithView:knockoutLabel] invertAlpha] CGImage];

    // create a new CALayer to use as the mask
    textLayer = [CALayer layer];
    // stick the image in the layer
    [textLayer setContents:(id)invertedAlphaImage];

    // create a nice gradient layer to use as our fill
    CAGradientLayer *gradientLayer = (CAGradientLayer *)[self layer];

    [gradientLayer setBackgroundColor:[[UIColor clearColor] CGColor]];
    [gradientLayer setColors: colors];
    [gradientLayer setLocations:gradientLocations];
    [gradientLayer setStartPoint:CGPointMake(0.0, 0.0)];
    [gradientLayer setEndPoint:CGPointMake(0.0, 1.0)];
    [gradientLayer setCornerRadius:10];

    // mask the text layer onto our gradient
    [gradientLayer setMask:textLayer];
}

- (void)layoutSubviews
{
    // resize the text layer
    [textLayer setFrame:[self bounds]];
}

- (void)dealloc 
{
    CGImageRelease(invertedAlphaImage);
    [knockoutLabel release];
    [textLayer     release];
    [super         dealloc];
}

@end

@implementation UIImage (RSAdditions)

/*
 create a UIImage from a UIView
 */
+ (UIImage *) imageWithView:(UIView *)view
{
    UIGraphicsBeginImageContextWithOptions(view.bounds.size, NO, 0.0);
    [view.layer renderInContext:UIGraphicsGetCurrentContext()];

    UIImage * img = UIGraphicsGetImageFromCurrentImageContext();

    UIGraphicsEndImageContext();

    return img;
}

/*
 get the image to invert its alpha channel
 */
- (UIImage *)invertAlpha
{
    // scale is needed for retina devices
    CGFloat scale = [self scale];
    CGSize size = self.size;
    int width = size.width * scale;
    int height = size.height * scale;

    CGColorSpaceRef colourSpace = CGColorSpaceCreateDeviceRGB();

    unsigned char *memoryPool = (unsigned char *)calloc(width*height*4, 1);

    CGContextRef context = CGBitmapContextCreate(memoryPool, width, height, 8, width * 4, colourSpace, kCGBitmapByteOrderDefault | kCGImageAlphaPremultipliedLast);

    CGColorSpaceRelease(colourSpace);

    CGContextDrawImage(context, CGRectMake(0, 0, width, height), [self CGImage]);

    for(int y = 0; y < height; y++)
    {
        unsigned char *linePointer = &memoryPool[y * width * 4];

        for(int x = 0; x < width; x++)
        {
            linePointer[3] = 255-linePointer[3];
            linePointer += 4;
        }
    }

    // get a CG image from the context, wrap that into a
    CGImageRef cgImage = CGBitmapContextCreateImage(context);
    UIImage *returnImage = [UIImage imageWithCGImage:cgImage scale:scale orientation:UIImageOrientationUp];

    // clean up
    CGImageRelease(cgImage);
    CGContextRelease(context);
    free(memoryPool);

    // and return
    return returnImage;
}
@end
白云悠悠 2024-12-31 02:54:31

这是一种与 Matt Gallagher 类似的技术,它将生成带有图像的反转文本蒙版。

分配(可变)数据缓冲区。创建具有 8 位 Alpha 通道的位图上下文。配置文本绘制的设置。在复制模式下填充整个缓冲区(假定默认颜色的 alpha 值为 1)。以清晰模式写入文本(alpha 值为 0)。从位图上下文创建图像。使用位图作为蒙版从源图像创建新图像。创建一个新的 UIImage 并清理。

每次 textString 或 sourceImage 或大小值更改时,重新生成最终图像。

CGSize size = /* assume this exists */;
UIImage *sourceImage = /* assume this exists */;
NSString *textString = /* assume this exists */;
char *text = [textString cStringUsingEncoding:NSMacOSRomanStringEncoding];
NSUInteger len = [textString lengthOfBytesUsingEncoding:cStringUsingEncoding:NSMacOSRomanStringEncoding];

NSMutableData *data = [NSMutableData dataWithLength:size.width*size.height*1];
CGContextRef context = CGBitmapContextCreate([data mutableBytes], size.width, size.height, 8, size.width, NULL, kCGImageAlphaOnly);

CGContextSelectFont(context, "Gill Sans Bold", 64.0f, kCGEncodingMacRoman);
CGContextSetTextDrawingMode(context, kCGTextFill);

CGContextSetBlendMode(context, kCGBlendModeCopy);
CGContextFillRect(context, overlay.bounds);
CGContextSetBlendMode(context, kCGBlendModeClear);
CGContextShowTextAtPoint(context, 16.0f, 16.0f, text, len);

CGImageRef textImage = CGBitmapContextCreateImage(context);
CGImageRef newImage = CGImageCreateWithMask(sourceImage.CGImage, textImage);

UIImage *finalImage = [UIImage imageWithCGImage:newImage];

CGContextRelease(context);
CFRelease(newImage);
CFRelease(textImage);

另一种方法是将 textImage 放入新图层并将该图层设置在视图图层上。 (删除创建“newImage”和“finalImage”的行。)假设这种情况发生在视图代码中的某处:

CALayer *maskLayer = [[CALayer alloc] init];
CGPoint position = CGPointZero;

// layout the new layer
position = overlay.layer.position;
position.y *= 0.5f;
maskLayer.bounds = overlay.layer.bounds;
maskLayer.position = position;
maskLayer.contents = (__bridge id)textImage;

self.layer.mask = maskLayer;

有更多替代方案,有些可能更好(子类 UIImage 并在超类完成其后直接以清晰模式绘制文本绘画?)。

Here's a technique that's similar to Matt Gallagher's, which will generate an inverted text mask with an image.

Allocate a (mutable) data buffer. Create a bitmap context with an 8-bit alpha channel. Configure settings for text drawing. Fill the whole buffer in copy mode (default colour assumed to have alpha value of 1). Write the text in clear mode (alpha value of 0). Create an image from the bitmap context. Use the bitmap as a mask to make a new image from the source image. Create a new UIImage and clean up.

Every time the textString or sourceImage or size values change, re-generate the final image.

CGSize size = /* assume this exists */;
UIImage *sourceImage = /* assume this exists */;
NSString *textString = /* assume this exists */;
char *text = [textString cStringUsingEncoding:NSMacOSRomanStringEncoding];
NSUInteger len = [textString lengthOfBytesUsingEncoding:cStringUsingEncoding:NSMacOSRomanStringEncoding];

NSMutableData *data = [NSMutableData dataWithLength:size.width*size.height*1];
CGContextRef context = CGBitmapContextCreate([data mutableBytes], size.width, size.height, 8, size.width, NULL, kCGImageAlphaOnly);

CGContextSelectFont(context, "Gill Sans Bold", 64.0f, kCGEncodingMacRoman);
CGContextSetTextDrawingMode(context, kCGTextFill);

CGContextSetBlendMode(context, kCGBlendModeCopy);
CGContextFillRect(context, overlay.bounds);
CGContextSetBlendMode(context, kCGBlendModeClear);
CGContextShowTextAtPoint(context, 16.0f, 16.0f, text, len);

CGImageRef textImage = CGBitmapContextCreateImage(context);
CGImageRef newImage = CGImageCreateWithMask(sourceImage.CGImage, textImage);

UIImage *finalImage = [UIImage imageWithCGImage:newImage];

CGContextRelease(context);
CFRelease(newImage);
CFRelease(textImage);

Another way to do this involves putting the textImage into a new layer and setting that layer on your view's layer. (Remove the lines that create "newImage" and "finalImage".) Assuming this happens inside your view's code somewhere:

CALayer *maskLayer = [[CALayer alloc] init];
CGPoint position = CGPointZero;

// layout the new layer
position = overlay.layer.position;
position.y *= 0.5f;
maskLayer.bounds = overlay.layer.bounds;
maskLayer.position = position;
maskLayer.contents = (__bridge id)textImage;

self.layer.mask = maskLayer;

There are more alternatives, some might be better (subclass UIImage and draw the text directly in clear mode after the superclass has done its drawing?).

活泼老夫 2024-12-31 02:54:31

Swift 5 解决方案(Xcode:12.5):

在此处输入图像描述

class MaskedLabel: UILabel {
    
    var maskColor : UIColor?

    override init(frame: CGRect) {
        super.init(frame: frame)
        customInit()
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        customInit()
    }

    func customInit() {
        maskColor = self.backgroundColor
        self.textColor = UIColor.white
        backgroundColor = UIColor.clear
        self.isOpaque = false
    }

    override func draw(_ rect: CGRect) {
        let context = UIGraphicsGetCurrentContext()!

        super.draw(rect)

        context.concatenate(__CGAffineTransformMake(1, 0, 0, -1, 0, rect.height))

        let image: CGImage = context.makeImage()!
        let mask: CGImage = CGImage(maskWidth: image.width, height: image.height, bitsPerComponent: image.bitsPerComponent, bitsPerPixel: image.bitsPerPixel, bytesPerRow: image.bytesPerRow, provider: image.dataProvider!, decode: image.decode, shouldInterpolate: image.shouldInterpolate)!

        context.clear(rect)
        
        context.saveGState()
        context.clip(to: rect, mask: mask)
        
        if (self.layer.cornerRadius != 0.0) {
            context.addPath(CGPath(roundedRect: rect, cornerWidth: self.layer.cornerRadius, cornerHeight: self.layer.cornerRadius, transform: nil))
            context.clip()
        }

        drawBackgroundInRect(rect: rect)
        context.restoreGState()
    }

    func drawBackgroundInRect(rect: CGRect) {
        let context = UIGraphicsGetCurrentContext()

        if let _ = maskColor {
            maskColor!.set()
        }

        context!.fill(rect)
    }
}

Swift 5 solution (Xcode: 12.5):

enter image description here

class MaskedLabel: UILabel {
    
    var maskColor : UIColor?

    override init(frame: CGRect) {
        super.init(frame: frame)
        customInit()
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        customInit()
    }

    func customInit() {
        maskColor = self.backgroundColor
        self.textColor = UIColor.white
        backgroundColor = UIColor.clear
        self.isOpaque = false
    }

    override func draw(_ rect: CGRect) {
        let context = UIGraphicsGetCurrentContext()!

        super.draw(rect)

        context.concatenate(__CGAffineTransformMake(1, 0, 0, -1, 0, rect.height))

        let image: CGImage = context.makeImage()!
        let mask: CGImage = CGImage(maskWidth: image.width, height: image.height, bitsPerComponent: image.bitsPerComponent, bitsPerPixel: image.bitsPerPixel, bytesPerRow: image.bytesPerRow, provider: image.dataProvider!, decode: image.decode, shouldInterpolate: image.shouldInterpolate)!

        context.clear(rect)
        
        context.saveGState()
        context.clip(to: rect, mask: mask)
        
        if (self.layer.cornerRadius != 0.0) {
            context.addPath(CGPath(roundedRect: rect, cornerWidth: self.layer.cornerRadius, cornerHeight: self.layer.cornerRadius, transform: nil))
            context.clip()
        }

        drawBackgroundInRect(rect: rect)
        context.restoreGState()
    }

    func drawBackgroundInRect(rect: CGRect) {
        let context = UIGraphicsGetCurrentContext()

        if let _ = maskColor {
            maskColor!.set()
        }

        context!.fill(rect)
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文