刘亦菲作为中国真美女的代表,因为360无死角的美貌深受中国没有对象却要面向对象编程的程序猿的喜爱,今天就借神仙姐姐的一张照片展示下SVG的变装艺术。

      俗话说:开篇一张图,内容全靠编,我们就从这张照片开始,然后开始编(程序)。如果性急的朋友想先看到最终效果,翻到最后,可以看到在线演示的地址。

神仙姐姐的变装秀-photoshop,SVG综合艺术小赏-LMLPHP

1、找衣服

想要变装,首先就要找到衣服在哪,这个需要先请出PHOTOSHOP。啥,你不会PS?告诉你吼,不会ps的前端不是好的单身汉,你怎么好意思说这个话。我们先用ps打开上面这张图,选择魔棒工具,

神仙姐姐的变装秀-photoshop,SVG综合艺术小赏-LMLPHP

把照片中的白色衣服部门都加入选区,就像这样

神仙姐姐的变装秀-photoshop,SVG综合艺术小赏-LMLPHP

然后在虚线的选区里面用鼠标右键选择“建立工作路径”,把选区保存成工作路径。这里需要注意一点,建立工作路径的时候,不要把容差像素选的太小(最小是0.5像素),否则路径展现出来的区域锯齿会很明显。

神仙姐姐的变装秀-photoshop,SVG综合艺术小赏-LMLPHP

神仙姐姐的变装秀-photoshop,SVG综合艺术小赏-LMLPHP

然后把工作路径导出到AI文件

神仙姐姐的变装秀-photoshop,SVG综合艺术小赏-LMLPHP

我们就得到了一个.ai的文件,这个文件就是矢量的文件路径。

2、生成svg文件

刚才我们得到了一个.ai的文件,这个后缀的文件可以被adobe illustrator打开,我们打开adobe illustrator....

愤怒的群众:刚才你让我打开ps也就算了,ps用的也还算多,帮女朋友P图的时候也用过,说到女朋友,她的大腿拉长,真难搞....,扯远了,illustrator是个什么鬼玩意

我:adobe illustrator是一款矢量插图软件....

愤怒的群众:它能帮女朋友p肤色身材吗?

我:不可以,不过它是矢量图,和SVG格式一样可以无损缩放....

愤怒的群众:那不学,有没有其他办法,否则我不学了,adobe的东西可贵了。

我:便宜有便宜的做法,我们用简单的方法搞定。

如果用illustrator可以直接把.ai文件打开并转成svg文件,但就为了转个格式,弄一个illustrator不划算,好在互联网啥都有,大家可以在这个网站做格式的转换,AI到SVG转换器,不用注册,直接转换,我们就获取到了神仙姐姐衣服区域的svg文件了。

神仙姐姐的变装秀-photoshop,SVG综合艺术小赏-LMLPHP

3、开始编码第一步,照片和svg文件

终于到了编码的部分了,让我们看下代码:

<div id="container">

        <svg id="product-svg" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" xml:space="preserve" width="640px"
            height="1136px" version="1.1"
            style="shape-rendering:geometricPrecision; text-rendering:geometricPrecision; image-rendering:optimizeQuality; fill-rule:evenodd; clip-rule:evenodd"
            viewBox="0 -293 640 1136" xmlns:xlink="http://www.w3.org/1999/xlink">

            <g id="product-shape" >
                <path
                    d="M 435 356.89C 444.608 357.009 447.67 362.091 454 364.89C 461.682 368.287 473.02 368.768 481 370.89C 482.418 383.019 489.684 392.964 494 402.89C 500.37 403.326 503.811 406.524 509 407.89C 515.069 409.487 519.959 407.72 525 409.89C 548.365 419.945 568.115 438.788 592 447.89C 604.079 452.493 616.042 456.089 627 460.89C 630.151 462.27 638.446 463.196 640 465.89C 640 591.211 640 716.569 640 841.89C 564.674 841.89 489.326 841.89 414 841.89C 411.278 830.633 401.78 824.183 398 814.89C 397.667 809.224 397.333 803.556 397 797.89C 393.842 784.161 393.461 769.681 387 758.89C 383.252 752.631 378.415 746.741 374 740.89C 370.215 735.872 361.228 732.021 359 725.89C 356.486 718.973 358.598 707.994 356 700.89C 350.984 687.175 342.72 675.935 337 663.89C 336.333 656.224 335.667 648.556 335 640.89C 332.189 630.358 326.916 610.397 322 600.89C 320.603 598.189 316.382 595.464 315 592.89C 315 591.557 315 590.223 315 588.89C 312.667 586.89 310.333 584.89 308 582.89C 307.667 576.89 307.333 570.889 307 564.89C 304.647 554.913 303.802 542.039 300 532.89C 295.442 521.921 286.33 510.813 279 501.89C 277.667 501.223 276.333 500.556 275 499.89C 269.871 492.59 272.501 478.438 270 468.89C 266.482 455.459 260.206 446.315 260 429.89C 261.516 429.354 261.693 429.215 264 428.89C 268.035 433.759 274.524 436.435 279 440.89C 285.562 447.42 292.165 454.709 300 459.89C 306.819 464.399 314.496 466.153 321 470.89C 332.781 479.47 343.161 490.077 355 498.89C 363.965 505.564 369.23 516.914 377 524.89C 384.12 532.199 391.977 538.433 400 544.89C 400.333 545.89 400.667 546.89 401 547.89C 405.792 552.398 412.614 555.027 417 559.89C 424.432 568.13 430.565 579.904 441 584.89C 441 584.223 441 583.556 441 582.89C 448.136 572.212 446.877 550.928 451 536.89C 452.334 532.348 455.39 526.209 457 521.89C 457.333 519.557 457.667 517.223 458 514.89C 458.649 513.395 461.403 512.401 462 510.89C 465.217 502.738 464.197 493.538 467 484.89C 470.464 474.2 477.422 464.946 478 450.89C 459.601 437.429 476.984 418.678 479 403.89C 459.681 393.116 436.043 385.84 435 356.89z" />
                <path
                    d="M 149 399.89C 148.462 407.57 144.433 418.001 147 426.89C 149.516 435.601 149.026 443.839 149 454.89C 151.933 456.364 152.223 455.971 153 459.89C 149.931 463 157.052 484.766 166 484.89C 164.314 496.205 170.063 493.683 173 502.89C 173.333 507.223 173.667 511.557 174 515.89C 177.507 529.877 177.79 546.883 184 558.89C 188.074 566.767 196.978 572.826 201 580.89C 201 584.223 201 587.557 201 590.89C 202.299 596.322 202.56 603.967 205 609.89C 208.41 618.168 215.046 625.957 219 633.89C 222.92 641.756 224.579 655.913 226 662.89C 227.9 672.218 223.996 679.582 226 687.89C 229.887 704.004 243.78 736.285 258 739.89C 257.043 753.447 265.829 765.444 268 779.89C 270.076 780.262 269.924 780.132 271 780.89C 275.347 786.936 276.564 794.806 281 800.89C 290.538 813.969 303.303 819.161 304 841.89C 202.677 841.89 101.323 841.89 0 841.89C 0 728.901 0 615.878 0 502.89C 21.4317 490.348 41.4014 474.965 61 460.89C 68.3359 455.621 76.9492 451.393 83 444.89C 87.7162 439.821 98.6967 421.282 104 418.89C 108.333 418.89 112.667 418.89 117 418.89C 119.698 416.749 124.022 416.879 127 414.89C 133.933 410.258 135.018 399.376 146 398.89C 147.073 399.641 146.946 399.491 149 399.89z" />

            </g>
        </svg>
        <img id="background-image"
            src="https://hbimg.huabanimg.com/f27eb7a381ad10ae51e161367538116e0a417effdea0d-hzE4Zg_fw658" alt="">
    </div>

中间一大坨的代码就是转换成的svg文件里面的内容,包括了两个path,细心的朋友如果仔细观察过照片,就能看到辫子把衣服分割成了两个独立的部分,所以会有两个path(啥,都只关注神仙姐姐的脸去了,其他地方没顾上)。下面就是神仙姐姐的那张照片了,用的是img标签,就不详述了。

4、CSS来一个

CSS的核心有两个作用,一是怎么把svg路径叠加在照片上面,让我们看下面这段

#product-svg {
  position: relative;
  z-index: 2;
  background-size: 100%;
  background-repeat: no-repeat;
  background-position: 50%;
  mix-blend-mode: multiply;
  display: block;
  position: relative;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}

#background-image {
  display: block;
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}

通过z-index 属性设置元素的堆叠顺序。拥有更高堆叠顺序的元素总是会处于堆叠顺序较低的元素的前面。这样,svg就堆叠在了图片的上面。

mix-blend-mode是这篇文章真正的核心,它是一种混合模式,可以作用于自身和堆叠顺序低于自己的图形(包括文字、图片和SVG图形等),我们这边用的是multiply,中文名称叫正片叠加。这里我们就能够把svg文件里面的内容叠加到图片上,用来改变图片选区的样子,但它不是覆盖,所以我们仍然能看到下面图片的样子。这个具体的解释可以看这里,讲的很详细。

CSS另外一个作用比较简单,就是给svg选区添加颜色

#product-shape {
  fill: #DBED64;
}

这样,神仙姐姐的身上就不再是白衣服了,而是黄颜色。但现在图片和svg选区并没有叠在一起,这需要我们做一些调整,把图片和svg纹丝合缝的叠加在一起。

5、图片和svg文件位置叠加的调整

让我们先看代码:

// Reference the color shape that was drawn over the image
const overlay = document.getElementById("product-shape");

// This function simulates background-size: cover for the SVG inside its parent div, so it would likely be helpful for people migrating from using images to using an SVG locked onto with a photo.

// Reference the SVG
const svg = document.getElementById("product-svg");

// Reference the image
const img = document.getElementById("background-image");

// Place the SVG inside a parent div, reference it
const container = document.getElementById("container");

// (On resize)
window.onresize = () => simulateCover(container, svg, img, 640, 1136);

// (On load)
simulateCover(container, svg, img, 640, 1136);

// Pass the parent div, and the SVG (child)
// Pass the image
// x and y are the native dimensions of the image
function simulateCover(parent, child, image, x, y) {
  let { width, height } = parent.getBoundingClientRect();
  let yPercentage = x / y;
  let xPercentage = y / x;

  if (width < height * yPercentage) {
    child.style.width = height * yPercentage + "px";
    child.style.height = height + "px";

    image.style.width = height * yPercentage + "px";
    image.style.height = height + "px";

  } else {
    child.style.width = width + "px";
    child.style.height = width * xPercentage + "px";

    image.style.width = width + "px";
    image.style.height = width * xPercentage + "px";


  }
}

这段的核心是simulateCover函数,数字640和1136是图片的宽度和高度。通过对child(就是svg区域)和image(图片)的位置的计算,把两者重叠在一起,主要是把宽度统一,高度我通过SVG本身的属性来控制,主要是下面这一句

<svg id="product-svg" viewBox="0 -293 640 1136">

这里我把SVG画布(viewBox)的高度和宽度调整的和图片一样,但SVG区域其实没有那么高,所以通过viewBox的第二个参数-293把svg区域往下挪,和图片中衣服的部分重叠就好了。viewBox四个参数分别代表的意思是最小X轴数值/最小y轴数值/宽度/高度。

6、选颜色

最后,我们使用一个颜色选择器选颜色,然后把颜色赋给svg区域,我们就能够随心所以的给神仙姐姐的衣服变换颜色了。

<input class="jscolor {onFineChange:'changeColor(this)'}" value="DBED64">
    <!-- partial -->
    <script src='https://cdnjs.cloudflare.com/ajax/libs/jscolor/2.0.4/jscolor.js'></script>
// Reference the color shape that was drawn over the image
const overlay = document.getElementById("product-shape");

function changeColor(picker) {
  // Set the fill style
  overlay.style.fill = picker.toHEXString();
}

最终,我们看到的效果就是这样的

神仙姐姐的变装秀-photoshop,SVG综合艺术小赏-LMLPHP

代码地址

在线围观地址

09-13 16:02