Who would say no to an open source 3D blog?

When it comes to blogging, everyone must be familiar with it. Whether you are a veteran who has been working hard in the workplace for many years or a young bird who has worked hard in school, you should have had the experience of "dressing up" a blog, such as: putting pictures you like, adding cool interactions, change to a DIY blog theme, and more. But no matter how you "dress up", you can't escape the flat "mortal body".

Today, HelloGitHub brings you an open source 3D blog project. To be honest, I was shocked when I first visited this blog, which subverted the blog's cognition. After entering, you need to control a 3D car to "find" the article before you can read it, which is very interesting!

Online: https://bruno-simon.com/

Project: https://github.com/brunosimon/folio-2019

Next, this article will first introduce how to run the project locally, then explain its source code and related technologies, and finally teach you how to modify the code and put your own blog posts in it to upgrade to a 3D blog! Now let us walk into this open source 3D blog and turn surprise into interest.

1. Introduction

1.1 Installation steps

Don't talk much, just run and talk, it only takes 4 steps. The command is as follows:

# 1.下载项目
git clone [email protected]:brunosimon/folio-2019.git
# 2.安装了 Parcel(Web 应用打包工具)
npm install -g parcel-bundler
# 3.安装依赖(仅第一次需要)
npm i
# 4.运行
npm run dev

Tip: I won’t introduce too much here how to install Node.js !

1.2 Operation effect

First, let's take a look at what this blog looks like:

A red, cute little jeep, galloping freely on the boundless map, you can also honk the horn to add to the fun, yes! This blog also comes with sound effects.

1.3 Mini games

Just as you "drive" the car and sing, you are suddenly "kidnapped" by the 3D world created by the author! Because he not only has simple models, but also comes with some very interesting mini-games.

For example, you can suddenly accelerate and hit these three "foam walls":

Or "bowling" in a small jeep:

Or do some "exciting" cross-country training:

Are these little games very interesting?

1.4 About the author

The author who can write such an interesting 3D blog must also be a very interesting person, but he also "portrayed" his own life into this project.

We can roughly guess that the daily life of this boss is roughly "one person, one dog", and he loves his dog very much. In addition to playing games, fitness, going out and other activities are all with it.

ah! What a pleasant life~ Where is the life of a programmer? This is obviously a life of wealth and freedom! If you think this blog is just a record of life, then you are wrong. When our little jeep drives to the "project", we will see many technical blog posts written by the authors.

After chatting about homework, let's enter the world of code!

2. Project overview

2.1 Project structure

Let's take a look at the project structure first:

A brief overview of these directories:

Is there a lot of files that I can't understand? It doesn't matter, let's start with the most important file, which is the most familiar srcfolder , where all the core code is placed. And the most important code file, I believe you can see it at a glance, yes! That is index.js.

import './style/main.css'
import Application from './javascript/Application.js'

window.application = new Application({
    $canvas: document.querySelector('.js-canvas'),
    useComposer: true
})

index.jsIsn't this very simple, it just tells us that all the effects we just saw are one canvas! The codes for processing logic come from Application.js, here we extract some important technology stacks and core libraries used in the project, and make a brief introduction.

I believe many friends have already guessed it, yes! That is Three.js.

2.2 Three.js

Three.js is a 3D JavaScript library that allows developers to create 3D experiences on the Web, and it is the best partner with WebGL.

Address: https://github.com/mrdoob/three.js

So what is WebGL? WebGL is a JavaScript API that is compatible with most modern browsers and uses the Graphics Processing Unit (GPU) directly, which allows for great optimization and more control, and is fast.

However, native WebGL is difficult and complicated. Using native WebGL to draw a triangle on the canvas requires at least 100 lines of code . In this case, adding perspective, lighting, models, animations, etc., can imagine how much It's balding. In order to save the few hairs of programmers, the Three.js library was born. Its value is that it simplifies the process of dealing with all of the above, and you can get an animated 3D scene with just a few lines of code .

2.3 dat.gui

Another library used in this 3D blog project is: dat.gui.js, which is a lightweight graphical user interface for changing variables in JavaScript. Using this library, it is easy to create interface components. The implemented interface roughly looks like this:

3. Explain the source code

After introducing the important technical points, let's go back to the core file of logic processing Application.jsand start explaining the source code.

3.1 Building the world

From the code structure, we can see that the entry is this.setWorldin , let's take a brief look at the code here:

constructor(_options)
{
  // Options
  this.config = _options.config
  this.debug = _options.debug
  ...
  // Set up
  this.container = new THREE.Object3D()
  this.container.matrixAutoUpdate = false

  this.setSounds() // 声音
  this.setControls() // 一些按键控制等
  this.setFloor() // 地板设置
  this.setAreas() // 区域设置
  this.setStartingScreen() // 首屏动画(loading > start)
}

I believe that you can understand some of the above settings at a glance. Here are a few method names that may cause doubts and a brief explanation. this.setControlsIt mainly includes two methods: this.setActionsand this.setKeyboard, here is the button control of the small jeep driving and honking.

And it is this.setFloormainly for the configuration file of the floor style of the current scene. If you don't like the original color scheme, you can customize a "colorful" color, but the premise is to have a certain aesthetic, otherwise it may be overturned as shown below .

Here we just customize the colors of the four corners of the scene (upper left, upper right, lower left, and lower right). The code snippet is as follows:

 // Colors 修改前
this.colors = {}
this.colors.topLeft = '#f5883c'
this.colors.topRight = '#ff9043'
this.colors.bottomRight = '#fccf92'
this.colors.bottomLeft = '#f5aa58'

// Colors 修改后
this.colors = {}
this.colors.topLeft = 'red'
this.colors.topRight = 'yello'
this.colors.bottomRight = 'blue'
this.colors.bottomLeft = 'black'

The rest is this.setAreasmainly for some mouse events, so that we can drag and explore the whole "world" with the mouse, including mousemove, mousedown, touchstartetc. The relevant codes will not be posted, and those who are interested can explore by themselves~

3.2 After starting

The above constructions are codes that are executed when the start page appears, which is equivalent to loading some resources in advance, and the rest of the loading starts after we click "start".

In World.jsthe file , we can also find the corresponding code this.start.

// On interact, reveal 点击 start 的交互
this.startingScreen.area.on('interact', () =>
  {
  TweenLite.to(this.startingScreen.startLabel.material, 0.3, { opacity: 0, delay: 0.4 })
  // 剩下的资源加载
  this.start()

  window.setTimeout(() =>
  {
    this.reveal.go()
  }, 600)
  })

In startthis method, we will see the loading of more content, such as the loading of the small jeep, and the loading of the list of articles we most want to know.

start()
{
  this.setCar() // 汽车加载
  this.areas.car = this.car
  this.setSections() // 文章加载
}

That's right, it is it. Next, we need to find the direction sign of the article entrance. That is, the x and y axes indicate the coordinate position of the object on the canvas, and we can also move it to a position we like.

// Projects
this.sections.projects = new ProjectsSection({
  ...options,
  x: 30,
  y: - 30
})

Here we need to briefly introduce the coordinate axis system Three.jsof , which adopts the right-handed coordinate system, as shown in the figure below, and corresponds to the left-handed coordinate system:

Therefore, when we increase the value of x, we will find that the distance of the entire article becomes farther. Similarly, modifying the value of y has the same effect.

3.3. Article list

Looking at ProjectsSection.jsthe file , we found that there are many pictures in it. Don’t worry about looking down and you will see one setList. The changes are as follows:

setList()
    {
        this.list = [
            {
                name: 'HelloGitHub',
                imageSources:
                [
                    projectsThreejsJourneySlideESources
                ],
                floorTexture: this.resources.items.projectsThreejsJourneyFloorTexture,
                link:
                {
                    href: 'https://hellogithub.com/',
                    // 控制按钮的位置
                    x: - 5.8,
                    y: - 4.5,
                    // 控制open按钮大小(0,0)的时候无边框
                    halfExtents:
                    {
                        x: 2,
                        y: 1
                    }
                },
                distinctions:
                [
                    // 一个3d模型的图标,xy是坐标轴位置
                    { type: 'fwa', x: 4.15, y: 5.15 }
                ]
            }
        ]
    }

In this way, you have your "own" 3D blog, but to be modest, 3D belongs to others, and the blog is your own . Let's take a close-up look:

Combined with the picture, let's explain the above code:

1. imageSources: It is the picture on the "billboard". I only made one picture of the homepage of the HelloGitHub community here. You can also put several pictures like the original blog.

Image storage address and import rules:

import projectsThreejsJourneySlideESources from '../../../models/projects/threejsJourney/slideE.jpg'

2. floorTextureThe "floor texture", that is, the picture we see "lying" on the ground, you may ask: Why can't we just put the picture on it and need to turn it into a texturetexture

Because this is a 3D world, as we drag the mouse up and down, our vision of the graph will change, so we need to "put" the graph into a 3D container, so that the 3D world we build is real and real letter. So here we follow the code to deduce how this graph is generated.

floorTexture: this.resources.items.projectsThreejsJourneyFloorTexture,

We learn that it is "hanging" under resourcesthe object . After checking layer by layer, we found that it Application.jswas loaded when . Going into Resources.jsthe file , we can find that there are a lot of resource files such as .png, .glband so on.

What is a glb file?

.glbFiles with the suffix mentioned above , which contain 3D models saved in GL Transfer Format (glTF). It stores information about the 3D model in a binary format, such as node hierarchy, cameras and materials, animations, and meshes. .glbfile is the binary version of .glTFthe file .

3.4 Going a little deeper

Then explore above: how the texture is generated, and follow Resources.jsthe file to see.

If Resources.jsyou projectsThreejsJourneyFloorTexturecan't find the keywords directly in the above, then delete some English words and try again. We will find such a line of code in this.loader.loadthis method:

{ name: 'projectsThreejsJourneyFloor', source: projectsThreejsJourneyFloorSource, type: 'texture' },

Follow its sourcefield to search again, and you will find its associated image file:

import projectsThreejsJourneyFloorSource from '../models/projects/threejsJourney/floorTexture2.png'

You must be curious, why can't you search directly? Let's fold the long code and take a look, you will find a handler function with a name:

this.loader.on('fileEnd', (_resource, _data) =>
  {
      this.items[_resource.name] = _data

      // Texture
      if(_resource.type === 'texture')
      {
          const texture = new THREE.Texture(_data)
          texture.needsUpdate = true

          this.items[`${_resource.name}Texture`] = texture
      }

      // Trigger progress
      this.trigger('progress', [this.loader.loaded / this.loader.toLoad])
  })

That's right, the processing function will automatically add a suffix Textureas the object name, which can be said to be very rigorous, because it has changed from an ordinary picture file to a "texture" file, which must be attached to the 3D container.

Now, let's go back to setListthe method . Other file links, coordinate axis positions of the model, I believe you have already seen them at a glance!

Five, the end

Reading the source code must not be an easy process, especially starting from a beginner. Although it is difficult, there are often some small surprises that inspire me, for example: in the process of reading the source code over and over again, it is quite interesting to suddenly discover a small knowledge point.

For example, there are many pictures like this in this 3D blog project:

When I clicked on it, I saw a dark picture. At first, I didn't know what it was, but as my understanding of the code deepened. It suddenly dawned on me that these are the position of the model and the rendering of the shadow effect.

Finally, this short 3D blog entry journey is here, and we are about to say goodbye to all passengers. In fact, the content of the entire original document is very rich, including many 3D model files, packaged configuration optimization, etc., which are worthy of more in-depth and systematic study, but due to limited space and ability, I will write here first today. If you are interested in browsing the source code, you will find more unexpected discoveries.

The above is all the content of this article. If you think this article is well written, please give me a like . Your support is the motivation for my update.

{{o.name}}
{{m.name}}

Guess you like

Origin my.oschina.net/HelloGitHub/blog/8569700