窗帘露出景色
Curtain revealing view
我正在尝试实现以下具有挑战性的效果:
我想将白色 "curtain" 向下移动以显示红色框。
(注:下面的截图中幕布为白色,背景为灰色)
问题出在视图层次结构中。
为了让盒子隐藏在初始位置,它必须放在窗帘后面,但为了在最终位置显示,它必须在窗帘上方。
我怎样才能 "cheat" 并且让窗帘看起来真的像用流畅的动画显示盒子一样?
谢谢!
您需要 2 张图片和一个遮罩。您完全遮盖的灰色区域和白色背景的框。窗帘的图像只是底部边缘的遮罩。这样它就可以绘制窗帘的底部边缘而不是抹掉灰色重叠区域。
在顶部设置起始位置,每一帧:
Draw/copy只有窗帘遮罩的大小,通过窗帘遮罩复制对应的红框区域。
将起始位置向下移动一个扫描线并等待下一帧。重复直到完成。
本质上,没有白色的幕布,只有 "hidden" 图像显示的内容,其中包含盒子的白色背景。根据您的绘制方式,您的蒙版图像可能是另一张带有 alpha 通道的图像。
编辑:根据要求,一些示例代码。但是,很可能无论您使用什么在屏幕上获取图形,都已经具有带遮罩的绘制例程,您最好还是使用它。
此代码段未经测试,但应该提供逻辑并且几乎可以在任何地方使用。我不熟悉 iOS 并且不知道您的图像像素是什么格式,24 位、32 位等,因此使用 "PixelType" 作为替代。
这还假设带有黑色背景的白色窗帘边缘是在绘图程序中作为 8 位图像制作的,黑色为零,其他为白色。它的宽度应与其他两张图片的宽度相同,高度仅与窗帘边缘所需的一样高。
struct Mask
{
char *mData; // set this to the image data of your 8 bit mask
int mWidth; // width in pixels, should be the same as your 2 images
int mHeight; // height in pixels of the mask
};
int iRevealPos = 0; // increment each frame value until box is revealed.
// Hopefully, your pixel type is a basic type like byte, short or int.
void Reveal(PixelType *foreground, PixelType *background, Mask *mask)
{
int height = (iRevealPos < mask->mHeight) ? iRevealPos : mask->mHeight; // account for initial slide in
PixelType *src = background + (iRevealPos * mask->mWidth); // background box at current reveal position
PixelType *dst = foreground + (iRevealPos * mask->mWidth); // matching foreground screen position
int count = mask->mWidth * height;
char *filter = mask->mData;
if ((iRevealPos < mask->mHeight)) // adjust for initial slide in
filter += (mask->mHeight - iRevealPos) * mask->mWidth;
while (count--)
{
if (*filter++) // not black?
*dst++ = *src++; // copy the box image
else // skip this pixel
{
src++;
dst++;
}
}
// if you create your mask with a solid white line at the top, you don't need this
if (iRevealPos > mask->mHeight) // fixup, so the mask doesn't leave a trail
{
src = background + ((iRevealPos-1) * mask->mWidth);
dst = foreground + ((iRevealPos-1) * mask->mWidth);
count = mask->mWidth;
while (count--)
*dst++ = *src++;
}
iRevealPos++; // bump position for next time
}
如果您在顶部使用白色实线或 2 创建您的蒙版,则不需要第二个循环来修复蒙版留下的任何痕迹。我还允许窗帘滑入而不是在开始时完全弹出。这是未经测试的,所以我可能对此进行了错误的调整。
我正在尝试实现以下具有挑战性的效果: 我想将白色 "curtain" 向下移动以显示红色框。 (注:下面的截图中幕布为白色,背景为灰色)
问题出在视图层次结构中。
为了让盒子隐藏在初始位置,它必须放在窗帘后面,但为了在最终位置显示,它必须在窗帘上方。
我怎样才能 "cheat" 并且让窗帘看起来真的像用流畅的动画显示盒子一样?
谢谢!
您需要 2 张图片和一个遮罩。您完全遮盖的灰色区域和白色背景的框。窗帘的图像只是底部边缘的遮罩。这样它就可以绘制窗帘的底部边缘而不是抹掉灰色重叠区域。
在顶部设置起始位置,每一帧: Draw/copy只有窗帘遮罩的大小,通过窗帘遮罩复制对应的红框区域。 将起始位置向下移动一个扫描线并等待下一帧。重复直到完成。
本质上,没有白色的幕布,只有 "hidden" 图像显示的内容,其中包含盒子的白色背景。根据您的绘制方式,您的蒙版图像可能是另一张带有 alpha 通道的图像。
编辑:根据要求,一些示例代码。但是,很可能无论您使用什么在屏幕上获取图形,都已经具有带遮罩的绘制例程,您最好还是使用它。 此代码段未经测试,但应该提供逻辑并且几乎可以在任何地方使用。我不熟悉 iOS 并且不知道您的图像像素是什么格式,24 位、32 位等,因此使用 "PixelType" 作为替代。
这还假设带有黑色背景的白色窗帘边缘是在绘图程序中作为 8 位图像制作的,黑色为零,其他为白色。它的宽度应与其他两张图片的宽度相同,高度仅与窗帘边缘所需的一样高。
struct Mask
{
char *mData; // set this to the image data of your 8 bit mask
int mWidth; // width in pixels, should be the same as your 2 images
int mHeight; // height in pixels of the mask
};
int iRevealPos = 0; // increment each frame value until box is revealed.
// Hopefully, your pixel type is a basic type like byte, short or int.
void Reveal(PixelType *foreground, PixelType *background, Mask *mask)
{
int height = (iRevealPos < mask->mHeight) ? iRevealPos : mask->mHeight; // account for initial slide in
PixelType *src = background + (iRevealPos * mask->mWidth); // background box at current reveal position
PixelType *dst = foreground + (iRevealPos * mask->mWidth); // matching foreground screen position
int count = mask->mWidth * height;
char *filter = mask->mData;
if ((iRevealPos < mask->mHeight)) // adjust for initial slide in
filter += (mask->mHeight - iRevealPos) * mask->mWidth;
while (count--)
{
if (*filter++) // not black?
*dst++ = *src++; // copy the box image
else // skip this pixel
{
src++;
dst++;
}
}
// if you create your mask with a solid white line at the top, you don't need this
if (iRevealPos > mask->mHeight) // fixup, so the mask doesn't leave a trail
{
src = background + ((iRevealPos-1) * mask->mWidth);
dst = foreground + ((iRevealPos-1) * mask->mWidth);
count = mask->mWidth;
while (count--)
*dst++ = *src++;
}
iRevealPos++; // bump position for next time
}
如果您在顶部使用白色实线或 2 创建您的蒙版,则不需要第二个循环来修复蒙版留下的任何痕迹。我还允许窗帘滑入而不是在开始时完全弹出。这是未经测试的,所以我可能对此进行了错误的调整。