写这个东西其实是因为最近在学习 JS 动画原理。虽然CSS3的普及,让我们在 web 端可以更轻易的做出一些相当不错的动画效果,但是复杂动画依旧需要 JS 去实现。
写一个简单的动画,只需要一些 web 编程基础和一点思路,但是写一些稍微复杂的动画,就会需要一些数学知识,为了更好的理解函数图像,我就这么耿直的自己画了。
原理很简单,就是在计算出X为各个值的时候,Y的值,然后画到画布上去就好了,不过如果 1x = 1px 就什么都看不清了,所以画图的时候需要放大一下。我是个数学渣,函数什么的,早都忘光了,数学错误各位看官就不用吐槽啦。
以下是代码:
<span style="font-size:14px;"> function Graph(element, option) {
var self = this;
this.element = typeof element == "string" ? document.getElementById(element) : element;
if(this.element.tagName.toLowerCase() !== "canvas") {
throw new TypeError("element isn`t canvas");
}
if(!option || typeof option !== "object") {
option = {};
}
this.context = this.element.getContext("2d");
this.style = {
width: self.element.width,
height: self.element.height,
}
this.style.centerX = parseInt(self.style.width) / 2,
this.style.centerY = parseInt(self.style.height) / 2
this.style.centerX = !option.center ?
this.style.centerX :
(option.center[0] == "auto") ? this.style.centerX : option.center[0];
this.style.centerY = !option.center ?
this.style.centerY :
(option.center[1]) ?
(option.center[1] == "auto"? this.style.centerY : option.center[1]) :
this.style.centerY;
// 图像拓展尺寸
this.ratioX = option.ratioX || 20;
this.ratioY = option.ratioY || 100;
// 轴到画布边框的距离
this.marginX = option.marginX || 30;
this.marginY = option.marginY || 30;
this.axisStyle = option.axisStyle;
this.drawStyle = option.drawStyle || "red";
this.startX = -10;
this.endX = 10;
this.acce = Math.PI / 60;
this.axis();
}
Graph.prototype = {
axis: function() {
var ct = this.context,
style = this.style;
ct.beginPath();
ct.moveTo(30, style.centerY);
ct.lineTo(style.width - 30, style.centerY);
ct.moveTo(style.centerX, 30);
ct.lineTo(style.centerX, style.height - 30);
ct.stroke();
ct.save();
},
/**
* 绘制函数图像
* @param {Object} easing
*/
draw: function(easing) {
var y = this.ratioY,
ratioX = this.ratioX,
x = this.startX,
s = this.acce,
end = this.endX,
ct = this.context,
style = this.style,
axisX = style.centerX,
axisY = style.centerY,
val = null,
strokeStyle = ct.strokeStyle;
ct.strokeStyle = this.drawStyle;
ct.beginPath();
for(var i = x; i < end; i += s ) {
if(x == i - s) {
ct.moveTo(axisX + ratioX * i, axisY + Math.floor(y * val));
continue;
}
val = easing(i);
ct.lineTo(axisX + ratioX * i, axisY + Math.floor(y * val));
}
ct.stroke();
ct.strokeStyle = strokeStyle;
}
}</span>
然后这么调用:
<span style="font-size:14px;">var grap = new Graph("canvas");
// 传入一个函数,这个函数可以接收一个参数 x 是 x 的值,返回 y 的值
grap.draw(Math.sin);
</span>
结果如图: