Author: Buddhist temple square stool elegant set of production

background

With the development, the operation of the title pictures on the event venue page needs online templating, and the self-developed guide material production platform is connected to Haitong-Creative Center. Through the ability of the platform, the material is templated, and a variety of scene-oriented and personalized materials are generated through configuration. However, the material template of the Creative Center is based on SVG, while the question pictures of the venue are basically output based on Photoshop(PS), and the source file is PSD. SVG is a vector graphics-oriented markup language, and PS is an image processing software centered on bitmap processing. In most cases, PS cannot directly export SVG files.

In order to connect the title drawing template of the venue to the production platform of shopping guide material and reduce the threshold for designers to use, we need to realize the function of directly converting PSD into SVG in the production platform of shopping guide material, online converting PSD into SVG, and then importing the title drawing into the creative center.

Graphics processing

In Photoshop, the pen tool is used to draw graphics.



For designers, the use of pen is a necessary skill, such as matting, drawing patterns, making ICONS, etc., are inseparable from the pen tool. The pen tool, also known as the path tool, outputs a vector image that, unlike a bitmap, ensures that the shape of the output pattern is not distorted by scaling.



SVG, or Scalable Vector Graphics, is itself a Vector graphics-oriented markup language, so information about graph paths in PSD can theoretically be mapped to SVG.


In SVG, there are many labels used to display graphics:


  • ellipse
  • circle
  • line
  • polyline
  • polygon
  • path


If you are exporting graphics directly in SVG, you may need to consider which label to use depending on the shape. For a circle, we think a little bit about circle tags, for a rectangle, we use rect, for a polygon, we use polygon, these tags allow us to draw the desired shape quickly and easily. However, if you want to convert graphics from PSD to SVG, it is difficult to select appropriate labels based on shape, which can complicate the implementation of the transformation.


Can we unify the drawing of different figures into one solution?


Yes, use the path tag. It is one of the most powerful of SVG’s basic shapes, providing a drawing syntax that allows you to create not only other basic shapes, but many more. No matter what shape the designer draws, as long as it is output with the pen tool, it will eventually be stored in the data format of path nodes. The graphic information obtained through PSD.js is actually a collection of graph path nodes.


Get path node


Using psd.js, you can obtain the graph path information in the following ways.


1const vectorMask = node.get('vectorMask'); 2vectorMask.parse(); 3const paths = vectorMask.export(); 4paths.forEach(path => { 5 console.log(path); // Path node data 6});Copy the code


Path is an object with several key fields:

field instructions
recordType The node type
numPoints Number of closed nodes
preceding Starting control point
anchor Path node coordinate point
leaving Terminal control point


recordType


RecordType Records the type of the node. For details about the type, see here. Search “Path Records”.

recordType instructions
0 The starting point
1 Closed Bezier curve point
2 Closed waypoint,precedingandleavingYou can ignore
4 Of a nonclosed Bezier curve
5 Non-closed waypoints,precedingandleavingYou can ignore


numPoints


Indicates the number of nodes in a continuous path. This field is used to determine where the path ends.


preceding/anchor/leaving


Preceding, Anchor, and leaving record the location information of the three control points relative to the PSD canvas in the path node. Control points corresponding to each field are shown as follows:



Converting path information


The data type object of the preceding, anchor, and leaving control points contains two fields, Horiz and Vert, corresponding to the position of x and Y coordinate points. But there is one thing to note here. Usually we use pixel distance to describe the position of a point, such as point A in the picture below:



The position of point A relative to the canvas is x: 10, y: 60.


However, the coordinate data of the control points of the path node in the PSD document are two unsigned floating point numbers, which are the ratio of the pixel distance relative to the origin in the upper left corner of the canvas to the width and height of the canvas, such as point A in the following figure:



The position of point A relative to the canvas can also be described as x: 0.05, y: 0.3.


To better export PSD path data to SVG, we need to perform a conversion of the positions of these control points, converting the proportional positions to pixel positions and converting unsigned floating-point numbers to symbolic floating-point numbers.


1// Convert an unsigned floating-point number to const signed =function(n) {
 3  let num = n;
 4  if(num > 0x8f) { 5 num = num - 0xff - 1; 6} 7 8return num;
 9};
10
11const getPathPosition = function(pathNode) { 12 const { 13 vert, 14 horiz 15 } = pathNode; 16, 17return {
18    x: signed(horiz),
19    y: signed(vert)
20  };
21}
22
23const parsePath = function(path, { width, height }) { 24 const { 25 preceding, 26 anchor, 27 leaving 28 } = path; 29 30 const precedingPos = this.getPathPosition(preceding); 31 const anchorPos = this.getPathPosition(anchor); 32 const leavingPos = this.getPathPosition(leaving); RelX and relY retain raw data in PSD. 35return {
36    preceding: {
37      relX: precedingPos.x,
38      relY: precedingPos.y,
39      x: Math.round(width * precedingPos.x),
40      y: Math.round(height * precedingPos.y)
41    },
42    anchor: {
43      relX: anchorPos.x,
44      relY: anchorPos.y,
45      x: Math.round(width * anchorPos.x),
46      y: Math.round(height * anchorPos.y)
47    },
48    leaving: {
49      relX: leavingPos.x,
50      relY: leavingPos.y,
51      x: Math.round(width * leavingPos.x),
52      y: Math.round(height * leavingPos.y)
53    }
54  };
55}
56
57const vectorMask = node.get('vectorMask'); 58vectorMask.parse(); 59const paths = vectorMask.export(); 60const convertedPath = [] 61paths.foreach (path => {6path => {6path => {6path => {6path => {6path => {6path => {6path => {6path => {6path => { recordType, numPoints } = path; 65 const { 66 preceding, 67 anchor, 68 leaving 69 } = parsePath(path, document); // ConvertedPath. push({72 preceding, 73 anchor, 74 leaving 75}); 76});Copy the code


Convert to the PATH tag of SVG


Follow the syntax of the PATH tag d attribute


 1const toPath = (paths) => {
 2  let head;
 3  const data = [];
 4  
 5  paths.forEach((path, index) => {
 6    const { preceding, anchor, leaving } = path;
 7    if (index < paths.length - 1) {
 8      if(index > 0) {// Middle node 9 data.push('${preceding.x}.${preceding.y} ${anchor.x}.${anchor.y} ${leaving.x}.${leaving.y}`); 10}else{// Record the first node, use 11 head = path when closing the path; 12 data.push(`M${anchor.x}.${anchor.y} C${leaving.x}.${leaving.y}`); 14 13}}else {
15      data.push(`${preceding.x}.${preceding.y} ${anchor.x}.${anchor.y} ${leaving.x}.${leaving.y} ${head.preceding.x}.${head.preceding.y} ${head.anchor.x}.${head.anchor.y}Z`); 16}}); 18 19return `<path d="${data.join(' ')}"/ > `; 20}Copy the code


Fill the shape with color


If the graph is filled with a solid color, it can be obtained as follows.


 1const getFillColor = function(node) {
 2  const solidColorData = node.get('solidColor');
 3  const clr = solidColorData['Clr ']; 4, 5return toHexColor([
 6    Math.round(clr['Rd ']),
 7    Math.round(clr['Grn ']),
 8    Math.round(clr['Bl '9]])); 10};Copy the code


Modify the previous toPath method.


 1const toPath = (paths, fill) => {
 2  let head;
 3  const data = [];
 4  
 5  paths.forEach((path, index) => {
 6    const { preceding, anchor, leaving } = path;
 7    if (index < paths.length - 1) {
 8      if(index > 0) {// Middle node 9 data.push('${preceding.x}.${preceding.y} ${anchor.x}.${anchor.y} ${leaving.x}.${leaving.y}`); 10}else{// Record the first node, use 11 head = path when closing the path; 12 data.push(`M${anchor.x}.${anchor.y} C${leaving.x}.${leaving.y}`); 14 13}}else {
15      data.push(`${preceding.x}.${preceding.y} ${anchor.x}.${anchor.y} ${leaving.x}.${leaving.y} ${head.preceding.x}.${head.preceding.y} ${head.anchor.x}.${head.anchor.y}Z`); 16}}); 18 19return `<path d="${data.join(' ')}" fill="${fill}"/ > `; 20}Copy the code


sample


Make a PSD document with graphics only in Photoshop



Exported SVG document:


1 <? xml version="1.0" encoding="UTF-8"? 2 > <! -- generated by lst-postman --> 3<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
 4  viewBox="0 0 750 300"
 5  enable-background="new 0 0 750 300"
 6  xml:space="preserve"
 7>
 8  
 9  <image x="0" y="0" width="750" height="300" overflow="visible" xlink:href="data:image/png; base64,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"></image>
10  <path d="M 246, 98 C351, 135 401, 55 422, 86 443, 117 464, 167 533, 125 602, 83 699, 115 636, 174 573, 233 408, 272 328, 245 248, 218 252, 171 144, 204 93, 220 122, 54 246, 98 Z" fill="#00ff15"></path>
11</svg>Copy the code


If you reap, reap the grain