Recently, I’ve been so engrossed in The Legend of Zelda: Breath of the Wild on The Nintendo Switch that my column has almost stopped. The question that every Zelda player has is, why is the game so much fun? ! Interestingly enough, the answer to this question seems to have something to do with why the front end is changing so fast, which gave me some new insights…

One aspect of zelda’s experience that has been widely praised is its intuitive open-world approach. In other words, if you can think of a way to do something in this game, you can almost do it that way. For example, if you see an apple hanging on a tree and you want to get it off, there are at least the following ways:

  • Cut down the tree and pick up the apple
  • Climb a tree, ride a horse or carry a box for your feet to reach the apple
  • Shoot the apple down with a bow and arrow
  • A fan or a bomb creates a shockwave that blows the apple down
  • Glide from the surrounding highlands to the apple trees
  • The fire set the tree alight and left the apples to roast

This freedom makes the adventure of the game full of surprises. There are often open, not unique, solutions to tricky organ puzzles. Coincidentally, my recent work has also had something to do with tinkering with various rendering mechanisms on the front end. When it comes to evaluating browsers in terms of freedom, it’s almost a Zelda-like open world.

Let’s use triangles as an example. Triangle as the simplest geometric figure, drawing it for any front-end students will not be a difficult thing. But how many technology solutions can draw a triangle in today’s front-end? The answer is a thousand flowers. Let’s start off step by step. The following routines can be divided into three categories according to the degree of discomfort:

  • 2B Play
  • Ordinary Play
  • Shame Play

2B Play

Let’s start with the easiest way to bully:

character

What could be an easier way to draw than to copy and paste a delta character? This is simply a Unicode special character in the form of ‘\ u25B3 ‘.

The picture

HTML

If we center a series of rectangles with uniformly increasing width vertically, do we get a triangle 😅

<div class="triangle">
  <div style="width: 1px; height: 1px;"></div>
  <div style="width: 2px; height: 1px;"></div>
  <div style="width: 3px; height: 1px;"></div>
  <div style="width: 4px; height: 1px;"></div>
  <! -... -->
</div>
Copy the code

Demo

Ordinary Play

If the above implementation feels too cynical, we can draw the same triangle with a slightly “normal” operation:

CSS

CSS is full of tricks and tricks, and this is probably the standard answer to many interview questions. We just need simple HTML:

<div class="triangle"></div>
Copy the code

With the magic change container border style:

.triangle {
  width: 0;
  height: 0;
  border-left: 50px solid transparent;
  border-right: 50px solid transparent;
  border-bottom: 100px solid red;
}
Copy the code

You can simulate a triangle. Demo

Icon Font

Using fonts as ICONS is also a cliche. You only need a font style configuration that looks something like this:

@font-face {
  font-family: Triangle;
  src: url(./triangle.woff) format("woff");
}

.triangle:before { content:"\t666" }
Copy the code

< I class=”triangle”>
inserts special characters with :before to render the corresponding icon font 😑Demo

SVG

Most of the time we’re used to using SVG as a static resource like images, but it’s not that complicated to write simple graphics in SVG by hand after a little understanding of its syntax:

<svg width="100" height="100">
  <polygon points="50, 0, 100100, 0100" style="fill: red;"/>
</svg>
Copy the code

Demo

Clip Path

SVG has a lot in common with CSS, but CSS, while better at styles, has long lacked the ability to “draw a shape.” Fortunately, the clip Path, recently added to the CSS specification, legitimately allows us to draw a wider variety of shapes in an SVG-like form. All it takes is something like this:

.triangle {
  width: 10px; height: 10px;
  background: red;
  clip-path: polygon(50% 0, 0 100%, 100% 100%);
}
Copy the code

How is this different from the familiar border routine? In addition to making the code more intuitive and concise, it also supports background image properties for drawn shapes, which unfortunately is mainly IE compatible. Demo

Canvas

None of the methods so far require writing JS code, which is somewhat underpaid. Good thing we have Canvas to do it with. All you need is a

tag with glue code like this:

const canvas = document.getElementById('canvas')
const ctx = canvas.getContext('2d')
ctx.beginPath()
ctx.fillStyle = 'red'
ctx.moveTo(50.0)
ctx.lineTo(0.100)
ctx.lineTo(100.100)
ctx.fill()
Copy the code

Demo

Shame Play

If this is still too formal for you, let’s explore the browser’s freedom scale in a few final ways:

CSS Houdini

The CSS Houdini got a lot of attention at the recent CSS conference. One of the major enhancements to CSS control is CSS Paint. In short, with this API, you can programmatically control the rendering process of an image through the Canvas wherever the CSS properties require the image.

Through CSS. PaintWorklet. AddModule API, we can define the paint used in the drawing canvas worklet:

<script>
  CSS.paintWorklet.addModule('/worklet.js')
</script>
Copy the code

The normal Canvas context is available in Paint Worklet:

class TrianglePainter {
  paint(ctx, geom, properties) {
	 const offset = geom.width
    ctx.beginPath()
    ctx.fillStyle = 'red'
    ctx.moveTo(offset / 2.0)
    ctx.lineTo(offset, offset)
    ctx.lineTo(0, offset)
    ctx.fill()
  }
}

registerPaint('triangle', TrianglePainter)
Copy the code

Once you’ve done that, you can use paint rules in your CSS:

.demo {
  width: 100px;
  height: 100px;
  background-image: paint(triangle);
}
Copy the code

We can also use CSS Variable to define parameters in the CSS of the form –triangle-size or –triangle-fill to control the canvas’s rendering, so that the canvas will automatically redraw when the parameters are updated. Combined with Animation, it also has a large imagination space in the field of special effects. While the final canvas is the aforementioned canvas, Houdini does bring more control over CSS-BASED rendering.

WebGL polygon

WebGL is fairly well supported by major browsers, but it’s still not a must-have technology for everyone in the front-end space. That may have something to do with its steep learning curve. Many students may have a misunderstanding about WebGL, that is, it is a SET of JS APIS like Canvas. In fact, when writing WebGL applications, in addition to writing JS glue code running in the CPU category, what is really executing on the GPU is the shader written in GLSL language. However, due to the complexity of the drawing library itself, the JS glue code is the absolute majority in the introductory example. With step-by-step computer graphics tutorials, it takes about a hundred lines of code to render even a single triangle. Due to space constraints, we will briefly summarize the key things that need to be done in this process as the following three steps:

  1. Write vertex shaders and slice shaders in GLSL language.
  2. Defines a vertex buffer to which data for each vertex of the triangle is passed.
  3. Do some preparation in our own render function. Call after loading the shader programdrawArrayAPI draws the data in the buffer.

At first glance, this process (Demo) controls just a more verbose canvas, other than 3D support, what’s the difference? We can see the difference in the last method.

WebGL styling functions

The above process is basically what every WebGL tutorial does step by step. Consider this question: do we need to provide three vertices to draw a triangle? That’s not true.

Those familiar with Canvas know that per-pixel operations like the following can easily cause performance problems when processing images:

for (let i = 0; i < width; i++) {
  for (let j = 0; j < height; j++) {
    // ...}}Copy the code

But in WebGL, there is no such serial loop. The shader you write in GLSL will be compiled to the GPU for parallel execution. Does that sound cool? As mentioned above, we have two types of shaders, vertex shaders and fragment shaders:

  • Vertex shader code is executed vertex by vertex, such as three times for triangles.
  • For a 100×100 area, the GPU will call the pixel shader in parallel for all 1W pixels, and the parallel process is transparent to you.

So for a “per-pixel” shard shader, as long as it knows the coordinates at which it is called each time, it can calculate the final color based on that position. This way, we don’t even need a vertex buffer, and we can calculate color per pixel based on a specific formula. The function thus designed for the shader is called Shaping function. A regular polygon shader looks like this:

# define TWO_PI 6.28318530718

// The screen resolution passed in from JS
uniform vec2 u_resolution;

void main() {
  vec2 st = gl_FragCoord.xy/u_resolution.xy;
  st.x *= u_resolution.x/u_resolution.y;
  vec3 color = vec3(0.0);
  float d = 0.0;

  // Remap space coordinates to between -1. And 1
  st = st * 2.1.;

  // The number of polygon edges
  int N = 3;

  // Angle and radius of the current pixel
  float a = atan(st.x,st.y)+PI;
  float r = TWO_PI/float(N);

  // Adjust the distance of the styling function
  d = cos(floor(. 5+a/r)*r-a)*length(st);

  color = vec3(1.0-smoothstep(4... 41,d));
  // color = vec3(d);

  gl_FragColor = vec4(color,1.0);
}
Copy the code

This is new territory, and because shader programming requires many pixels to be written in the same concise, parallel code, completely transparent to each other and unable to log at will, the bar for shad-oriented programming is actually quite high. The examples here have chapters in The Book of Shaders, a very good primer, and those who are interested may open The door to a new world at 🤔

P.S. why would we want to be far away here? This approach is actually a bit similar to the principle of font rendering. I am also learning some related knowledge recently and hope to have more content to share

conclusion

Admittedly, regular business development can easily get into the boring repetitive labor phase, but if we look a little further, we can see that there are actually a lot of technologies available to optimize interactions in the front end area. A simple triangle can be drawn in HTML/CSS/JS/GLSL languages in a dozen of schemes, more complex scenes are more flowers bloom. Browser rendering is an open world: no matter what you want to draw, there’s always a way to do it.

But unlike zeldari, where the more advanced the operation seems to be, the more sophisticated the technical solution, the more complex the implementation. However, whether it is game, code or life, I believe there is more than one way to be happy. I hope everyone can enjoy the process and find their own fun