The introduction

In front-end development, we occasionally use SVG. It may be used to draw ICONS, or it may be used to do some image manipulation. This article will introduce some SVG filters and image processing practices in the project, hoping to help you quickly understand the combination and use of SVG filters.

First, what did we do

This is an SVG based effect. A finished diagram consists of 25 fragments. Each time the user acquires a new fragment, it is highlighted and merged with existing ones into a larger image. Do not proceed to the next round of collection until all are collected.

Why SVG?

In fact, looking at our current interface, a lot of students will feel that div+ CSS can do a similar effect. However, THE choice of SVG was based on the following considerations:

  1. Considering that in the later stage, if we need to support irregular jigsaw fragment graph 🧩, div will be difficult. Canvas and SVG can both do this, but at this time, SVG may be easier to create some effects through filters. It is also feasible to convert SVG to Canvas in the later stage. After all, the path calculation method can be reused.
  2. SVG filter effect carries out more picture processing, we are engaged in activities, general visual requirements are relatively rich effects, canvas operation is more complex, SVG filter is relatively easy to use.

So what are we talking about?

This article will not go through the various attributes of SVG. Most of these documents are probably more professional. We are more likely to help you sort out some cognitive frameworks for making SVG from the rich array of SVG tags and attributes through some practical cases. My case mainly involves:

  1. The use of D in path, that is, how to draw a custom graph;
  2. Filter overlay example, to help you better understand the combination of SVG filter method;
  3. FeColorMatarix filter practice. This filter is arguably the most useful image pixel manipulation filter. Basically probably helps us to complete most of the image processing effects.

This article has been synchronized toLOFTER technical team public accountWelcome to watch.

SVG view and adaptation

Why do we get back to basics, because there’s an interesting trick in views, and I’ll talk a little bit more about it.

Let’s look at the viewBox property of SVG

ViewBox Container size

ViewBox =”x, y, width, height”

ViewBox = xy in “x, y, width, height”, indicating the starting position of the view. Xy can be negative (width, height not). If we set xy to negative and move the entire canvas to the bottom right, we can achieve a padding-like effect without having to modify the completed path inside! This will be a good protection if you have some external glow effect that appears outside 0,0.

PreserveAspectRatio Specifies whether to enforce uniform scaling

Parameter: preserveAspectRatio=”xMidYMid meet”

  1. XMidYMid: indicates the alignment position. Other parameters include xMin, xMid, xMax, YMin, YMid, and YMax.
  2. Meet: clipping position, other parameters include slice;
  3. PreserveAspectRatio =” None “: does not set the width to height ratio of the stretch;

PreserveAspectRatio, by the way, since SVG automatically scales, you can learn about it and help us do some screen adaptation.

Drawing graphics

SVG has many labels for drawing graphics: Line for straight lines, rect for squares, and Circle for circles. These documents can get the full picture, almost no special introduction. Attached document address developer.mozilla.org/zh-CN/docs/…

This article will focus on the path description method of path. Because of the degree of freedom, it also introduces complexity.

The path tag

So that’s where we’re going to focus on the D property, which is how do we draw paths

D property – Draws a path

Let’s start with a simple example

<path
  d="M0,0 h100 v100 h-100 z"
/>
Copy the code

Highlight: Each path is separated by a space or whitespace, with a comma for x and y for coordinates. Don’t be confused by the long path you see; analyze it one by one to get the results.

Let’s take a look at the steps to draw the image in the code above:

  1. M0,0 moved to x equals 0,y equals 0
  2. H100 Draw a horizontal line of length 100 with the end point x=100 and y=0
  3. V100 Draw a line of length 100 longitudinally, starting at x=100,y=0, and ending at x=100,y=100
  4. H-100 Horizontally draw a line of length -100. -100 means drawn from right to left. That is, the beginning of the line is x=100,y=100, and the end is x=0,y=100
  5. Z closed graph, now you can imagine that this actually draws a square, as shown below:

M, h, v, z have been used in the above examples. What are the total path descriptions?

  1. M/ M – Moves to each position;
  2. H/ H – draw a horizontal line;
  3. V/ V – draw a vertical line;
  4. L/ L – Draw a line to x,y;
  5. C/ C – Draw a Bezier curve;
  6. A/ A – Draw an arc;
  7. Z-closure;

You can see there’s upper case and lower case. Uppercase represents absolute coordinates, lowercase represents coordinates relative to the previous point. Let’s say we start at x equals 100,y equals 100 and draw a line of length 100, h100 in lower case, H200 in upper case.

Fill-rule =”evenodd”

Fill-rule is also a property we need to care about when drawing graphs, especially if there are intersecting paths. Hollow out is the key point is how to determine the content of the internal or external, look at this article detailed introduction, can help you to understand: www.zhangxinxu.com/wordpress/2…

Draw the highlighted area

Now that we’ve combed through the fundamentals, let’s get down to business. Take a look at the renderings:

image.png

So here’s our title:

We know that the back-end data is

[[1, 1, 1, 0, 1], [0, 0, 1, 0, 1], [0, 0, 1, 1, 0] to [0, 1, 1, 1, 0] to [0, 0, 1, 1, 1]]Copy the code

A two-dimensional array of. 1 means obtained and needs to be drawn as highlighted. 0 means not obtained and requires a white mask. Figure out how to draw this boundary path.

Problem solving begins:

  1. Each square has four linesAdd four lines of data to the array.
  2. Two adjacent squares need to remove the same line. Such asWhere B->D and D’->B’ are the same line, we remove both. The result is going to be zeroA bigger square.
  3. Repeat steps 1 and 2 to get an array of paths containing the entire puzzle.
  4. Take any line from the array.
  5. Find another line whose starting point is equal to its end point and repeat the process until the next line cannot be found, at which point the end point of the last line must be equal to the beginning of the first line. Mark Z and close the current path.
  6. Check whether the array is empty. If not, repeat steps 4 and 5. If yes, the path path has been completed.

Follow the steps above to get a complete path, we will continue to explain how to use fill to fill the mask and the image and filter to achieve the glow effect.

The fill to fill

Once we’ve mapped the path, we’re going to fill it in.

Color color

Fill =”# FFFFFF “is a simple and intuitive color to fill, but I’ll go over it. The mask can be filled with color and transparency.

The pattern design

Pattern lets you use images as fillers and some SVG content as fillers, which is very useful. You can use this for highlights. Can also be directly transparent, this is to achieve the right to follow up the internal and external light filter.

1. Add images

<pattern id="puzzleImage" x="0" y="0" patternUnits="userSpaceOnUse" primitiveUnits="userSpaceOnUse" width="495" height="1237">
  <image x="0" y="0" width="495" height="1237" xlink:href="https://lofter.lf127.net/1645514196505/puzzle.jpg?imageView&crop=0_0_495_1237#pattern" />
</pattern>
Copy the code

PatternUnits have the following properties to focus on: userSpaceOnUse and objectBoundingBox. UserSpaceOnUse represents the user-space viewBox on the outermost SVG. ObjectBoundingBox is relative to the current element.

We use userSpaceOnUse to make sure that the images are filled in exactly the same way by stacking multiple layers of images.

2. Combine other SVG content

<pattern id="puzzleImage" x="0" y="0" patternUnits="userSpaceOnUse" primitiveUnits="userSpaceOnUse" width="495" height="1237">
  <image x="0" y="0" width="495" height="1237" xlink:href="https://lofter.lf127.net/1645514196505/puzzle.jpg?imageView&crop=0_0_495_1237#pattern" />
  <line x1="99" y1="0" x2="99" y2="1237" stroke-width="1" stroke="#fff" />
  <line x1="198" y1="0" x2="198" y2="1237" stroke-width="1" stroke="#fff" />
  <line x1="297" y1="0" x2="297" y2="1237" stroke-width="1" stroke="#fff" />
</pattern>
Copy the code

In addition to images, other SVG tags can be added to pattern. For example, as shown in the image above, we also put white dividers into pattern, so that the filled images are automatically marked with white dividers. This is how we fill in the highlights.

Filter combination demonstration

Jigsaw highlight filter demo

Let me look at the next highlight effect, an SVG filter that glows inside and out.

image.png

Its implementation code is as follows:

<filter id="puzzleNormalShadow" x="-50%" y="-50%" width="200%" height="200%"> <feGaussianBlur in="SourceAlpha" stdDeviation="13" /> <feMorphology operator="dilate" radius="6" result="offsetblur" /> <feFlood flood-color="#ffe4b1" <feComposite result="outblur" in2="offsetblur" operator="in" /> <feFlood flood-color="#ffe4b1" Flood -opacity="0.75" /> <feComposite in2="SourceGraphic" operator="out" /> <feGaussianBlur stdDeviation="13" /> <feComposite result="inblur" in2="SourceGraphic" operator="atop" /> <feMerge> <feMergeNode in="outblur" /> <feMergeNode in="inblur" /> </feMerge> </filter>Copy the code

This is a typical COMBINATION of SVG filters, but how do they work together? We can take a look at the GIF below and use our analysis to understand.

No title – 1. GIF

Now let’s look at each filter one by one to deepen our understanding:

  1. <feGaussianBlur in="SourceAlpha" stdDeviation="13" /> The function of feGaussianBlur filter is blur, in=”SourceAlpha” indicates the effect on the transparent area, stdDeviation=”13″Indicates the degree of ambiguity
  2. <feMorphology operator="dilate" radius="6" result="offsetblur" /> FeMorphology is for making things bigger or smaller. operator=”dilate”Expansion.result=”offsetblur”Result indicates that the record product isoffsetblurYou can use it for the purposes specified later.
  3. < feFlood flood - color = "# ffe4b1" flood - opacity = "0.75" / > feFloodRepresents the fill color
  4. <feComposite result="outblur" in2="offsetblur" operator="in" /> feComposite To merge images, yesinAnd **in2 **2 attributes. Among them,inThe product of the previous step is automatically used by default, **in2=”offsetblur”** the product of the previous step is used.
  5. At this point, the effect of external light production is completed.
  6. The following 4 steps are for the effect of internal light production, the basic principle and external light is the same, small friends can combine the previous steps to imagine how to make.
  7. Finally:<feMerge>Merging the outer glow with the inner glow,At this point, internal and external luminescence can be used in different colors and effects.

Although internal and external glow is a very common effect in our eyes, it requires a combination of multiple filters to achieve it. Thinking about this example over and over again will help you understand how the filters are put together and figure out what to think about when you make them yourself, rather than just searching for the ones you already have.

FeColorMatrix Color matrix filter

What is a feColorMatrix?

FeColorMatrix is an SVG filter whose main function is to convert each color on the image to another color by a computational method. Like red to yellow, or red to redder, green to greener, it can be done. You can see that feColorMatrix is probably the most commonly used image processing filter.

Let’s look at the properties of a feColorMatrix:

<feColorMatrix in="SourceGraphic" type="matrix" id="feColorMatrix" values="0.2 0.2 0.2 0.3 0.2 0.2 0.2 0.3 0.17 0.17 0 0 0 0 0 1 0" />Copy the code

The most important of these is **values ** which is our transformation matrix.

How is the matrix computed?

The calculation formula is as follows:

Let’s take a look at each section:

  1. The $on the far leftIt’s every pixel in the image,RGBA value of the original image;
  2. isValues attribute in feColorMatrix;
  3. isImage RGBA value after processing;

And finally, I want you to take a few more minutes, go back to our formula, and understand it. Only with understanding can we carry out our actual operation.

To do a gradient mapping effect!

The result is shown below, the left is the finished image, and the right is the original image. Let’s use feColorMatrix.

image.png

When we get this effect, we usually communicate with visual students first to understand how they make this effect with PS. After communication, we know that they have done two steps:

  1. Make the picture black and white;
  2. Use a purple one for gradient mapping. The configuration on PS is shown as follows:

Make the picture black and white

Black and white means only black and white, and only white, gray and black on the graph. In fact, the method is to add the RGB 3 channels of color and then divide. For example, RGB (30, 60, 90) becomes RGB (60,60,60). Do this with each dot, and the image becomes black and white. The value of feColorMatrix should be:

0.333 0.333 0.333 0 0 0 0 0 0.333 0.333 0.333 0 0 0 0 0 0 0 0 0 0 0 0 0 0Copy the code

That is, by setting the value of each channel to R * 1/3 + G * 1/3 + B * 1/3 to achieve the change of black and white.

Understanding gradient mapping

A gradient map is just a special go black and white. Fill each channel with a transition color from the specified color to white with changes from 0 to 255.

Let’s say we have a value of zeroRgba (115115157, 1)Purple to white to transition. Taking the calculation of R channel as an example, let’s take a look at the calculation process:

  1. The gradient ranges from 115(purple r-channel value) to 255(white R-channel value) equal to 140. The original image varies between 0(black) and 255(white) equals 255.So it follows thatRR (refer to the formula above) = Target transition interval/original transition interval = 140/255.
  2. Also consider black and white first, i.e. multiply by 1/3, rR(refer to the formula above) = 140 / (255 * 3). And then we get the first row is 1, 2140 / (255 * 3) 140 / (255 * 3) 140 / (255 * 3) 0 X. X, see the next one.
  3. Since we are transitioning from **115(purple)**, X is the base value, i.eX = 115 / 255. The end result is that140 / (255 * 3) 140 / (255 * 3) 140 / (255 * 3) 0 115/255
  4. Calculated for0.1830065359477124 0.1830065359477124 0.1830065359477124 0 0.45098039215686275

The transformation matrix of G and B channels can be calculated by using the same method.

The final generated result is as follows:

<feColorMatrixi in="SourceGraphic" type="matrix" values=" 0.1830065359477124 0.1830065359477124 0.1830065359477124 0 0.45098039215686275 0.1830065359477124 0.1830065359477124 0.1830065359477124 0 0.45098039215686275 0.12810457516339868 0.12810457516339868 0.12810457516339868 0 0.615686274509804 0 0 10"Copy the code

This calculation process can also be carded into JS functions for easy use next time. The calculation process is roughly as follows:

var originMax = 255;
var total = originMax * 3;

var white = 255;
var r = rInput.value;
var g = gInput.value;
var b = bInput.value;

var rp = (white - r) / total;
var gp = (white - g) / total;
var bp = (white - b) / total;

var matrix = `
  ${rp} ${rp} ${rp} 0 ${r / originMax}
  ${gp} ${gp} ${gp} 0 ${g / originMax}
  ${bp} ${bp} ${bp} 0 ${b / originMax}
  0 0 0 1 0
`;
Copy the code

Compatibility Record

This is a record of the development of several compatibility problems, you can easily view ~

Q: image href or xlink:href, which should I use?

A: Xlink :href has better compatibility, recommended use. Lower versions of ios do not support href

Q: What if the left side glow looks cropped after feGaussianBlur makes the outer glow filter?

A: Add the following attributes to the filter tag x=”-50%” y=”-50%” width=”200%” height=”200%” to enlarge the scope of the lower filter

Q: How is feFlood not working in ios Safari?

A: Add x=”0″ y=”0″ width=”100%” height=”100%” to the feFlood label to clarify the scope of feFlood

The end of the

This development is also a process for the author to develop and use SVG. A number of SVG features are used in between. SVG itself has some convenience. Images can be quickly processed through preset filters. In most cases, using SVG filters to process images gives you faster results than canvas. Canvas needs to be loaded first and then processed. Generally, the process is long. However, SVG relies on the optimization of the browser itself, which is slightly insufficient on ios. Therefore, we will still consider using canvas. But it’s good enough to do some quick processing of images. Finally, you are welcome to leave a message to discuss, if you have any questions, you can communicate with us.