有个小需求,需要实现一个圆形的头像。要ui设计直接给圆形的png当然可以,但这种解决方式总是不优雅。然后就在网上查了半天,最终找到了使用ClippingNode来实现的方法。
关于ClippingNode,有一篇十分详细的文章,推荐一下:
作者写得十分详细,并且分析了两个十分有用的例子。
这里稍微总结一下,也熟悉一下其中原理。
一、原理
ClippingNode,有三个相关实体:模板(Stencil)、底板、Layer,其原理就是将模板做为遮罩,遮罩本身不渲染,透过遮罩对底板进行裁剪,最后将裁剪后的结果放在Layer层上。
简单来说遮罩上有不同的形状和透明区域(是否透明由setAlphaThreshold来指定,小于指定值的都算透明),根据形状来将裁剪底板,裁剪后当做一个节点,可以和普通node一样任意摆放。
当然,也可以根据透明区域去裁剪,由setInverted(true)来指定。
二、实现带边框圆形头像
现在我们就可以来实现上面说到的功能了。其实有了上面的知识储备,想要什么形状的头像都可以了
1、为什么要带边框
开始尝试只使用ClippingNode来裁剪,确实可以将图变成圆形,但是边上的锯齿严重,非常不好看,所以需要在外面再罩一个圆圈边框,看上去会好很多。对比如下图:
2、实现
实现是很简单的,有了上面的知识储备,就是用一张图当模板,头像图片做底板,最后再盖上一个边框:
/*
设置相关图片,返回设置好后的精灵
@param imgPath:头像图片路径
@param maskPath:模板图片路径
@param circlePath:边框路径
*/
cocos2d::Sprite* CirSprite::setImg(const char* imgPath,const char* maskPath, const char* circlePath)
{
auto clipNode = ClippingNode::create();
auto mask = Sprite::create(maskPath);
clipNode->setAlphaThreshold(0.0f);
clipNode->setStencil(mask);
auto img = Sprite::create(imgPath);
//将头像大小缩放为模板大小
img->setScale(mask->getContentSize().width/img->getContentSize().width);
clipNode->addChild(img);
this->addChild(clipNode);
auto circle = Sprite::create(circlePath);
this->addChild(circle);
return this;
}