阅读 379

堕落糜烂的光芒-CSS+SVG实现霓虹灯效果

一、往事

几年前,我有幸出差到东莞,在市中心一个85元一晚的小旅馆里面,我很激动。我像个没见过世面的孩子,看着窗外闪亮的霓虹灯招牌,心情久久不能平复。那灯红酒绿的景色,像那神秘的漩涡,把我吸进去了。我舔了舔嘴唇,从门缝下拾起一张名片,拨打了一个从未打过的电话......

--------------------------------强行分割线--------------------------

二、搞下字

在开始前,我们要先想下,霓虹灯的特点是什么。我在东莞的时候由于上面供血不足,只想到了两条,一是要有字,二是要发光。我们先把字弄出来。

        body {
            background: #000000;
            margin: 0;
            font-family: Helvetica, sans-serif;
            overflow: hidden;
        }

        .texta-front {
            font-family: YouYuan;
            font-size: 64px;
            font-weight: normal;
            text-transform: uppercase;
            fill: #db94f7;
        }

<svg width="600" height="250">
        <text text-anchor="middle" x="30%" y="50%" class="texta-front">
            巴黎の玫瑰
        </text>
</svg>复制代码

为了体现霓虹灯的光芒,我特地把背景改成黑色,字使用的是svg的text,用到属性如下:

  • text-anchor:文本锚点属性,被用来描述该文本与所给点的对齐方式 (开头、中间、末尾对齐) 。
  • x,y:表示当前元素针对svg的相对位置的X,Y坐标,可以用百分比表示。
  • class:可以直接在css里面设置属性,然后用class方式引进到svg里面,非常方便

我们再看css,我为了体现霓虹灯的效果,特地选了细长的字体,这里为了能让大多数人看到,选了装了office就有的幼圆字体。弄完后的效果是这样的

好像离完成还有很远的距离

显然,这样是不行的,不发光,这就是个普通的文字而已,开始发光吧。

.texta-front {
            font-family: YouYuan;
            font-size: 64px;
            font-weight: normal;
            text-transform: uppercase;
            stroke: #db94f7;
            stroke-width: 2px;
            text-shadow: 0px 0px 10px #e2b2f5;
        }复制代码

这里我把text-shadow的阴影特效加上去了,为了强化霓虹灯的效果,我把文字的填充(fill)换成了stroke。关于stroke,这里说明一下:

  • stroke:设置绘制对象的线条的颜色。这里我用来做描边。
  • stroke-width:描边的线条粗细。

其实stroke还有其他作用,待会我们会用到。最后的效果是这样的。

这个特效有点靠谱了

三、搞个框

为了不显得单调,我决定给字加个框。

.rect-front {
            stroke: #07eb93;
            stroke-width: 5;
            box-shadow: 0px 0px 10px #07eb93;/*无效,text-shadow也无效 */
        }
<svg width="600" height="250" >
            <rect x="7%" y="25%" rx="30" ry="30" width="340" height="90" fill-opacity="1" class="rect-front" />
                <text text-anchor="middle" x="35%" y="50%" fill-opacity="1" class="texta-front">
                    巴黎の玫瑰
                </text>
    </svg>复制代码

因为我们只需要框,不需要填充,所以还是用了stroke,结果如下:

没有光,啥玩意

很不幸,这个翠绿的框竟然没有光,看了无论是text-shadow还是box-shadow对rect都毫无效果,看来简单的配置就能搞定的时代已经过去了,我只能另想办法了,徒手把光给发出来!

.rect-front {
            stroke: #07eb93;
            stroke-width: 2;
        }
        .rect-back {
            stroke-width: 4;
            filter:url(#filter-blur);
        }

<svg width="600" height="250" >
            <filter id="filter-blur">
                    <feGaussianBlur in="SourceGraphic" stdDeviation="4" />
            </filter>
            <rect x="7%" y="25%" rx="30" ry="30" width="340" height="90" fill-opacity="1" class="rect-front rect-back" />
            <rect x="7%" y="25%" rx="30" ry="30" width="340" height="90" fill-opacity="0" class="rect-front" />
                ......
    </svg>复制代码

之前看过我做云的朋友知道,svg的filter是个好东西,这里我用的就是高斯模糊滤镜(feGaussianBlur ),把模糊后的效果作为底部,上面再铺一层清晰的框,这样,一个发出翠绿光芒的框就出来了,另外,我把前面框的fill-opacity设置成0,是为了让上面的这层rect透明(stroke是不受fill-opacity影响的,不会透明化),方便底下的模糊光可以看的到。最后看到的效果就是这样的

这样看起来有点靠谱了,但看相貌也是平平无奇啊,何必费这功夫写这么多字呢。但这种完美的霓虹灯怎么能入我的法眼,在那神奇的霓虹灯中,总有那损坏的部分更吸引人,比如这种:

是的,没有残缺的霓虹灯是不完整的(本篇金句),所以我决定把霓虹灯颓废的一面表现出来。

四、残缺美

在一个漆黑的巷子里面,一间破旧的酒吧,门口的招牌因为年久失修,招牌已经破损,灯也变的有的亮有的不亮了,里面的老板是一个胡子拉碴的中年男人,他一开口,就用沧桑的口气说:“当年我出差到东莞的时候,一时没忍住..."

--------------------------------再次强行分割线--------------------------

为了达到残缺破损的效果,我用了两样东西,一是旋转,二是破损。先看简单的,旋转效果。

<text text-anchor="middle" x="39%" y="50%" fill-opacity="1" rotate="0 0 0 0 40"class="texta-front">
                    巴黎の玫瑰
</text>复制代码

这里用上了rotate,它的规则如下:

rotate参数值是一个数列,用来规定旋转的度数,单位可以省略,默认是deg。

字符应用角度规则:

(1).如果只有一个参数,所有文本都旋转同一个角度。

(2).如果规定多个参数,第一个参数用于第一个字符,第二个参数用于第二个字符,以此类推。

效果如下:

下面我们还需要搞定破损,既然瑰字都歪斜了,自然电源的接触也不好,那就让它继续破损吧。顺便把这个绿框也搞搞破坏。

.textb-front {
            font-family: YouYuan;
            font-size: 64px;
            font-weight: normal;
            text-transform: uppercase;
            stroke: #723c88;
            stroke-width: 2px;
            stroke-dasharray: 180 280;
            text-shadow: 0px 0px 3px #332638;
        }

        .rect-front {
            stroke: #07eb93;
            stroke-width: 2;
            stroke-dasharray: 180 100;
        }

......
<text text-anchor="middle" x="35%" y="50%" fill-opacity="1" class="texta-front">
                    巴黎の玫
                </text>
                <text text-anchor="middle" x="62%" y="50%" fill-opacity="1" rotate="40" class="textb-front">
                        瑰
                </text>复制代码

这里的关键是stroke-dasharray,它可控制用来描边的点划线的图案范式。它的值是一个数列,一般成对出现,第一个值表示线的长度,第二个值表示缺口的长度,反正我是谁便试,看着合适就行。另外把“瑰”的颜色调深,看着比较像供电不足,最后的效果如下

五、来个图吧

到目前为止,我们都试围绕着字和规则图形来的,但霓虹灯的世界难道只有呆板的文字和形状吗,不,我拒绝。既然试巴黎的玫瑰,没有巴黎也就算了,连玫瑰也没有就太寒酸了,我决定把玫瑰加上去。但普通的图片肯定不行,既然是svg的文章,自然要来张svg的图片。SVG的图片,我想到了马云。

阿里巴巴矢量图标库,你值得拥有,有大量的图标,都可以用多种格式下载,我选了一朵玫瑰,下载成svg的格式

什么是svg图,我抄一段吧,详细的请自行查阅

  • SVG 指可伸缩矢量图形 (Scalable Vector Graphics)
  • SVG 用来定义用于网络的基于矢量的图形
  • SVG 使用 XML 格式定义图形
  • SVG 图像在放大或改变尺寸的情况下其图形质量不会有所损失
  • SVG 是万维网联盟的标准
  • SVG 与诸如 DOM 和 XSL 之类的 W3C 标准是一个整体

它在内容是这样子的

全部的代码太长,我就截个图意思一下吧。我同样通过X,Y的参数挪到合适的位置,效果是这个样子。

但这个玫瑰不发光,算什么霓虹灯,我又开始了发光了。

.svg-font1 {
            fill:none;
            stroke: red;
            stroke-width: 10;
            stroke-dasharray: 880 330;
        }
        .svg-font2 {
            fill:none;
            stroke: yellow;
            stroke-width: 10;
            stroke-dasharray: 700 1030;
        }
        .svg-font3 {
            fill:none;
            stroke: gold;
            stroke-width: 10;
        }
        .svg-font4 {
            fill:none;
            stroke: rgb(243, 40, 165);
            stroke-width: 10;
        }
        .svg-font5 {
            fill:none;
            stroke: rgb(7, 252, 117);
            stroke-width: 10;
        }
        .svg-back {
            filter: url(#filter-blur-svg);
        }
...
<filter id="filter-blur-svg">
                <feGaussianBlur in="SourceGraphic" stdDeviation="15" />
</filter>
...
<svg x="60%" y="0%" t="1562754342698" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"
            p-id="1277" width="128" height="128" fill="1">
            <path class="svg-font1  svg-back" ...
            <path class="svg-font3 svg-back" ...
            <path class="svg-font2 svg-back" ...
            <path class="svg-font4 svg-back" ...
            <path class="svg-font5 svg-back" ...
            <path class="svg-font5 svg-back" ...
            <path class="svg-font5 svg-back" ...
             <path class="svg-font5 svg-back" ...
</svg>
<svg x="60%" y="0%" t="1562754342698" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"
            p-id="1277" width="128" height="128" fill="1">
            <path class="svg-font1" ...
            <path class="svg-font3" ...
            <path class="svg-font2" ...
            <path class="svg-font4" ...
            <path class="svg-font5" ...
            <path class="svg-font5" ...
            <path class="svg-font5 ...
             <path class="svg-font5 svg-back" ...
</svg>复制代码

需要说明的是,svg标签里面可以使用filter="url(#filter_id)"这种方式,直接使用filter,但class="classname"是无效的,但path标签是可以使用的。我就是用一层svg的path使用高斯模糊(feGaussianBlur )作为发光的效果,在上面铺上一层图作为灯光本体,再把颜色改变一下,效果就出来了。然后再次请出stroke-dasharray,给玫瑰花也做出一些缺陷美,就完成了。最后的效果如下:


六、往事-续篇

正在我如痴如醉的撸代码的时候,一阵敲门声传来,一个娇滴滴的声音在旅馆房间的门外传来,“靓仔,是你要的客房服务吗?”。我赶忙开门,急促的说道:“快,快进来,关门”。把人拉进来后,我急忙关上灯,继续拉着人往里走,“来,上床”。在床上,我深吸一口气,迅速打开我的thinkpad,指着屏幕说:“我做的霓虹灯和窗外的比,是不是一模一样...”

源码地址
不会闪的霓虹灯算什么霓虹灯,下次的文章就是要做会闪的霓虹灯,还有东莞的往事,也会有续篇...
预告


关注下面的标签,发现更多相似文章
评论