How does vue+canvas implement the cute login interface of station b

When I saw the login page of the bear in the Nuggets, many people liked it, so I shamelessly said that I would use canvas to implement it again. I really set a flag for myself, but the result was bad.

Dear viewers, this may be the most bleak demo you have ever seen. I hope you don't dislike it.

First look at other people's renderings

to think

  1. Why does the little bear move with the input of the input box.
  2. Why do bear ears move to the front
  3. What is the movement pattern of the bear

Make some logical thinking and exclusion

  1. 2d
  2. 3d
  3. Determine the focus coordinates of the text box, so as to provide data support for the bear's rotation and other actions

A vector class that implements 3d

var eyeLength = 250, centerX = 200/ 2, centerY = 200 / 2;
//设定视距,中心点的坐标

  function Vector3(x, y, z) {
    this.x = x;
    this.y = y;
    this.z = z;
    this._get2d = function() {
    //将空间左边进行缩放后生成平面视图中的坐标
      var scale = eyeLength / (eyeLength + this.z);
      var x = centerX + this.x * scale;
      var y = centerY + this.y * scale;
      return { x: x, 
              y: y };
    }
  }

Rotate an object in space

function rotateX(vec3,angleX) {
    var cos = Math.cos(angleX);
    var sin = Math.sin(angleX);
 
      var y1 = vec3.y * cos - vec3.z * sin;
      var z1 = vec3.z * cos + vec3.y * sin;
      vec3.y = y1;
      vec3.z = z1;

  }

  function rotateY(vec3,angleY) {
    var cos = Math.cos(angleY);
    var sin = Math.sin(angleY);

      var x1 = vec3.x * cos - vec3.z * sin;
      var z1 = vec3.z * cos + vec3.x * sin;
      vec3.x = x1;
      vec3.z = z1;
  }

By inputting the vector and angle value, the calculation is performed to generate the coordinates after the coordinates are rotated in space. The calculation formula used here is the rotation matrix, and the matrix is ​​not separated into a separate class.

shape class

If you have read the previous 2d vector explanation, you will know that when we use vectors to process, we need to process each vector point, so we can't directly use such fillRectmethods. Here I use Bezier curves to draw graphics.

function shape(option) {
	this.points=[];
	this.site=new Vector3(0,0,0);
	this.create(option);
	this.face=[];
	this.ctx={};
}
shape.prototype.render = function(ctx) {
	this.ctx=ctx;
    for(let f =0;f<this.paths.length;f++){
    	this.face[f]=new Face(this.ctx,this.color,...this.paths[f]);
    }
    this.face.sort(function(a,b){
    	return a-b;
    })
    this.face.forEach( function(face, index) {
    	face.draw(ctx);
    });
  }

We generate a surface by capturing the vector in the paths, and then use the surface to form an object, and rearrange the surface in the same shape, so that the surface is z(深度)rendered according to the drawing, resulting in the effect of occlusion.

This way we will be able to create the shape as follows

var face=new shape({
		paths:[[new Vector3(-50,0,4),new Vector3(-50,-70,4),new Vector3(50,-70,4),new Vector3(50,0,4)]],
		color:"#3366C"
	})
	var eyes=new shape({
		paths:[[new Vector3(-54,0,6),new Vector3(-54,-8,6),new Vector3(-46,-4,6),new Vector3(-46,0,6)],
		[new Vector3(-54,0,6),new Vector3(-54,8,6),new Vector3(-46,4,6),new Vector3(-46,0,6)]],
		color:"white"
	})

The quickest way to do this kind of drawing is to draw coordinates on paper first, and then implement it in code.

After implementing the drawing and transformation, the next step is to interact. Here I use vue to write the page, which is calculated by monitoring the text length of the input box, (text length * font size) + left margin = focus coordinate.

var vm=new Vue({
		el:'#bod',
		data:{
			username:"",//记录输入框
			left:0,//距离左边的长度,用于判断旋转何时结束
			len:0,//焦点坐标
			pos:0,//是否开始选择
			dir:'left'//旋转的方向
		},
		computed:{
		//计算文本长度
			roate:function (argument) {
				this.len=this.username.length;
			}
		},
		watch:{
		//监听len的值,判断是增还是减
			len:function(o,n){
				this.pos=1;
				if(n<o){
					this.dir='right';
				}else {
					this.dir='left'
				}
			}
		}
	})

Then we can hand everything over to the browser

function anima(){
		if(vm.pos===1){//如果可以旋转
			if(vm.left<r){//如果长度不够,继续旋转
				ctx.clearRect(0,0,200,200);
				switch (vm.dir) {//判断方向
					case 'right':
						face.rotate(0,r);
						eyes.rotate(0,r);
						face.render(ctx);
						eyes.render(ctx);
						vm.left+=r/5;
						break;
					case 'left':
						face.rotate(0,-r);
						eyes.rotate(0,-r);
						face.render(ctx);
						eyes.render(ctx);
						vm.left+=r/5;
						break;
				}
			}else{//长度达到后则重置数据
				vm.left=0;
				vm.pos=0;
			}
		}
		requestAnimationFrame(anima)
	}
	anima();

insufficient

  1. The painting is a bit ugly, it is not very clear to have that feeling
  2. Only depth rendering is performed for a single object, and spatial depth rendering is not implemented
  3. The functions of vectors and shapes are not perfect, making the effect very limited

This is what it looks like when it is not input. For the sake of contrast, I said that the angle of rotation has been increased.

The source code is here: source code

Summarize

In fact, this thing is not easy to do. When I used PS or AE for animation, I only thought about how to beautify the effect. After I realized it, I felt that the group of people in the graphics engine was really awesome. From the beginning, I planned to make it simple. , It took nearly half a day, and I pushed down a lot of ideas in the middle, and then I sorted it out. Although the final effect is not very good, I still shamelessly hope that I can tempt some big guys to join the canvas team and write interesting stories together. thing.

The related technical tutorials of canvas and svg are updated from time to time, including actual combat type and main principle type. 2d, 2.5d and 3d will be included, and the basic knowledge of linear algebra, physical graphics, etc. will be involved.

Welcome guests to collect and pay attention to coin tossing

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325340153&siteId=291194637