天仙子·水调数声持酒听
【宋】张先
水调数声持酒听,午醉醒来愁未醒。送春春去几时回?临晚镜,伤流景,往事后期空记省。
沙上并禽池上暝,云破月来花弄影。重重帘幕密遮灯,风不定,人初静,明日落红应满径。
昨天七夕,下班在地铁里面看到了各种恩爱撒狗粮的,不禁想起当年情窦初开的时候,非常喜欢宋词。而张先,因为“影”字用的好,被称为“张三影”,这首词就是三影之一(不是火影)。回到家,小孩和老婆都睡了(996害死人啊),但心中的火却旺的很,右手也不安份。我想到今天多少对情侣在那啥,我却只能一个人,心中躁动不已,艺术之魂熊熊燃烧,我控制住右手,强行挪开了点击某hub网站的冲动,点开了另一个某hub网站,开始了我的艺术创作。
1、月来
用svg做个月亮还是很简单的,只要画一个发光的大圆饼就好了,上代码。
<circle id="whitemoon" cx="420" cy="160" r="60" fill="white" />
上帝说,要有光,那就来个光
<filter id="blur-moon">
<feGaussianBlur in="SourceGraphic" stdDeviation="3" />
</filter>
用feGaussianBlur模糊后的作为月亮的光,和大圆饼合起来,就是一个发光的月亮了
<use xlink:href="#whitemoon" />
<use xlink:href="#whitemoon" filter="url(#blur-moon)" />
这个月亮圆也很圆,亮也很亮,但是作为一个现代人,我知道月亮上是有环形山的,这么洁白无暇的月亮太假了,所以还要加点黑影。
<circle id="greymoon" cx="420" cy="170" r="45" fill="grey" fill-opacity="0.15"
filter="url(#filter-greymoon)" />
<filter id="filter-greymoon" >
<feTurbulence type="fractalNoise" baseFrequency="0.03" numOctaves="9" seed="3" />
<feDisplacementMap in="SourceGraphic" scale="120" />
</filter>
看过前面做云文章的朋友都知道,feTurbulence和feDisplacementMap的组合用来做纹理和腐蚀效果是很好的,这里也用来做月亮的黑影,这里需要说明一个知识点,这个问题之前其实困扰了我很久。
我们使用filter特效的时候,如果效果超出了图形本身的矩形框范围,那么效果会在矩形框范围直接切断,比如上面这个greymoon,显示出来是这样的
明显可以看出左边切掉了一块,非常影响效果,去掉边界的限制在哪呢?就在filter的属性,这个例子里面,我改成这样就好了
<filter id="filter-greymoon" height="250%" width="250%" x="-100%" y="-100%">
把filter的width,hegith加宽加高,单这样还不行,因为width,height只能影响图形的右边和下边,结果效果只是这样
可以看到,左边和上边仍然被无情的截取了,所以必须把x,y参数加上去,因为是向左和向上,在坐标原点前,所以是负数,最终的效果如下
最后把阴影加到大月亮上去,就能看到最终效果了
<circle id="whitemoon" cx="420" cy="160" r="60" fill="white" />
<circle id="greymoon" cx="420" cy="170" r="30" fill="grey" fill-opacity="0.25"
filter="url(#filter-greymoon)" />
<filter id="filter-greymoon" width="350%" height="250%" x="-100%" y="-100%">
<feTurbulence type="fractalNoise" baseFrequency="0.03" numOctaves="9" seed="3" />
<feDisplacementMap in="SourceGraphic" scale="120" />
</filter>
<g id="moon">
<use xlink:href="#whitemoon" />
<use xlink:href="#whitemoon" filter="url(#blur-moon)" />
<use xlink:href="#greymoon" filter="url(#blur-greymoon)" />
</g>
<use xlink:href="#moon" />
一个比较真实的月亮就做好了(不要和我提阴影和真实的月面情况不一样,我又不是华为手机的AI拍摄,能自动把真实月面给P出来)。
2、云破
月亮做出来了,我们开始做云。之前在做云的文章里面其实已经很详细的讲了做云的方法,所以我这边就不详细讲了。不过这次我们搞点新花样,不用css的box-shadow来做,直接使用svg来做,代码会更简洁。
<defs>
<ellipse id="cloudback" cx="260" cy="230" rx="280" ry="70" fill="white" fill-opacity="0.9"
filter="url(#blur-cloud)" />
<ellipse id="cloudmid" cx="260" cy="240" rx="220" ry="55" fill="#9EA8B3" fill-opacity="0.5"
filter="url(#blur-cloud)" />
<ellipse id="cloudfront" cx="260" cy="260" rx="170" ry="30" fill="black" fill-opacity="0.2"
filter="url(#blur-cloud)" />
<filter id="blur-cloud" width="350%" height="250%" x="-100%" y="-100%">
<feGaussianBlur in="SourceGraphic" stdDeviation="15" />
</filter>
<filter id="filter-back" width="350%" height="250%" x="-100%" y="-100%">
<feTurbulence type="fractalNoise" baseFrequency="0.012" numOctaves="4" seed="0" />
<feDisplacementMap in="SourceGraphic" scale="170" />
</filter>
<filter id="filter-mid" width="350%" height="250%" x="-100%" y="-100%">
<feTurbulence type="fractalNoise" baseFrequency="0.012" numOctaves="4" seed="0" />
<feDisplacementMap in="SourceGraphic" scale="150" />
</filter>
<filter id="filter-front" width="350%" height="250%" x="-100%" y="-100%">
<feTurbulence type="fractalNoise" baseFrequency="0.012" numOctaves="4" seed="0" />
<feDisplacementMap in="SourceGraphic" scale="100" />
</filter>
<g id="cloud">
<use xlink:href="#cloudback" filter="url(#filter-back)" />
<use xlink:href="#cloudmid" filter="url(#filter-mid)" />
<use xlink:href="#cloudfront" filter="url(#filter-front)" />
</g>
</defs>
<use xlink:href="#cloud" />
最后的效果如下
3、花弄影
在这里我们先需要一堵墙,否则影子在哪显示呢,所以我就上花瓣网找了一堵墙过来。图片地址在这里
针对原图我做了一点处理,主要是把墙面搞暗了一些,把图片的天空部分变成了透明,方便显示月亮和云,使用的同样是svg的图片显示
<image xlink:href="yuanqiang1.png" x="0" y="300" width="400"/>
然后是花影,要有花影,首先得有花,同样的,我又从花瓣网弄来了一束花。图片地址忘了存,找不到了┐(゚~゚)┌
<image xlink:href="huazhi1.png" x="200"y="690" width="170"></image>
现在关键来了,花弄影主要是影,我们开始光影的魔法。
<filter id="huazhishadow" x="0" y="0" width="200%" height="200%">
<feOffset result="offOut" in="SourceAlpha" dx="210" dy="0" />
<feGaussianBlur result="blurOut" in="offOut" stdDeviation="1" />
<feBlend in="SourceGraphic" in2="blurOut" mode="darken" />
</filter>
先介绍下这几个filter:
feoffset:该输入图像作为一个整体,在属性dx
和属性dy
的值指定了它的偏移量。说白了就是把原图在离开dx和dy的距离外复制一个一样的图像,活脱脱的拷贝魔法,这就是filter界的旗木卡卡西啊。
feGaussianBlur:老朋友,干模糊化的,略
feBlend:把两个对象组合在一起,使它们受特定的混合模式控制。这类似于图像编辑软件中混合两个图层。它是个粘合剂,把上面两个filter的效果合在一起,并且用mode来控制最后的效果。mode的效果有很多种,我们这边需要的是影子,所以选择了darken,具体的mode说明,请看这里。
<image xlink:href="huazhi1.png" x="0" y="600" width="170" filter="url(#huazhishadow)" />
最后看到的是这样
对话录:
画外音:是不是这样就算做好了
我:当然没有,你没发现我选的这个墙不是平面的吗
画外音:那又怎样
我:这样影子打上去应该是斜的,不是这样平平的影子
画外音:为啥你不选个正平墙的图呢
我:花瓣上没找到啊...
画外音:你为啥要执着于这个影子效果呢,用现在这个就行了
我:不行,我是个严谨的艺术家,我的影子要真实,真实,再真实
画外音:那刚才月亮的阴影你咋不追求真实的月面阴影呢
我:.....,警察叔叔,就是这个声音给我打的诈骗电话,马上抓他去坐牢。
我:让你和我抬杠
画外音:算你狠...
-------------------------------------------------------我是分割线----------------------------------------------
我们需要把花的图片和花的影子分开处理,现在我们把生成影子的花弄出屏幕外
<image xlink:href="huazhi1.png" x="-630" y="720" width="170" filter="url(#huazhishadow)">
通过x的设置,把花的图像移到 屏幕外,只留下影子
<image xlink:href="huazhi1.png" x="-630" y="720" width="170" filter="url(#huazhishadow)" transform="skewX(29)"/>
这里要讲下transform:
transform和上面这些filter不同,是SVG元素的属性。作用是设置svg元素的变形,包括位移translate
, 旋转rotate
, 缩放scale
, 斜切skew。今天我们用到的就是斜切(skew)。具体的大家可以去看这篇文章,讲的很详细。最后的花影的效果如下:
4、成品
当我们把月亮,云、院墙和花影组合起来,就可以看到最终的效果了
<image xlink:href="yuanqiang1.png" x="0" y="300" width="400"/>
<use xlink:href="#moon" />
<use xlink:href="#cloud" />
<image xlink:href="huazhi1.png" x="200"y="690" width="170"></image>
<image xlink:href="huazhi1.png" x="-630" y="720" width="170" filter="url(#huazhishadow)" transform="skewX(29)"/>