When I saw the cubs’ login page in Denver, many people liked it very much, so I shamelenly said that I would use canvas to implement it again, which really set a flag for myself. Fortunately, the result was terrible.

Ladies and gentlemen, this is probably the worst demo you’ve ever seen, so I hope you don’t mind

Start by looking at other people’s renderings

To think

  1. Why the bear will follow the input box to move.
  2. Why do bear’s ears move forward
  3. What is the movement pattern of the bear

Do some logical thinking and elimination

  1. 2d
  2. 3d
  3. Judge the focus coordinates of the text box, so as to support the data of the bear rotation and other actions

Implement 3d vector classes

var eyeLength = 250, centerX = 200/ 2, centerY = 200 / 2;
// Set the visual distance and the coordinates of the center point

  function Vector3(x, y, z) {
    this.x = x;
    this.y = y;
    this.z = z;
    this._get2d = function() {
    // Scale the left side of the space to generate coordinates in the plane view
      var scale = eyeLength / (eyeLength + this.z);
      var x = centerX + this.x * scale;
      var y = centerY + this.y * scale;
      return { x: x, 
              y: y }; }}Copy the code

Rotate objects 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;
  }
Copy the code

Through the input vector and Angle value, the calculation is carried out to generate the coordinate after the coordinate is rotated in space. The calculation formula used here is the rotation matrix, and the matrix is not separated into a separate class.

The shape of the class

And if you saw in the last 2d vector presentation, when you’re dealing with vectors, you’re dealing with each vector point, so you can’t just do something like fillRect, and I’m using a Bates curve to draw it.

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);
    });
  }
Copy the code

We capture the vectors in paths to generate a face, and then form the object by the face, and rearrange the faces in the same shape so that the faces can be rendered according to Z (depth) when drawing, so as to produce the effect of occlusion.

We will then be able to create shapes 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"
	})
Copy the code

After rendering and transformation, the next step is to interact, here I use vUE to write the page, by listening to the input box text length, (text length * font size) + left margin = focus coordinates.

var vm=new Vue({
		el:'#bod'.data: {username:"".// Record input box
			left:0.// The distance to the left is used to determine when the rotation ends
			len:0.// Focus coordinates
			pos:0.// Whether to start the selection
			dir:'left'// Direction of rotation
		},
		computed: {// Calculate the length of the text
			roate:function (argument) {
				this.len=this.username.length; }},watch: {// Listen for len to increase or decrease
			len:function(o,n){
				this.pos=1;
				if(n<o){
					this.dir='right';
				}else {
					this.dir='left'}}}})Copy the code

Then we can turn everything over to the browser

function anima(){
		if(vm.pos===1) {// If you can rotate
			if(vm.left<r){// If the length is not enough, continue to rotate
				ctx.clearRect(0.0.200.200);
				switch (vm.dir) {// Determine the direction
					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{// Reset the data when the length is reached
				vm.left=0;
				vm.pos=0;
			}
		}
		requestAnimationFrame(anima)
	}
	anima();
Copy the code

insufficient

  1. The painting is a little ugly, not very clear to have that feeling
  2. Only a single object was rendered in depth, but the rendering of spatial depth was not realized
  3. The function of vector and shape is not perfect, so the effect is very limited

The source code

conclusion

In fact this is a rather bad things to do, do with PS or AE dynamic effect before, only think about how to beautification effect, the implement before really kick-ass graphics engine that group of people, from start to do simple implementation, it took nearly half a day, down among a lot of ideas, and then to arrange, although the final effect is not good, but, I’m still shameless and hope I can lure some big shots to join the canvas team and write interesting stuff together.

The related technical tutorials of Canvas and SVG will be updated from time to time. There will be practical ones, master principles ones, 2D 2.5D 3D ones, and linear algebra, physical graphics and other related basic knowledge will be involved.

Welcome guests to pay attention to the coin collection