用HTML制作运动类网页,使用HTML5制作爬行运动学动画模拟

JavaScript

语言:

JaveScriptBabelCoffeeScript

确定

var Input = {

keys: [],

mouse: {

left: false,

right: false,

middle: false,

x: 0,

y: 0

}

};

for (var i = 0; i < 230; i++) {

Input.keys.push(false);

}

document.addEventListener("keydown", function(event) {

Input.keys[event.keyCode] = true;

});

document.addEventListener("keyup", function(event) {

Input.keys[event.keyCode] = false;

});

document.addEventListener("mousedown", function(event) {

if ((event.button = 0)) {

Input.mouse.left = true;

}

if ((event.button = 1)) {

Input.mouse.middle = true;

}

if ((event.button = 2)) {

Input.mouse.right = true;

}

});

document.addEventListener("mouseup", function(event) {

if ((event.button = 0)) {

Input.mouse.left = false;

}

if ((event.button = 1)) {

Input.mouse.middle = false;

}

if ((event.button = 2)) {

Input.mouse.right = false;

}

});

document.addEventListener("mousemove", function(event) {

Input.mouse.x = event.clientX;

Input.mouse.y = event.clientY;

});

//Sets up canvas

var canvas = document.createElement("canvas");

document.body.appendChild(canvas);

canvas.width = Math.max(window.innerWidth, window.innerWidth);

canvas.height = Math.max(window.innerWidth, window.innerWidth);

canvas.style.position = "absolute";

canvas.style.left = "0px";

canvas.style.top = "0px";

document.body.style.overflow = "hidden";

var ctx = canvas.getContext("2d");

//Necessary classes

var segmentCount = 0;

class Segment {

constructor(parent, size, angle, range, stiffness) {

segmentCount++;

this.isSegment = true;

this.parent = parent; //Segment which this one is connected to

if (typeof parent.children == "object") {

parent.children.push(this);

}

this.children = []; //Segments connected to this segment

this.size = size; //Distance from parent

this.relAngle = angle; //Angle relative to parent

this.defAngle = angle; //Default angle relative to parent

this.absAngle = parent.absAngle + angle; //Angle relative to x-axis

this.range = range; //Difference between maximum and minimum angles

this.stiffness = stiffness; //How closely it conforms to default angle

this.updateRelative(false, true);

}

updateRelative(iter, flex) {

this.relAngle =

this.relAngle -

2 *

Math.PI *

Math.floor((this.relAngle - this.defAngle) / 2 / Math.PI + 1 / 2);

if (flex) {

//this.relAngle=this.range/

//(1+Math.exp(-4*(this.relAngle-this.defAngle)/

//(this.stiffness*this.range)))

// -this.range/2+this.defAngle;

this.relAngle = Math.min(

this.defAngle + this.range / 2,

Math.max(

this.defAngle - this.range / 2, (this.relAngle - this.defAngle) / this.stiffness + this.defAngle

)

);

}

this.absAngle = this.parent.absAngle + this.relAngle;

this.x = this.parent.x + Math.cos(this.absAngle) * this.size; //Position

this.y = this.parent.y + Math.sin(this.absAngle) * this.size; //Position

if (iter) {

for (var i = 0; i < this.children.length; i++) {

this.children[i].updateRelative(iter, flex);

}

}

}

draw(iter) {

ctx.beginPath();

ctx.moveTo(this.parent.x, this.parent.y);

ctx.lineTo(this.x, this.y);

ctx.stroke();

if (iter) {

for (var i = 0; i < this.children.length; i++) {

this.children[i].draw(true);

}

}

}

follow(iter) {

var x = this.parent.x;

var y = this.parent.y;

var dist = Math.pow( (Math.pow((this.x - x), 2) + Math.pow((this.y - y), 2)), 0.5 );

this.x = x + this.size * (this.x - x) / dist;

this.y = y + this.size * (this.y - y) / dist;

this.absAngle = Math.atan2(this.y - y, this.x - x);

this.relAngle = this.absAngle - this.parent.absAngle;

this.updateRelative(false, true);

//this.draw();

if (iter) {

for (var i = 0; i < this.children.length; i++) {

this.children[i].follow(true);

}

}

}

}

class LimbSystem {

constructor(end, length, speed, creature) {

this.end = end;

this.length = Math.max(1, length);

this.creature = creature;

this.speed = speed;

creature.systems.push(this);

this.nodes = [];

var node = end;

for (var i = 0; i < length; i++) {

this.nodes.unshift(node);

//node.stiffness=1;

node = node.parent;

if (!node.isSegment) {

this.length = i + 1;

break;

}

}

this.hip = this.nodes[0].parent;

}

moveTo(x, y) {

this.nodes[0].updateRelative(true, true);

var dist = Math.pow((Math.pow((x - this.end.x), 2) + Math.pow((y - this.end.y), 2)), 0.5);

var len = Math.max(0, dist - this.speed);

for (var i = this.nodes.length - 1; i >= 0; i--) {

var node = this.nodes[i];

var ang = Math.atan2(node.y - y, node.x - x);

node.x = x + len * Math.cos(ang);

node.y = y + len * Math.sin(ang);

x = node.x;

y = node.y;

len = node.size;

}

for (var i = 0; i < this.nodes.length; i++) {

var node = this.nodes[i];

node.absAngle = Math.atan2(

node.y - node.parent.y,

node.x - node.parent.x

);

node.relAngle = node.absAngle - node.parent.absAngle;

for (var ii = 0; ii < node.children.length; ii++) {

var childNode = node.children[ii];

if (!this.nodes.includes(childNode)) {

childNode.updateRelative(true, false);

}

}

}

//this.nodes[0].updateRelative(true,false)

}

update() {

this.moveTo(Input.mouse.x, Input.mouse.y);

}

}

class LegSystem extends LimbSystem {

constructor(end, length, speed, creature) {

super(end, length, speed, creature);

this.goalX = end.x;

this.goalY = end.y;

this.step = 0; //0 stand still, 1 move forward,2 move towards foothold

this.forwardness = 0;

//For foot goal placement

this.reach =

0.9 *

Math.pow((Math.pow((this.end.x - this.hip.x), 2) + Math.pow((this.end.y - this.hip.y), 2)) , 0.5);

var relAngle =

this.creature.absAngle -

Math.atan2(this.end.y - this.hip.y, this.end.x - this.hip.x);

relAngle -= 2 * Math.PI * Math.floor(relAngle / 2 / Math.PI + 1 / 2);

this.swing = -relAngle + (2 * (relAngle < 0) - 1) * Math.PI / 2;

this.swingOffset = this.creature.absAngle - this.hip.absAngle;

//this.swing*=(2*(relAngle>0)-1);

}

update(x, y) {

this.moveTo(this.goalX, this.goalY);

//this.nodes[0].follow(true,true)

if (this.step == 0) {

var dist =

Math.pow((Math.pow((this.end.x - this.goalX), 2) + Math.pow((this.end.y - this.goalY), 2)),

0.5);

if (dist > 1) {

this.step = 1;

//this.goalX=x;

//this.goalY=y;

this.goalX =

this.hip.x +

this.reach *

Math.cos(this.swing + this.hip.absAngle + this.swingOffset) +

(2 * Math.random() - 1) * this.reach / 2;

this.goalY =

this.hip.y +

this.reach *

Math.sin(this.swing + this.hip.absAngle + this.swingOffset) +

(2 * Math.random() - 1) * this.reach / 2;

}

} else if (this.step == 1) {

var theta =

Math.atan2(this.end.y - this.hip.y, this.end.x - this.hip.x) -

this.hip.absAngle;

var dist =

Math.pow(( Math.pow((this.end.x - this.hip.x), 2) + Math.pow((this.end.y - this.hip.y), 2)), 0.5 );

var forwardness2 = dist * Math.cos(theta);

var dF = this.forwardness - forwardness2;

this.forwardness = forwardness2;

if (dF * dF < 1) {

this.step = 0;

this.goalX = this.hip.x + (this.end.x - this.hip.x);

this.goalY = this.hip.y + (this.end.y - this.hip.y);

}

}

//ctx.strokeStyle='blue';

//ctx.beginPath();

//ctx.moveTo(this.end.x,this.end.y);

//ctx.lineTo(this.hip.x+this.reach*Math.cos(this.swing+this.hip.absAngle+this.swingOffset),

//this.hip.y+this.reach*Math.sin(this.swing+this.hip.absAngle+this.swingOffset));

//ctx.stroke();

//ctx.strokeStyle='black';

}

}

class Creature {

constructor(

x,

y,

angle,

fAccel,

fFric,

fRes,

fThresh,

rAccel,

rFric,

rRes,

rThresh

) {

this.x = x; //Starting position

this.y = y;

this.absAngle = angle; //Staring angle

this.fSpeed = 0; //Forward speed

this.fAccel = fAccel; //Force when moving forward

this.fFric = fFric; //Friction against forward motion

this.fRes = fRes; //Resistance to motion

this.fThresh = fThresh; //minimum distance to target to keep moving forward

this.rSpeed = 0; //Rotational speed

this.rAccel = rAccel; //Force when rotating

this.rFric = rFric; //Friction against rotation

this.rRes = rRes; //Resistance to rotation

this.rThresh = rThresh; //Maximum angle difference before rotation

this.children = [];

this.systems = [];

}

follow(x, y) {

var dist = Math.pow((Math.pow((this.x - x), 2) + Math.pow((this.y - y), 2)), 0.5);

var angle = Math.atan2(y - this.y, x - this.x);

//Update forward

var accel = this.fAccel;

if (this.systems.length > 0) {

var sum = 0;

for (var i = 0; i < this.systems.length; i++) {

sum += this.systems[i].step == 0;

}

accel *= sum / this.systems.length;

}

this.fSpeed += accel * (dist > this.fThresh);

this.fSpeed *= 1 - this.fRes;

this.speed = Math.max(0, this.fSpeed - this.fFric);

//Update rotation

var dif = this.absAngle - angle;

dif -= 2 * Math.PI * Math.floor(dif / (2 * Math.PI) + 1 / 2);

if (Math.abs(dif) > this.rThresh && dist > this.fThresh) {

this.rSpeed -= this.rAccel * (2 * (dif > 0) - 1);

}

this.rSpeed *= 1 - this.rRes;

if (Math.abs(this.rSpeed) > this.rFric) {

this.rSpeed -= this.rFric * (2 * (this.rSpeed > 0) - 1);

} else {

this.rSpeed = 0;

}

//Update position

this.absAngle += this.rSpeed;

this.absAngle -=

2 * Math.PI * Math.floor(this.absAngle / (2 * Math.PI) + 1 / 2);

this.x += this.speed * Math.cos(this.absAngle);

this.y += this.speed * Math.sin(this.absAngle);

this.absAngle += Math.PI;

for (var i = 0; i < this.children.length; i++) {

this.children[i].follow(true, true);

}

for (var i = 0; i < this.systems.length; i++) {

this.systems[i].update(x, y);

}

this.absAngle -= Math.PI;

this.draw(true);

}

draw(iter) {

var r = 4;

ctx.beginPath();

ctx.arc(

this.x,

this.y,

r,

Math.PI / 4 + this.absAngle,

7 * Math.PI / 4 + this.absAngle

);

ctx.moveTo(

this.x + r * Math.cos(7 * Math.PI / 4 + this.absAngle),

this.y + r * Math.sin(7 * Math.PI / 4 + this.absAngle)

);

ctx.lineTo(

this.x + r * Math.pow(Math.cos(this.absAngle) * 2, 0.5),

this.y + r * Math.pow(Math.sin(this.absAngle) * 2, 0.5),

);

ctx.lineTo(

this.x + r * Math.cos(Math.PI / 4 + this.absAngle),

this.y + r * Math.sin(Math.PI / 4 + this.absAngle)

);

ctx.stroke();

if (iter) {

for (var i = 0; i < this.children.length; i++) {

this.children[i].draw(true);

}

}

}

}

//Initializes and animates

var critter;

function setupSimple() {

//(x,y,angle,fAccel,fFric,fRes,fThresh,rAccel,rFric,rRes,rThresh)

var critter = new Creature(

window.innerWidth / 2,

window.innerHeight / 2,

0,

12,

1,

0.5,

16,

0.5,

0.085,

0.5,

0.3

);

var node = critter;

//(parent,size,angle,range,stiffness)

for (var i = 0; i < 128; i++) {

var node = new Segment(node, 8, 0, 3.14159 / 2, 1);

}

setInterval(function() {

ctx.clearRect(0, 0, canvas.width, canvas.height);

critter.follow(Input.mouse.x, Input.mouse.y);

}, 33);

}

function setupTentacle() {

//(x,y,angle,fAccel,fFric,fRes,fThresh,rAccel,rFric,rRes,rThresh)

critter = new Creature(

window.innerWidth / 2,

window.innerHeight / 2,

0,

12,

1,

0.5,

16,

0.5,

0.085,

0.5,

0.3

);

var node = critter;

//(parent,size,angle,range,stiffness)

for (var i = 0; i < 32; i++) {

var node = new Segment(node, 8, 0, 2, 1);

}

//(end,length,speed,creature)

var tentacle = new LimbSystem(node, 32, 8, critter);

setInterval(function() {

ctx.clearRect(0, 0, canvas.width, canvas.height);

critter.follow(canvas.width / 2, canvas.height / 2);

ctx.beginPath();

ctx.arc(Input.mouse.x, Input.mouse.y, 2, 0, 6.283);

ctx.fill();

}, 33);

}

function setupArm() {

//(x,y,angle,fAccel,fFric,fRes,fThresh,rAccel,rFric,rRes,rThresh)

var critter = new Creature(

window.innerWidth / 2,

window.innerHeight / 2,

0,

12,

1,

0.5,

16,

0.5,

0.085,

0.5,

0.3

);

var node = critter;

//(parent,size,angle,range,stiffness)

for (var i = 0; i < 3; i++) {

var node = new Segment(node, 80, 0, 3.1416, 1);

}

var tentacle = new LimbSystem(node, 3, critter);

setInterval(function() {

ctx.clearRect(0, 0, canvas.width, canvas.height);

critter.follow(canvas.width / 2, canvas.height / 2);

}, 33);

ctx.beginPath();

ctx.arc(Input.mouse.x, Input.mouse.y, 2, 0, 6.283);

ctx.fill();

}

function setupTestSquid(size, legs) {

//(x,y,angle,fAccel,fFric,fRes,fThresh,rAccel,rFric,rRes,rThresh)

critter = new Creature(

window.innerWidth / 2,

window.innerHeight / 2,

0,

size * 10,

size * 3,

0.5,

16,

0.5,

0.085,

0.5,

0.3

);

var legNum = legs;

var jointNum = 32;

for (var i = 0; i < legNum; i++) {

var node = critter;

var ang = Math.PI / 2 * (i / (legNum - 1) - 0.5);

for (var ii = 0; ii < jointNum; ii++) {

var node = new Segment(

node,

size * 64 / jointNum,

ang * (ii == 0),

3.1416,

1.2

);

}

//(end,length,speed,creature,dist)

var leg = new LegSystem(node, jointNum, size * 30, critter);

}

setInterval(function() {

ctx.clearRect(0, 0, canvas.width, canvas.height);

critter.follow(Input.mouse.x, Input.mouse.y);

}, 33);

}

function setupLizard(size, legs, tail) {

var s = size;

//(x,y,angle,fAccel,fFric,fRes,fThresh,rAccel,rFric,rRes,rThresh)

critter = new Creature(

window.innerWidth / 2,

window.innerHeight / 2,

0,

s * 10,

s * 2,

0.5,

16,

0.5,

0.085,

0.5,

0.3

);

var spinal = critter;

//(parent,size,angle,range,stiffness)

//Neck

for (var i = 0; i < 6; i++) {

spinal = new Segment(spinal, s * 4, 0, 3.1415 * 2 / 3, 1.1);

for (var ii = -1; ii <= 1; ii += 2) {

var node = new Segment(spinal, s * 3, ii, 0.1, 2);

for (var iii = 0; iii < 3; iii++) {

node = new Segment(node, s * 0.1, -ii * 0.1, 0.1, 2);

}

}

}

//Torso and legs

for (var i = 0; i < legs; i++) {

if (i > 0) {

//Vertebrae and ribs

for (var ii = 0; ii < 6; ii++) {

spinal = new Segment(spinal, s * 4, 0, 1.571, 1.5);

for (var iii = -1; iii <= 1; iii += 2) {

var node = new Segment(spinal, s * 3, iii * 1.571, 0.1, 1.5);

for (var iv = 0; iv < 3; iv++) {

node = new Segment(node, s * 3, -iii * 0.3, 0.1, 2);

}

}

}

}

//Legs and shoulders

for (var ii = -1; ii <= 1; ii += 2) {

var node = new Segment(spinal, s * 12, ii * 0.785, 0, 8); //Hip

node = new Segment(node, s * 16, -ii * 0.785, 6.28, 1); //Humerus

node = new Segment(node, s * 16, ii * 1.571, 3.1415, 2); //Forearm

for (

var iii = 0; iii < 4; iii++ //fingers

) {

new Segment(node, s * 4, (iii / 3 - 0.5) * 1.571, 0.1, 4);

}

new LegSystem(node, 3, s * 12, critter, 4);

}

}

//Tail

for (var i = 0; i < tail; i++) {

spinal = new Segment(spinal, s * 4, 0, 3.1415 * 2 / 3, 1.1);

for (var ii = -1; ii <= 1; ii += 2) {

var node = new Segment(spinal, s * 3, ii, 0.1, 2);

for (var iii = 0; iii < 3; iii++) {

node = new Segment(node, s * 3 * (tail - i) / tail, -ii * 0.1, 0.1, 2);

}

}

}

setInterval(function() {

ctx.clearRect(0, 0, canvas.width, canvas.height);

critter.follow(Input.mouse.x, Input.mouse.y);

}, 33);

}

canvas.style.backgroundColor = "black";

ctx.strokeStyle = "white";

//setupSimple();//Just the very basic string

//setupTentacle();//Tentacle that reaches for mouse

//setupLizard(.5,100,128);//Literal centipede

//setupSquid(2,8);//Spidery thing

var legNum = Math.floor(1 + Math.random() * 12);

setupLizard(

8 / Math.sqrt(legNum),

legNum,

Math.floor(4 + Math.random() * legNum * 8)

);

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值