写点什么

Logo 小变动,心境大不同,SVG 矢量动画格式网站 Logo 图片制作与实践教程 (Python3)

  • 2022 年 2 月 23 日
  • 本文字数:14308 字

    阅读完需:约 47 分钟

Logo小变动,心境大不同,SVG矢量动画格式网站Logo图片制作与实践教程(Python3)

原文转载自「刘悦的技术博客」https://v3u.cn/a_id_207


曾几何时,SVG(Scalable Vector Graphics)矢量动画图被坊间称之为一种被浏览器诅咒的技术,只因为糟糕的硬件支持(IE),和没完没了的兼容性调优(Safari)。但是在 2022 年的今天,一切都不一样了,正所谓三十年河东,三十年河西,微软所研发的采用 Chromium 内核作为 IE 替代者的 Edge 浏览器已经有望超越 Safari 成为第二大桌面浏览器,而曾经因为不支持关键帧动画被人诟病的 Safari 也统一了标准,市面上除了老帮菜 IE,几乎所有平台(包括移动端)都已经对 SVG 足够友好,这让我们可以放心大胆的在网站上应用 SVG 矢量动画图。


目前国内外相对来说技术先行的平台都已经采用 SVG 矢量格式,比如线上媒体界的巨擘 Netflix、社交平台 Twitter 和国内的 B 站:



总的来说,采用 SVG 格式图像的好处还是比较多的,由于 SVG 图像是矢量图像,可以无限缩放,而且在图像质量下降方面没有任何问题。为什么会这样呢?因为 SVG 图像是使用 XML 标记构建的,浏览器通过绘制每个点和线来打印它们。这确保 SVG 图像可以适应不同的屏幕大小和分辨率,传统图像格式(如 PNG、GIF 或 JPG)是通过预定义的像素来填充色彩空间,这就导致屏幕素质会对图像的成像质量产生影响。


举个例子,传统像素图片就像是食堂里已经烙好的饼,是多大就是多大,碰上胃口好的,饼不够大,就会产生影响,而 SVG 是通过 XML 技术把饼的轮廓和技术参数定义好,由浏览器实时绘制,可以根据胃口的大小自适应饼的大小,达到矢量的目的。同时,由于是在 XML 中定义的,SVG 图像比 JPG 或 PNG 图像更灵活,而且我们可以使用 CSS 和 JavaScript 与它们进行交互。另外从文件体积角度上讲,SVG 并不比 PNG 更大,反而压缩之后体积更小,最后作为 XML 的网页格式,直接在浏览器中解析,所以不需要单独的带宽进行请求,节约了网络请求数,百利而无一害。


接下来的传统节目应该是介绍 SVG 基本语法,然后画几个不痛不痒的简单矢量图,展现一下 SVG 特性,最后草草了事,那样就太无趣了,本次我们来点“快餐”,简单粗暴的将 PNG 的 Logo 图像直接转化成 SVG 格式,略过“绘制”的步骤,五分钟内直接让你的网站 Logo“芜湖起飞”。

SVG 图像转化与压缩

以本站的 Logo 为例子,首先需要一个 PNG 矢量图:



注意图像颜色位数最好越小越好,这样转化后的图像不会过大,同时背景最好是透明的,因为透明元素不会被 XML 文件进行标记,达到节约空间的目的,这里我们以 PNG 仿色 4 位的位图为例子。


转化方式有很多种,可以通过 Python3 的三方图像库:


pip3 install Pillow
复制代码


编写转化脚本 test.py:


import sys  import os  import operator  from collections import deque  import io  from optparse import OptionParser  from PIL import Image      def add_tuple(a, b):      return tuple(map(operator.add, a, b))      def sub_tuple(a, b):      return tuple(map(operator.sub, a, b))      def neg_tuple(a):      return tuple(map(operator.neg, a))      def direction(edge):      return sub_tuple(edge[1], edge[0])      def magnitude(a):      return int(pow(pow(a[0], 2) + pow(a[1], 2), .5))      def normalize(a):      mag = magnitude(a)      assert mag > 0, "Cannot normalize a zero-length vector"      return tuple(map(operator.truediv, a, [mag] * len(a)))      def svg_header(width, height):      return """<?xml version="1.0" encoding="UTF-8" standalone="no"?>  <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"     "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">  <svg width="%d" height="%d"     xmlns="http://www.w3.org/2000/svg" version="1.1">  """ % (width, height)      def rgba_image_to_svg_pixels(im):      s = io.StringIO()      s.write(svg_header(*im.size))        width, height = im.size      for x in range(width):          for y in range(height):              here = (x, y)              rgba = im.getpixel(here)              if not rgba[3]:                  continue              s.write(                  """  <rect x="%d" y="%d" width="1" height="1" style="fill:rgb%s; fill-opacity:%.3f; stroke:none;" />\n"""                  % (x, y, rgba[0:3], float(rgba[3]) / 255))          print("Converting pixels: " + str(x * 100 / width) + "%")      s.write("""</svg>\n""")      return s.getvalue()      def joined_edges(assorted_edges, keep_every_point=False):      pieces = []      piece = []      directions = deque([          (0, 1),          (1, 0),          (0, -1),          (-1, 0),      ])      while assorted_edges:          if not piece:              piece.append(assorted_edges.pop())          current_direction = normalize(direction(piece[-1]))          while current_direction != directions[2]:              directions.rotate()          for i in range(1, 4):              next_end = add_tuple(piece[-1][1], directions[i])              next_edge = (piece[-1][1], next_end)              if next_edge in assorted_edges:                  assorted_edges.remove(next_edge)                  if i == 2 and not keep_every_point:                      # same direction                      piece[-1] = (piece[-1][0], next_edge[1])                  else:                      piece.append(next_edge)                  if piece[0][0] == piece[-1][1]:                      if not keep_every_point and normalize(direction(                              piece[0])) == normalize(direction(piece[-1])):                          piece[-1] = (piece[-1][0], piece.pop(0)[1])                          # same direction                      pieces.append(piece)                      piece = []                  break          else:              raise Exception("Failed to find connecting edge")      return pieces      def rgba_image_to_svg_contiguous(im, keep_every_point=False):        # collect contiguous pixel groups        adjacent = ((1, 0), (0, 1), (-1, 0), (0, -1))      visited = Image.new("1", im.size, 0)        color_pixel_lists = {}        width, height = im.size      for x in range(width):          for y in range(height):              here = (x, y)              if visited.getpixel(here):                  continue              rgba = im.getpixel((x, y))              if not rgba[3]:                  continue              piece = []              queue = [here]              visited.putpixel(here, 1)              while queue:                  here = queue.pop()                  for offset in adjacent:                      neighbour = add_tuple(here, offset)                      if not (0 <= neighbour[0] <                              width) or not (0 <= neighbour[1] < height):                          continue                      if visited.getpixel(neighbour):                          continue                      neighbour_rgba = im.getpixel(neighbour)                      if neighbour_rgba != rgba:                          continue                      queue.append(neighbour)                      visited.putpixel(neighbour, 1)                  piece.append(here)                if not rgba in color_pixel_lists:                  color_pixel_lists[rgba] = []              color_pixel_lists[rgba].append(piece)          print("Converting image: " + str(round(x * 100 / width, 2)) + "%")      del adjacent      del visited        # calculate clockwise edges of pixel groups        edges = {          (-1, 0): ((0, 0), (0, 1)),          (0, 1): ((0, 1), (1, 1)),          (1, 0): ((1, 1), (1, 0)),          (0, -1): ((1, 0), (0, 0)),      }        color_edge_lists = {}        counter = 0      for rgba, pieces in color_pixel_lists.items():          for piece_pixel_list in pieces:              edge_set = set([])              for coord in piece_pixel_list:                  for offset, (start_offset, end_offset) in edges.items():                      neighbour = add_tuple(coord, offset)                      start = add_tuple(coord, start_offset)                      end = add_tuple(coord, end_offset)                      edge = (start, end)                      if neighbour in piece_pixel_list:                          continue                      edge_set.add(edge)              if not rgba in color_edge_lists:                  color_edge_lists[rgba] = []              color_edge_lists[rgba].append(edge_set)          counter = counter + 1          print("Calculating edges: " +                str(round(counter * 100 / len(color_pixel_lists.items()), 2)) +                "%")      del color_pixel_lists      del edges        # join edges of pixel groups        color_joined_pieces = {}        for color, pieces in color_edge_lists.items():          color_joined_pieces[color] = []          for assorted_edges in pieces:              color_joined_pieces[color].append(                  joined_edges(assorted_edges, keep_every_point))        s = io.StringIO()      s.write(svg_header(*im.size))        counter = 0      for color, shapes in color_joined_pieces.items():          for shape in shapes:              s.write(""" <path d=" """)              for sub_shape in shape:                  here = sub_shape.pop(0)[0]                  s.write(""" M %d,%d """ % here)                  for edge in sub_shape:                      here = edge[0]                      s.write(""" L %d,%d """ % here)                  s.write(""" Z """)              s.write(                  """ " style="fill:rgb%s; fill-opacity:%.3f; stroke:none;" />\n"""                  % (color[0:3], float(color[3]) / 255))          counter = counter + 1          print("Joining edges: " +                str(round(counter * 100 / len(color_joined_pieces.items()), 2)) +                "%")      s.write("""</svg>\n""")      return s.getvalue()      def png_to_svg(filename, contiguous=None, keep_every_point=None):      try:          im = Image.open(filename)      except IOError as e:          sys.stderr.write('%s: Could not open as image file\n' % filename)          sys.exit(1)      im_rgba = im.convert('RGBA')        if contiguous:          return rgba_image_to_svg_contiguous(im_rgba, keep_every_point)      else:          return rgba_image_to_svg_pixels(im_rgba)      if __name__ == "__main__":      parser = OptionParser()      parser.add_option(          "-p",          "--pixels",          action="store_false",          dest="contiguous",          help=          "Generate a separate shape for each pixel; do not group pixels into contiguous areas of the same colour",          default=True)      parser.add_option(          "-1",          "--one",          action="store_true",          dest="keep_every_point",          help=          "1-pixel-width edges on contiguous shapes; default is to remove intermediate points on straight line edges. ",          default=None)      (options, args) = parser.parse_args()    if (len(sys.argv)) < 2:      for file in os.listdir("."):          if file.endswith(".png"):              print("Converting " + file)              f = open(file.replace(".png", ".svg"), 'w')              f.write(                  png_to_svg(file,                             contiguous=options.contiguous,                             keep_every_point=options.keep_every_point))  else:      for file in sys.argv:          if file.endswith(".png"):              print("Converting " + file)              f = open(file.replace(".png", ".svg"), 'w')              f.write(                  png_to_svg(file,                             contiguous=options.contiguous,                             keep_every_point=options.keep_every_point))
复制代码


运行脚本文件:


python3 test.py test.png
复制代码


将会直接产出同名的 test.svg 文件,利用 vscode(安装 svg 预览控件)打开:



原理就是将原位图的像素进行遍历,转化成 SVG 的 Path 路径格式,每个位图元素块都会是单独的一个 Path 标签,如果不需要对某个单独元素块进行操作,也可以合并为一个 path 路径标签。


接下来,将转化好的 svg 文件进行压缩,压缩后体积会相应的减小,同时一些 path 也可以被合并,通过 npm 安装压缩软件 svgo:


npm install -g svgo
复制代码


执行压缩命令,test.svg 是源文件,my.svg 是压缩后的文件:


svgo test.svg -o my.svg
复制代码


得到压缩后的 svg:


<svg xmlns="http://www.w3.org/2000/svg" width="250"  viewBox="0 0 400 313.725">         <path  d="M231.828 11.305c-3.763 2.949-7.266 3.479-30.517 4.623-46.344 2.278-61.703 11.6-61.703 37.45v9.581l4.839-3.636c7.122-5.353 14.345-8.975 17.906-8.982 2.225-.005 1.454.883-2.652 3.051-8.485 4.482-31.488 27.939-35.476 36.176-9.856 20.362.264 32.59 30.95 37.395 10.341 1.619 13.209 3.617 11.781 8.208-5.166 16.617 80.367 23.977 87.191 7.503 2.614-6.311.889-11.626-5.131-15.81-2.802-1.948-9.967-7.7-15.923-12.784-14.324-12.226-19.669-14.14-31.915-11.43-4.296.951-4.944.731-4.127-1.399.812-2.117-.114-2.455-5.715-2.085-9.411.622-9.816-2.778-.483-4.057 5.39-.739 8.043-.415 9.634 1.176 1.428 1.428 4.214 1.925 7.969 1.421 7.532-1.01 14.472 2.028 25.819 11.301l9.177 7.5 8.078-1.812c24.986-5.605 33.798-15.992 30.135-35.52-4.175-22.251-53.429-34.124-83.234-20.063l-4.706 2.22 3.717-3.226c13.698-11.889 56.459-11.57 74.326.555 6.558 4.45 7.448 3.51 7.448-7.864 0-18.854-18.5-23.967-61.832-17.088-17.292 2.744-31.119 2.595-34.083-.369-1.105-1.105.531-1.381 5.19-.876 3.742.405 15.189-.734 25.438-2.531 10.249-1.796 22.072-3.266 26.274-3.266 9.076 0 10.213-3.562 4.056-12.699-4.358-6.466-6.887-7.008-12.431-2.663M215.737 130.9c6.031 2.521 7.046 6.169 2.405 8.653-7.504 4.016-17.052-2.06-12.003-7.639 3.538-3.909 2.844-3.836 9.598-1.014m-5.541 3.125c0 2.208.706 4.014 1.569 4.014.862 0 1.568-1.37 1.568-3.044 0-1.675-.706-3.481-1.568-4.015-.89-.549-1.569.768-1.569 3.045M5.839 203.529c-1.456 5.21-1.896 9.241-1.042 9.543.832.294 1.478 10.421 1.478 23.184v22.661l19.933-.439 19.933-.439 12.084-21.096c6.647-11.602 13.134-21.863 14.416-22.8 1.765-1.29 7.359-15.836 7.359-19.134 0-.274-6.686-.499-14.858-.499H50.284l-2.439 8.389c-1.342 4.614-2.02 9.482-1.508 10.817 1.026 2.672-8.309 22.482-9.862 20.929-1.831-1.831-.255-18.929 1.898-20.591 1.163-.899 2.926-4.649 3.918-8.334.992-3.685 2.194-7.715 2.67-8.955.722-1.883-2.223-2.255-17.868-2.255H8.359l-2.52 9.019m88.643-7.092c-4.02 1.937-8.873 9.28-10.389 15.72l-1.016 4.314h11.689c10.312 0 11.807-.37 12.685-3.138.995-3.134 2.585-3.951 4.316-2.219 2.318 2.317-2.36 10.062-6.077 10.062-2.643 0-4.275 1.231-5.337 4.024-2.064 5.43-2.083 5.388 2.517 5.388 3.889 0 4.479 5.745 1.167 11.373-1.871 3.178-3.952.753-3.083-3.593l.954-4.769-12.746.456-12.746.455-2.07 7.024c-4.424 15.015-1.162 17.292 24.767 17.284 26.011-.008 31.009-3.079 34.928-21.461.834-3.908.349-5.713-2.228-8.289l-3.294-3.294 5.343-5.044c6.691-6.316 8.977-16.391 5.072-22.35-2.821-4.306-36.497-5.778-44.452-1.943m55.95 7.444c-1.607 6.168-1.884 9.557-.81 9.915 1.024.341.046 6.455-2.623 16.408-4.903 18.284-5.207 22.736-1.789 26.155 3.537 3.536 22.107 3.427 26.064-.154 2.704-2.447 3.022-2.443 4.861.072 1.629 2.228 4.114 2.611 14.418 2.227l12.45-.465 2.273-9.33c1.484-6.092 1.716-9.516.668-9.865-2.218-.739 4.443-23.327 7.629-25.87 1.985-1.585 6.035-13.389 6.035-17.59 0-.481-6.896-.874-15.325-.874h-15.324l-3.73 13.725c-6.592 24.261-9.634 33.334-11.174 33.334-2.44 0-1.81-3.858 3.984-24.422 3.02-10.717 5.49-20.194 5.49-21.061 0-.948-6.105-1.576-15.327-1.576h-15.328l-2.442 9.371m112.181-4.261c-4.796 4.396-6.336 7.744-11.004 23.922-9.813 34.013-9.05 35.284 21.183 35.276 27.768-.008 33.534-3.39 37.222-21.83l.966-4.831h-26.969l-1.293 4.991c-1.424 5.496-5.081 7.938-5.054 3.375.009-1.582 1.088-6.405 2.397-10.719 1.309-4.314 3.093-10.49 3.965-13.726.914-3.391 2.556-5.882 3.878-5.882 2.679 0 2.718.208.953 4.996-.736 1.997-1.816 5.6-2.398 8.007l-1.06 4.375 13.715-.453 13.714-.454 3.341-11.765c1.839-6.471 3.819-13.706 4.401-16.078l1.058-4.314h-10.226c-8.044 0-10.226.502-10.226 2.353 0 1.294-.403 2.353-.896 2.353s-1.955-1.059-3.249-2.353c-5.034-5.034-27.917-3.201-34.418 2.757m65.074 4.261c-1.504 5.773-1.848 9.568-.897 9.885 2.306.769-3.529 22.871-6.473 24.519-1.361.762-3.653 5.694-5.095 10.961l-2.622 9.578h28.713l1.774-6.648c1.148-4.3 1.23-6.983.233-7.6-2.082-1.286.12-9.573 2.347-8.831.969.323 2.74 5.673 3.936 11.887l2.173 11.3 14.88-.446 14.881-.447 2.753-8.909c1.836-5.941 2.231-9.433 1.185-10.479-2.066-2.065 3.146-22.253 6.434-24.924 1.326-1.077 3.613-5.842 5.082-10.588l2.669-8.629h-27.769l-1.965 6.556c-1.45 4.842-1.497 6.711-.176 7.151 1.288.43 1.338 1.883.179 5.209-2.181 6.257-4.094 5.799-5.3-1.269-.553-3.235-1.671-8.53-2.485-11.765l-1.481-5.882h-30.534l-2.442 9.371m-112.089 36.903c-.261.863-1.513 5.303-2.784 9.867l-2.311 8.299 11.835-.455 11.835-.456 2.105-7.059c3.515-11.782 3.528-11.764-9.027-11.764-6.149 0-11.393.706-11.653 1.568m-17.951 42.353c0 1.294.706 2.353 1.569 2.353.862 0 1.568-1.059 1.568-2.353 0-1.294-.706-2.353-1.568-2.353-.863 0-1.569 1.059-1.569 2.353m-121.274.229c-.594.593-1.079 5.549-1.079 11.013v9.935h7.059c4.716 0 7.059-.671 7.059-2.023 0-1.176-1.806-1.997-4.314-1.961-4.168.06-4.319-.227-4.465-8.485-.14-7.955-1.693-11.046-4.26-8.479m17.745 9.967c0 8.715.485 10.981 2.353 10.981 1.867 0 2.353-2.266 2.353-10.981 0-8.714-.486-10.98-2.353-10.98-1.868 0-2.353 2.266-2.353 10.98m9.411-3.137c0 12.177 9.456 18.732 16.228 11.249 3.493-3.859 3.687-19.092.243-19.092-1.765 0-2.353 1.882-2.353 7.529 0 8.705-2.181 11.917-6.515 9.597-2.219-1.188-2.897-3.371-2.897-9.338 0-5.877-.577-7.788-2.353-7.788-1.777 0-2.353 1.917-2.353 7.843m27.432-1.6c2.167 3.434 3.941 8.375 3.941 10.981 0 3.165.781 4.737 2.353 4.737 1.525 0 2.353-1.528 2.353-4.342 0-2.388 1.765-6.939 3.921-10.113 4.579-6.738 4.736-7.506 1.535-7.506-1.312 0-3.19 1.765-4.173 3.922-.983 2.156-2.298 3.921-2.923 3.921s-2.293-1.765-3.706-3.921c-1.413-2.157-3.621-3.922-4.906-3.922-1.801 0-1.433 1.431 1.605 6.243m21.542 2.619c1.015 12.236 9.26 17.547 15.881 10.23 3.493-3.859 3.687-19.092.243-19.092-1.764 0-2.352 1.882-2.352 7.529 0 8.705-2.181 11.917-6.515 9.597-2.22-1.188-2.897-3.371-2.897-9.338 0-6.141-.539-7.788-2.547-7.788-2.137 0-2.429 1.428-1.813 8.862m23.183 2.036v11.063h7.843c5.261 0 7.844-.651 7.844-1.976 0-1.184-2.029-1.97-5.059-1.961-3.572.011-5.22-.792-5.605-2.73-.407-2.045.483-2.745 3.49-2.745 2.22 0 4.036-.706 4.036-1.569 0-.862-1.764-1.568-3.921-1.568-6.549 0-4.808-4.443 1.961-5.004 8.742-.723 7.117-3.553-2.353-4.098l-8.236-.474v11.062m33.855-8.834c-4.079 2.983-2.494 7.781 3.433 10.39 7.54 3.318 4.217 7.372-3.798 4.633-.992-.339-2.051.072-2.352.914-.825 2.3 7.059 4.556 11.779 3.371 5.827-1.463 6.039-9.856.285-11.3-2.122-.532-4.672-1.949-5.667-3.149-2.507-3.02 1.892-4.623 6.264-2.283 2.594 1.388 3.26 1.287 3.26-.495 0-4.216-8.461-5.549-13.204-2.081m28.89 8.916v10.981h6.147c9.758 0 15.815-6.318 9.687-10.105-.782-.483-1.025-2.395-.54-4.249 1.136-4.346-3.195-7.607-10.103-7.607h-5.191v10.98m23.53 0v10.981h6.274c4.076 0 6.275-.709 6.275-2.023 0-1.176-1.806-1.997-4.314-1.961-4.159.06-4.33-.26-4.784-8.957-.668-12.8-3.451-11.219-3.451 1.96m20.304-8.087c-2.416 1.956-3.572 4.574-3.572 8.087 0 9.948 12.212 14.654 19.073 7.35 9.723-10.35-4.406-24.421-15.501-15.437m26.868 1.24c-7.54 9.587 1.045 20.207 13.612 16.839 4.862-1.303 5.249-11.163.424-10.807-4.346.32-5.861 2.278-3.124 4.038 2.027 1.303 2.022 1.667-.036 2.989-3.051 1.96-8.465-1.512-9.118-5.848-.677-4.496 5.425-8.61 9.52-6.418 3.969 2.124 7.98-1.06 4.282-3.399-4.707-2.976-12.149-1.729-15.56 2.606m-15.121 2.025c5.815 6.425-2.308 15.742-8.407 9.643-4.05-4.05-4.068-5.573-.115-9.527 3.899-3.898 5.085-3.915 8.522-.116m-44.6.901c0 1.307-1.395 2.353-3.137 2.353-1.743 0-3.138-1.046-3.138-2.353 0-1.307 1.395-2.353 3.138-2.353 1.742 0 3.137 1.046 3.137 2.353m1.363 7.595c2.196 2.647.744 4.169-3.978 4.169-2.614 0-3.66-.896-3.66-3.137 0-3.647 4.916-4.311 7.638-1.032" />    </svg>
复制代码


这里我们将多个 path 路径合并为一个,如果不想使用本地的代码脚本进行转化和压缩,也可以利用线上对应的网络工具,转化 svg:https://www.pngtosvg.com/ 压缩 svg: https://jakearchibald.github.io/svgomg/


线上转化效果和本地转化效果大同小异。

SVG 交互效果

事实上,直接将上面的代码放到页面中,就可以直接使用了,这里通过指定 svg 的 viewBox 属性里面的 4 个坐标来标定 svg 图片的显示区域,也就是我们理解的“画布”,然后通过控制 width 属性来实现等比的扩大和缩小,非常方便,效果是这样的:



除了分辨率能够适应屏幕显得更加精细,其他的地方和传统 png 好像没有什么不同?那么就来点不一样的吧,svg 可以通过 css 样式来实现“动画”特效,比如描边:


<svg xmlns="http://www.w3.org/2000/svg" width="250"  viewBox="0 0 400 313.725">         <path  class="path" stroke-opacity="0.2" stroke-width="7" stroke="black"   d="M231.828 11.305c-3.763 2.949-7.266 3.479-30.517 4.623-46.344 2.278-61.703 11.6-61.703 37.45v9.581l4.839-3.636c7.122-5.353 14.345-8.975 17.906-8.982 2.225-.005 1.454.883-2.652 3.051-8.485 4.482-31.488 27.939-35.476 36.176-9.856 20.362.264 32.59 30.95 37.395 10.341 1.619 13.209 3.617 11.781 8.208-5.166 16.617 80.367 23.977 87.191 7.503 2.614-6.311.889-11.626-5.131-15.81-2.802-1.948-9.967-7.7-15.923-12.784-14.324-12.226-19.669-14.14-31.915-11.43-4.296.951-4.944.731-4.127-1.399.812-2.117-.114-2.455-5.715-2.085-9.411.622-9.816-2.778-.483-4.057 5.39-.739 8.043-.415 9.634 1.176 1.428 1.428 4.214 1.925 7.969 1.421 7.532-1.01 14.472 2.028 25.819 11.301l9.177 7.5 8.078-1.812c24.986-5.605 33.798-15.992 30.135-35.52-4.175-22.251-53.429-34.124-83.234-20.063l-4.706 2.22 3.717-3.226c13.698-11.889 56.459-11.57 74.326.555 6.558 4.45 7.448 3.51 7.448-7.864 0-18.854-18.5-23.967-61.832-17.088-17.292 2.744-31.119 2.595-34.083-.369-1.105-1.105.531-1.381 5.19-.876 3.742.405 15.189-.734 25.438-2.531 10.249-1.796 22.072-3.266 26.274-3.266 9.076 0 10.213-3.562 4.056-12.699-4.358-6.466-6.887-7.008-12.431-2.663M215.737 130.9c6.031 2.521 7.046 6.169 2.405 8.653-7.504 4.016-17.052-2.06-12.003-7.639 3.538-3.909 2.844-3.836 9.598-1.014m-5.541 3.125c0 2.208.706 4.014 1.569 4.014.862 0 1.568-1.37 1.568-3.044 0-1.675-.706-3.481-1.568-4.015-.89-.549-1.569.768-1.569 3.045M5.839 203.529c-1.456 5.21-1.896 9.241-1.042 9.543.832.294 1.478 10.421 1.478 23.184v22.661l19.933-.439 19.933-.439 12.084-21.096c6.647-11.602 13.134-21.863 14.416-22.8 1.765-1.29 7.359-15.836 7.359-19.134 0-.274-6.686-.499-14.858-.499H50.284l-2.439 8.389c-1.342 4.614-2.02 9.482-1.508 10.817 1.026 2.672-8.309 22.482-9.862 20.929-1.831-1.831-.255-18.929 1.898-20.591 1.163-.899 2.926-4.649 3.918-8.334.992-3.685 2.194-7.715 2.67-8.955.722-1.883-2.223-2.255-17.868-2.255H8.359l-2.52 9.019m88.643-7.092c-4.02 1.937-8.873 9.28-10.389 15.72l-1.016 4.314h11.689c10.312 0 11.807-.37 12.685-3.138.995-3.134 2.585-3.951 4.316-2.219 2.318 2.317-2.36 10.062-6.077 10.062-2.643 0-4.275 1.231-5.337 4.024-2.064 5.43-2.083 5.388 2.517 5.388 3.889 0 4.479 5.745 1.167 11.373-1.871 3.178-3.952.753-3.083-3.593l.954-4.769-12.746.456-12.746.455-2.07 7.024c-4.424 15.015-1.162 17.292 24.767 17.284 26.011-.008 31.009-3.079 34.928-21.461.834-3.908.349-5.713-2.228-8.289l-3.294-3.294 5.343-5.044c6.691-6.316 8.977-16.391 5.072-22.35-2.821-4.306-36.497-5.778-44.452-1.943m55.95 7.444c-1.607 6.168-1.884 9.557-.81 9.915 1.024.341.046 6.455-2.623 16.408-4.903 18.284-5.207 22.736-1.789 26.155 3.537 3.536 22.107 3.427 26.064-.154 2.704-2.447 3.022-2.443 4.861.072 1.629 2.228 4.114 2.611 14.418 2.227l12.45-.465 2.273-9.33c1.484-6.092 1.716-9.516.668-9.865-2.218-.739 4.443-23.327 7.629-25.87 1.985-1.585 6.035-13.389 6.035-17.59 0-.481-6.896-.874-15.325-.874h-15.324l-3.73 13.725c-6.592 24.261-9.634 33.334-11.174 33.334-2.44 0-1.81-3.858 3.984-24.422 3.02-10.717 5.49-20.194 5.49-21.061 0-.948-6.105-1.576-15.327-1.576h-15.328l-2.442 9.371m112.181-4.261c-4.796 4.396-6.336 7.744-11.004 23.922-9.813 34.013-9.05 35.284 21.183 35.276 27.768-.008 33.534-3.39 37.222-21.83l.966-4.831h-26.969l-1.293 4.991c-1.424 5.496-5.081 7.938-5.054 3.375.009-1.582 1.088-6.405 2.397-10.719 1.309-4.314 3.093-10.49 3.965-13.726.914-3.391 2.556-5.882 3.878-5.882 2.679 0 2.718.208.953 4.996-.736 1.997-1.816 5.6-2.398 8.007l-1.06 4.375 13.715-.453 13.714-.454 3.341-11.765c1.839-6.471 3.819-13.706 4.401-16.078l1.058-4.314h-10.226c-8.044 0-10.226.502-10.226 2.353 0 1.294-.403 2.353-.896 2.353s-1.955-1.059-3.249-2.353c-5.034-5.034-27.917-3.201-34.418 2.757m65.074 4.261c-1.504 5.773-1.848 9.568-.897 9.885 2.306.769-3.529 22.871-6.473 24.519-1.361.762-3.653 5.694-5.095 10.961l-2.622 9.578h28.713l1.774-6.648c1.148-4.3 1.23-6.983.233-7.6-2.082-1.286.12-9.573 2.347-8.831.969.323 2.74 5.673 3.936 11.887l2.173 11.3 14.88-.446 14.881-.447 2.753-8.909c1.836-5.941 2.231-9.433 1.185-10.479-2.066-2.065 3.146-22.253 6.434-24.924 1.326-1.077 3.613-5.842 5.082-10.588l2.669-8.629h-27.769l-1.965 6.556c-1.45 4.842-1.497 6.711-.176 7.151 1.288.43 1.338 1.883.179 5.209-2.181 6.257-4.094 5.799-5.3-1.269-.553-3.235-1.671-8.53-2.485-11.765l-1.481-5.882h-30.534l-2.442 9.371m-112.089 36.903c-.261.863-1.513 5.303-2.784 9.867l-2.311 8.299 11.835-.455 11.835-.456 2.105-7.059c3.515-11.782 3.528-11.764-9.027-11.764-6.149 0-11.393.706-11.653 1.568m-17.951 42.353c0 1.294.706 2.353 1.569 2.353.862 0 1.568-1.059 1.568-2.353 0-1.294-.706-2.353-1.568-2.353-.863 0-1.569 1.059-1.569 2.353m-121.274.229c-.594.593-1.079 5.549-1.079 11.013v9.935h7.059c4.716 0 7.059-.671 7.059-2.023 0-1.176-1.806-1.997-4.314-1.961-4.168.06-4.319-.227-4.465-8.485-.14-7.955-1.693-11.046-4.26-8.479m17.745 9.967c0 8.715.485 10.981 2.353 10.981 1.867 0 2.353-2.266 2.353-10.981 0-8.714-.486-10.98-2.353-10.98-1.868 0-2.353 2.266-2.353 10.98m9.411-3.137c0 12.177 9.456 18.732 16.228 11.249 3.493-3.859 3.687-19.092.243-19.092-1.765 0-2.353 1.882-2.353 7.529 0 8.705-2.181 11.917-6.515 9.597-2.219-1.188-2.897-3.371-2.897-9.338 0-5.877-.577-7.788-2.353-7.788-1.777 0-2.353 1.917-2.353 7.843m27.432-1.6c2.167 3.434 3.941 8.375 3.941 10.981 0 3.165.781 4.737 2.353 4.737 1.525 0 2.353-1.528 2.353-4.342 0-2.388 1.765-6.939 3.921-10.113 4.579-6.738 4.736-7.506 1.535-7.506-1.312 0-3.19 1.765-4.173 3.922-.983 2.156-2.298 3.921-2.923 3.921s-2.293-1.765-3.706-3.921c-1.413-2.157-3.621-3.922-4.906-3.922-1.801 0-1.433 1.431 1.605 6.243m21.542 2.619c1.015 12.236 9.26 17.547 15.881 10.23 3.493-3.859 3.687-19.092.243-19.092-1.764 0-2.352 1.882-2.352 7.529 0 8.705-2.181 11.917-6.515 9.597-2.22-1.188-2.897-3.371-2.897-9.338 0-6.141-.539-7.788-2.547-7.788-2.137 0-2.429 1.428-1.813 8.862m23.183 2.036v11.063h7.843c5.261 0 7.844-.651 7.844-1.976 0-1.184-2.029-1.97-5.059-1.961-3.572.011-5.22-.792-5.605-2.73-.407-2.045.483-2.745 3.49-2.745 2.22 0 4.036-.706 4.036-1.569 0-.862-1.764-1.568-3.921-1.568-6.549 0-4.808-4.443 1.961-5.004 8.742-.723 7.117-3.553-2.353-4.098l-8.236-.474v11.062m33.855-8.834c-4.079 2.983-2.494 7.781 3.433 10.39 7.54 3.318 4.217 7.372-3.798 4.633-.992-.339-2.051.072-2.352.914-.825 2.3 7.059 4.556 11.779 3.371 5.827-1.463 6.039-9.856.285-11.3-2.122-.532-4.672-1.949-5.667-3.149-2.507-3.02 1.892-4.623 6.264-2.283 2.594 1.388 3.26 1.287 3.26-.495 0-4.216-8.461-5.549-13.204-2.081m28.89 8.916v10.981h6.147c9.758 0 15.815-6.318 9.687-10.105-.782-.483-1.025-2.395-.54-4.249 1.136-4.346-3.195-7.607-10.103-7.607h-5.191v10.98m23.53 0v10.981h6.274c4.076 0 6.275-.709 6.275-2.023 0-1.176-1.806-1.997-4.314-1.961-4.159.06-4.33-.26-4.784-8.957-.668-12.8-3.451-11.219-3.451 1.96m20.304-8.087c-2.416 1.956-3.572 4.574-3.572 8.087 0 9.948 12.212 14.654 19.073 7.35 9.723-10.35-4.406-24.421-15.501-15.437m26.868 1.24c-7.54 9.587 1.045 20.207 13.612 16.839 4.862-1.303 5.249-11.163.424-10.807-4.346.32-5.861 2.278-3.124 4.038 2.027 1.303 2.022 1.667-.036 2.989-3.051 1.96-8.465-1.512-9.118-5.848-.677-4.496 5.425-8.61 9.52-6.418 3.969 2.124 7.98-1.06 4.282-3.399-4.707-2.976-12.149-1.729-15.56 2.606m-15.121 2.025c5.815 6.425-2.308 15.742-8.407 9.643-4.05-4.05-4.068-5.573-.115-9.527 3.899-3.898 5.085-3.915 8.522-.116m-44.6.901c0 1.307-1.395 2.353-3.137 2.353-1.743 0-3.138-1.046-3.138-2.353 0-1.307 1.395-2.353 3.138-2.353 1.742 0 3.137 1.046 3.137 2.353m1.363 7.595c2.196 2.647.744 4.169-3.978 4.169-2.614 0-3.66-.896-3.66-3.137 0-3.647 4.916-4.311 7.638-1.032" />    </svg>
复制代码


这里我们为 path 属性加上伪类,同时通过 stroke 属性为 logo 加上一层外边框,透明度为 0.2,宽度为 7 个像素,接着,编写关键帧动画:


@keyframes pinap {    to {      stroke-dashoffset: 0;    }    0% {fill-opacity: 0; }       100% {fill-opacity: 1;    filter: drop-shadow(0px 0px 2px var(--logo-color));}     }
复制代码


页面加载时,指定 stroke-dasharray 属性进行描边的路径遍历,同时将 logo 本体的颜色透明度由 0 至 1 进行递增操作:



如果觉得意犹未尽,可以利用 hover 属性,将鼠标对 Logo 进行悬停动作时再触发一遍特效:


path.path:hover{  stroke-dasharray: 1000;    stroke-dashoffset: 1000;    animation: dash 3s linear forwards;    /* fill:white; */    fill-opacity: 1;  }
复制代码


还记得之前对于网站“暗黑模式”的实验吗?利用CSS3自定义属性来为网站添加“暗黑模式”(暗色模式/DarkMode) 当时我们使用了自定义属性,切换暗黑模式的同时切换另外一张暗色的 Logo 达到明亮和暗黑的效果,成本就是需要一明一暗两张图片配合使用,而现在,不需要多余的图片,只需要通过简单的自定义颜色即可:


:root{--logo-color:#2b2b2b}    path.path{      fill:var(--logo-color);  }
复制代码


svg 的 fill 属性可以直接渲染图片颜色:



简单而又方便,还等什么?抛弃落伍的 PNG 吧。


配合滤镜,还可以打造霓虹灯特效:


filter: drop-shadow(0px 0px 2px var(--logo-color));
复制代码



结语:“旧时王谢堂前燕,飞入寻常百姓家”,通过淘汰落后产能、上大压小、加强技术革新,我们可以利用 SVG 技术打造成本更低,扩展性更高的图像展示方案,何乐而不为?最后,奉上演示项目地址:https://github.com/zcxey2911/svg_website_logo,博君一晒。


原文转载自「刘悦的技术博客」 https://v3u.cn/a_id_207

发布于: 刚刚阅读数: 2
用户头像

专注技术,凝聚意志,解决问题 v3u.cn 2020.12.21 加入

还未添加个人简介

评论

发布
暂无评论
Logo小变动,心境大不同,SVG矢量动画格式网站Logo图片制作与实践教程(Python3)