如何在iOS中绘制下拉阴影

时间:2010-05-28 16:30:43

标签: iphone

CAShapeLayer使用CGPathRef来绘制它的东西。所以我有一条星路,我想要一个半径约为15个单位的平滑投影。可能在一些新的iPhone OS版本中有一些不错的功能,但我需要自己做一个旧版本的3.0(大多数人仍然使用)。

我试图做一些非常令人讨厌的事情: 我创建了一个for循环并按顺序创建了15个这样的路径,逐步变换它们以变大。然后将它们分配给新创建的CAShapeLayer,并在每次迭代时稍微降低它的alpha值。不仅这个缩放在数学上是不正确的并且很糟糕(它应该相对于轮廓发生!),阴影不是圆形的并且看起来非常难看。这就是为什么漂亮的柔和阴影具有半径。

在15个单位的阴影后,星星的尖端不应该显得非常尖锐。它们应该像奶油一样柔软。但是在我丑陋的解决方案中,它们就像恒星本身一样竖琴,因为我所做的只是将恒星缩放15次并将其降低15次。难看。

我想知道大家伙是怎么做到的?如果你有一个任意路径,并且该路径必须抛出阴影,那么算法如何工作呢?可能必须将路径扩展30次,相对于远离填充部分的轮廓的切线逐点扩展,并且只需0.5个单位即可进行良好的混合。

在重新发明轮子之前,也许有人有一个方便的例子或链接?

2 个答案:

答案 0 :(得分:3)

阴影是一个半透明的灰度蒙版,对象的形状被模糊和偏移。

CGContextSetShadowWithColorCGContextSetShadow是如何在iPhone上完成的。您设置阴影然后绘制一些东西,并且还应用阴影。

CAShapeLayer没有简单的选项来应用阴影。您必须创建自定义视图或图层,并在绘制形状之前设置阴影。

我没有尝试过,但以下情况可能有效:

@interface ShadowShapeLayer : CAShapeLayer
@end

@implementation ShadowShapeLayer
-(void) drawInContext:(CGContextRef)context {
  CGContextSaveGState( context );
  CGContextSetShadow( context , CGSizeMake( 5 , 5 ) , 15 );
  [super drawInContext:context];
  CGContextRestoreGState( context );
}
@end

编辑:谢谢Miser。

答案 1 :(得分:1)

我问自己同样的问题。我根本不是这个主题的专家,但我有以下想法:在物理上,绘图的一个点应该产生圆形(或椭圆形),半透明的阴影。因此,由多个点组成的整个绘图应该会产生许多这样的圆形阴影。

所以我在Photoshop中画了一个小阴影(画笔工具,尺寸7,不透明度33%,颜色#3b3b3b)。它几乎不可见:

alt text

然后我用Javascript编写了一个小HTML,试着看看它的样子(绝对不是理想的技术: - ):

<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="content-type" content="text/html; charset=UTF-8">
    <title>Title</title>

    <script type="text/javascript" language="javascript"> 

        function pageload() {
            var drawingContainerElem = document.getElementById("drawing-container");
            var shadowContainerElem = document.getElementById("shadow-container");

            this.drawDot = function(x, y) {
                var imgElem = document.createElement("img");
                imgElem.style.left = x + "px";
                imgElem.style.top = y + "px";
                imgElem.src = "blue-dot.png";
                drawingContainerElem.appendChild(imgElem);
            }
            this.drawShadow = function(x, y) {
                var imgElem = document.createElement("img");
                imgElem.style.left = x + "px";
                imgElem.style.top = y + "px";
                imgElem.src = "soft-shadow.png";
                shadowContainerElem.appendChild(imgElem);
            }
            this.drawDotAndShadow = function(x, y) {
                drawShadow(x - 5, y - 1);
                drawDot(x, y);
            }

            for (var x = 50; x < 70; x ++) {
                for (var y = 50; y < 58; y ++) {
                    drawDotAndShadow(x, y);
                }
            }
            for (var x = 0; x < 15; x ++) {
                for (var y = 0; y < x; y ++) {
                    drawDotAndShadow(69 + 15 - x, 54 + y);
                    drawDotAndShadow(69 + 15 - x, 54 - y);
                }
            }

        }

    </script>

    <style type="text/css">
        #drawing-container {
            position: absolute;
            left: 2em;
            top: 2em;
            width: 400px;
            height: 400px;
            z-index: 2;
        }
        #shadow-container {
            position: absolute;
            left: 2em;
            top: 2em;
            width: 400px;
            height: 400px;
            z-index: 1;
        }

        #drawing-container img {
            position: absolute;
        }
        #shadow-container img {
            position: absolute;
        }
    </style>

</head>
<body onload="javascript:pageload()">
    <div id="drawing-container"></div>
    <div id="shadow-container"></div>
</body>
</html>

结果如下:

alt text

可能有很多优化空间,当然你不会以这种方式使用javascript真正渲染它...也许你可以找到一种方法如何在iPhone上有效地渲染它?如果是,请告诉我!

可能的改进:

  • 使阴影圆的中心更暗(更不透明),其余更亮(不透明度更低)以达到核心阴影。
  • 缩放阴影:使其变小,以达到深度效果。