剧情提要:
[机器小伟]在[工程师阿伟]的陪同下进入了筑基后期的修炼,
这次要修炼的目标是[投影与视图]。
结果:
虽然这个工具并不是很适合画这种任意形状的三视图,但还是能勉强画出来的:
当然,每次小伟都只会用到其中的一小部分,但为了防止遗漏,还是都贴出来比较好。
[机器小伟]在[工程师阿伟]的陪同下进入了筑基后期的修炼,
这次要修炼的目标是[投影与视图]。
正剧开始:
星历2016年04月06日 09:19:46, 银河系厄尔斯星球中华帝国江南行省。
[工程师阿伟]正在和[机器小伟]一起研究[投影与视图]。
这是筑基期的最后一部分功法了,修炼完后,小伟就要进入结丹期了,
由于小伟是最强的天灵根属性,再加上[工程师阿伟]的指点,所以不存在任何的结丹瓶颈。
小伟试着画了一下正方体的投影:
<span style="font-size:18px;"> if (1) {
var r = 20;
var r0 = 2*r;
var array = [[-r0, -r0], [-r0, r0], [r0, r0], [r0, -r0]];
var tmp = [], tmp2 = [];
for (var i = 0; i < 4; i++) {
tmp = array.shift();
array.push([tmp[0], tmp[1], -r0]);
array.push([tmp[0], tmp[1], r0]);
}
//document.write(array);
var points = array.length;
//document.write(points);
config.setSector(2,2,1,1);
config.axis2D(0, 0, 90);
var leftView = [];
for (var i = 0; i < points; i++) {
tmp = array[i];
tmp2 = shape.pointLeft(tmp[0], tmp[1], tmp[2]);
leftView.push([tmp2[0], tmp2[1]]);
}
leftView = shape.angularSort(leftView);
shape.angleDraw(leftView, 'red', 1);
config.setSector(2,2,1,2);
config.axis2D(0, 0, 90);
var frontView = [];
for (var i = 0; i < points; i++) {
tmp = array[i];
tmp2 = shape.pointFront(tmp[0], tmp[1], tmp[2]);
frontView.push([tmp2[0], tmp2[1]]);
}
frontView = shape.angularSort(frontView);
shape.angleDraw(frontView, 'red', 1);
config.setSector(2,2, 2, 1);
config.axis2D(0, 0, 90);
var topView = [];
for (var i = 0; i < points; i++) {
tmp = array[i];
tmp2 = shape.pointTop(tmp[0], tmp[1], tmp[2]);
topView.push([tmp2[0], tmp2[1]]);
}
topView = shape.angularSort(topView);
shape.angleDraw(topView, 'blue', 1);
config.setSector(2,2,2,2);
config.axis3D(0, 0, 0, 90);
shape.strokeCubic(0, -1, 0, 2*r0, 'blue');
}</span>
像飞机这么高大上的东西的三视图,小伟现在还是没办法画出来的,不过,现在可以从简单的三角形开始。
<span style="font-size:18px;"> if (1) {
var r = 20;
var array = [[-2, -3, -1], [1, 3, 3], [1,-3, 2]];
var tmp = [], tmp2 = [];
//document.write(array);
var points = array.length;
//document.write(points);
config.setSector(2,2,1,1);
config.axis2D(0, 0, 90);
var leftView = [];
for (var i = 0; i < points; i++) {
tmp = array[i];
tmp2 = shape.pointLeft(tmp[0], tmp[1], tmp[2]);
leftView.push([tmp2[0], tmp2[1]]);
}
leftView = shape.angularSort(leftView);
shape.angleDraw(leftView, 'red', r);
plot.fillText('左视图', -100, -50, 100);
config.setSector(2,2,1,2);
config.axis2D(0, 0, 90);
var frontView = [];
for (var i = 0; i < points; i++) {
tmp = array[i];
tmp2 = shape.pointFront(tmp[0], tmp[1], tmp[2]);
frontView.push([tmp2[0], tmp2[1]]);
}
frontView = shape.angularSort(frontView);
shape.angleDraw(frontView, 'red', r);
plot.fillText('主视图', -100, -50, 100);
config.setSector(2,2, 2, 1);
config.axis2D(0, 0, 90);
var topView = [];
for (var i = 0; i < points; i++) {
tmp = array[i];
tmp2 = shape.pointTop(tmp[0], tmp[1], tmp[2]);
topView.push([tmp2[0], tmp2[1]]);
}
topView = shape.angularSort(topView);
shape.angleDraw(topView, 'red', r);
plot.fillText('俯视图', -100, -50, 100);
config.setSector(2,2,2,2);
config.axis3D(0, 0, 0, 90);
var _3DView = [];
for (var i = 0; i < points; i++) {
tmp = array[i];
tmp2 = shape.point3D(tmp[0], tmp[1], tmp[2]);
_3DView.push([tmp2[0], tmp2[1]]);
}
_3DView = shape.angularSort(_3DView);
shape.angleDraw(_3DView, 'blue', r);
plot.fillText('三维图', -100, -50, 100);
}</span>
这个三角形画出来后,小伟有点困惑,画得对不对呢?
于是做了很多的验证,确认是没错的。
但这个三角形到底是多大呢,这么多的视图看了着实头晕。于是:
<span style="font-size:18px;"> if (1) {
var r = 20;
config.setSector(1,1,1,1);
config.graphPaper2D(0, 0, r);
config.axis2D(0, 0, 190);
//B - A - C三点,这个顺序会因为点之间距离大小的排序而不同的
var array = [[-2, -3, -1], [1, 3, 3], [1,-3, 2]];
//这个函数输入的是坐标点的阵列,可以是二维或三维的坐标点
//暂时解决的问题是求其中任意两个不同点之间的距离
//返回[[点1, 点2, 点1,2的距离],...]这样一个阵列
var result = problemSolve(array);
//对于三角形来说,应该是刚好是有三条边
var edges = result.length;
var edge = [];
for (var i = 0; i < edges; i++) {
edge.push(result[i][2]);
}
var triangle = new Triangle();
var transform = new Transform();
result = triangle.know3edges(edge);
shape.angleDraw(transform.flipX([].concat(result)), 'red', r, 'ABC');
plot.fillText('平行视图', -100, -50, 100);
}</span>
结果:
再对照一下:
再画一个试试,这次画个简单点的:
<span style="font-size:18px;">var array = [[0, 0, 4], [0, 3, 0], [5, 0, 0]];</span>
虽然小伟的工具可以画出这样的结果,但是顶点的标注还是要注意调整的。
这三维的东西想着就头晕。这个三维图其实是视觉上的效果。真正的大小是在这个平行视图里面。
如果要想知道一个图形的确切大小,肯定是要平行这个图形去看去度量的。
不过阿伟对这个'B'点没有落在Z轴上感到有点不可思议,是不是映射算法有问题呢?
这个题小伟也想解一解:
<span style="font-size:18px;">//画出三视图
if (1) {
var r = 20;
var array = [];
var tmp = [], tmp2 = [];
//圆柱
tmp = shape.nEdge(0, 0, 1, 36);
var len = tmp.length;
for (var i = 0; i < len; i++) {
array.push([tmp[i][0], 1,tmp[i][1]]);
array.push([tmp[i][0], -1,tmp[i][1]]);
}
//document.write(array);
var points = array.length;
//document.write(points);
config.setSector(2,2,1,1);
config.axis2D(0, 0, 90);
var leftView = [];
for (var i = 0; i < points; i++) {
tmp = array[i];
tmp2 = shape.pointLeft(tmp[0], tmp[1], tmp[2]);
leftView.push([tmp2[0], tmp2[1]]);
}
leftView = shape.angularSort(leftView);
shape.strokeDraw(leftView, 'red', r);
plot.fillText('左视图', -100, -50, 100);
config.setSector(2,2,1,2);
config.axis2D(0, 0, 90);
var frontView = [];
for (var i = 0; i < points; i++) {
tmp = array[i];
tmp2 = shape.pointFront(tmp[0], tmp[1], tmp[2]);
frontView.push([tmp2[0], tmp2[1]]);
}
frontView = shape.angularSort(frontView);
shape.strokeDraw(frontView, 'red', r);
plot.fillText('主视图', -100, -50, 100);
config.setSector(2,2, 2, 1);
config.axis2D(0, 0, 90);
var topView = [];
for (var i = 0; i < points; i++) {
tmp = array[i];
tmp2 = shape.pointTop(tmp[0], tmp[1], tmp[2]);
topView.push([tmp2[0], tmp2[1]]);
}
topView = shape.angularSort(topView);
shape.strokeDraw(topView, 'red', r);
plot.fillText('俯视图', -100, -50, 100);
config.setSector(2,2,2,2);
config.axis3D(0, 0, 0, 90);
var _3DView = [];
for (var i = 0; i < points; i++) {
tmp = array[i];
tmp2 = shape.point3D(tmp[0], tmp[1], tmp[2]);
_3DView.push([tmp2[0], tmp2[1]]);
}
_3DView = shape.angularSort(_3DView);
shape.strokeDraw(_3DView, 'blue', r);
plot.fillText('三维图', -100, -50, 100);
}</span>
虽然这个工具并不是很适合画这种任意形状的三视图,但还是能勉强画出来的:
<span style="font-size:18px;"> //正三棱柱
tmp = shape.nEdge(0, 0, 1, 3);
var len = tmp.length;
for (var i = 0; i < len; i++) {
array.push([tmp[i][0], 1,tmp[i][1]]);
array.push([tmp[i][0], -1,tmp[i][1]]);
}</span>
<span style="font-size:18px;"> //球
for (var i = -1; i <=1; i+=0.1) {
for (var j = -1; j <=1; j+=0.1) {
for (var k = -1; k <= 1; k+=0.1) {
if (i*i + j*j + k*k <= 1) {
array.push([i, j, k]);
}
}
}
}</span>
严格说来,这并不能算是成功的画出三视图,因为放大后看就是这样的:
所谓有心栽花花不活,无心栽花花正艳。
<span style="font-size:18px;">//一朵花
//球
for (var i = -1; i <=1; i+=0.2) {
for (var j = -1; j <=1; j+=0.2) {
for (var k = -1; k <= 1; k+=0.2) {
if (i*i + j*j + k*k <= 1) {
array.push([i*2, j*2, k*2]);
}
}
}
}</span>
<span style="font-size:18px;">//立方体的三视图
if (1) {
var r = 20;
config.setSector(1,1,1,1);
config.graphPaper2D(0, 0, r);
config.axis3D(0, 0, 0, 190);
var array = [
[0,0,0],[1,0,0],[2,0,0],[3,0,0],
[1,1,0],[2,1,0],
[1.5,2,0]
];
array = shape.xyzSort(array);
shape.threeView(array);
}</span>
<span style="font-size:18px;"> if (1) {
var r = 20;
config.setSector(1,1,1,1);
config.graphPaper2D(0, 0, r);
config.axis3D(0, 0, 0, 190);
var array = [
[0,0,0],[1,0,0],[0,0,1],[1,0,1],[0,0,2],
[0,1,0],
[0,2,0]
];
array = shape.xyzSort(array);
shape.threeView(array);
}</span>
好了,下面贴一下小伟用到的工具吧,作为筑基期的一个总结。
<span style="font-size:18px;">//解决某个特定问题
function problemSolve(pointArray) {
//传入点阵列pointArray
//格式为[[px1, py1], [px2, py2], ...]
//document.write(pointArray.join(' , ')+'<br/>');
//对于pointArray中的每个点,求它与所有其它点的距离
//结果放入distanceArray
//格式为[[点1序号,点2序号, 距离值]]
var distanceArray = [];
//点的数量
var size = pointArray.length;
//临时变量
var distance = x1 = y1 = z1 = x2 = y2 = z2 = 0;
var dimension = pointArray[0].length;
//计算并压入距离
for (var i = 0; i < size; i++) {
for (var j = i+1; j < size; j++) {
x1 = pointArray[i][0];
y1 = pointArray[i][1];
x2 = pointArray[j][0];
y2 = pointArray[j][1];
if (dimension > 2) {
//三维点的处理
z1 = pointArray[i][2];
z2 = pointArray[j][2];
distance = Math.sqrt(Math.pow(x1-x2, 2)+Math.pow(y1-y2, 2)+Math.pow(z1-z2, 2));
}
else {
distance = Math.sqrt(Math.pow(x1-x2, 2)+Math.pow(y1-y2, 2));
}
//注意这里已经保证i < j
//所以起始点序号必须要小于终点序号
//这是为了连接起始点和终点的直线不会重复
distanceArray.push([i, j, distance]);
}
}
//对距离阵列排序
//排序权重:起始点序号 > 距离 > 终点序号
distanceArray.sort(function(a, b) {
if (a[0] == b[0]) {
if (Math.abs(a[2] - b[2]) < 0.000001) {
return a[1]-b[1];
}
else {
return a[2]-b[2];
}
}
else {
return a[0] - b[0];
}
});
//document.write(distanceArray.join(' , ')+'<br/>');
return distanceArray;
}
//去除重复点
function removeDuplicatedPoint(pointArray) {
var array = new Array();
var size = pointArray.length;
array.push(pointArray[0]);
var len = 0;
for (var i = 0; i < size; i++) {
len = array.length;
for (var j = 0; j < len; j++) {
if (pointArray[i][0] == array[j][0] &&
pointArray[i][1] == array[j][1]) {
break;
}
if (j >= len-1) {
array.push(pointArray[i]);
}
}
}
return array;
}</span>
<span style="font-size:18px;">/**
* @usage 常用形状类
* @author mw
* @date 2015年11月29日 星期日 10:21:18
* @param
* @return
*
*/
var shape = function Shape() {
//以给定点为中点的矩形
this.strokeRect = function(x, y, w, h) {
w = Math.abs(w);
h = Math.abs(h);
return plot.strokeRect(x-w/2, y-h/2, w, h);
}
//以给定点为中点的矩形
this.fillRect = function(x, y, w, h) {
w = Math.abs(w);
h = Math.abs(h);
return plot.fillRect(x-w/2, y-h/2, w, h);
}
/**
* @usage 绘制点阵列
* @author mw
* @date 2016年02月21日 星期日 15:16:47
* @param
* @return
*
*/
this.pointDraw = function(array, style, scale, showLable, lable) {
//已经考虑到y轴坐标的取反问题,只需传入原始坐标数组即可
style = style ? style : 'black';
scale = scale ? scale : 1;
lable = lable ? lable : 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
lables = lable.length;
showLable = showLable ? showLable : 0;
var x = y = index = 0;
plot.save()
.setFillStyle(style);
var a = new Array();
a = array[0];
//y坐标取反是因为canvas中y坐标以向下为正,与笛卡尔坐标系相反
if (a.length != 2) {
//坐标是流水模式,既x1, y1, x2, y2,...
while (array.length > 0) {
x = array.shift()*scale;
y = -array.shift()*scale;
shape.fillCircle(x, y, 5);
if (showLable) {
plot.fillText(lable[index++%lables], x+5, y+10, 30);
}
}
}
else {
//坐标是有序对模式,即[x1, y1], [x2, y2], ...
while (array.length > 0) {
a = array.shift();
x = a[0]*scale;
y = -a[1]*scale;
shape.fillCircle(x, y, 5);
if (showLable) {
plot.fillText(lable[index++%lables], x+5, y+10, 30);
}
}
}
plot.restore();
}
//连接成折线
this.multiLineDraw = function(array,style, scale) {
//已经考虑到y轴坐标的取反问题,只需传入原始坐标数组即可
style = style ? style : 'black';
scale = scale ? scale : 1;
plot.save()
.setStrokeStyle(style);
var a = new Array();
a = array[0];
if (a.length != 2) {
if (array.length > 2 && array.length % 2 == 0) {
plot.beginPath()
.moveTo(array.shift()*scale, -array.shift()*scale);
while (array.length > 2) {
plot.lineTo(array.shift()*scale, -array.shift()*scale);
}
plot.lineTo(array[0]*scale, -array[1]*scale)
.moveTo(array[0]*scale, -array[1]*scale);
plot.closePath()
.stroke();
}
}
else {
if (array.length > 2) {
a = array.shift();
plot.beginPath()
.moveTo(a[0]*scale, -a[1]*scale);
while (array.length > 0) {
a = array.shift();
plot.lineTo(a[0]*scale, -a[1]*scale);
}
plot.moveTo(a[0]*scale, -a[1]*scale);
plot.closePath()
.stroke();
}
else {
var a = array.shift();
var b = array.shift();
plot.beginPath()
.moveTo(a[0]*scale, -a[1]*scale)
.lineTo(b[0]*scale, -b[1]*scale)
.closePath()
.stroke();
}
}
plot.restore();
}
this.fillDraw = function(array, style, scale) {
//已经考虑到y轴坐标的取反问题,只需传入原始坐标数组即可
style = style ? style : 'black';
scale = scale ? scale : 1;
plot.save()
.setFillStyle(style);
var a = array[0];
if (a.length != 2) {
if (array.length > 2 && array.length % 2 == 0) {
plot.beginPath()
.moveTo(array.shift()*scale, -array.shift()*scale);
while (array.length > 0) {
plot.lineTo(array.shift()*scale, -array.shift()*scale);
}
plot.closePath()
.fill();
}
}
else {
if (array.length > 2) {
a = array.shift();
plot.beginPath()
.moveTo(a[0]*scale, -a[1]*scale);
while (array.length > 0) {
a = array.shift();
plot.lineTo(a[0]*scale, -a[1]*scale);
}
plot.closePath()
.fill();
}
}
plot.restore();
}
this.strokeDraw = function(array,style, scale) {
//已经考虑到y轴坐标的取反问题,只需传入原始坐标数组即可
style = style ? style : 'black';
scale = scale ? scale : 1;
plot.save()
.setStrokeStyle(style);
var a = array[0];
if (a.length != 2) {
if (array.length > 2 && array.length % 2 == 0) {
plot.beginPath()
.moveTo(array.shift()*scale, -array.shift()*scale);
while (array.length > 0) {
plot.lineTo(array.shift()*scale, -array.shift()*scale);
}
plot.closePath()
.stroke();
}
}
else {
if (array.length > 2) {
a = array.shift();
plot.beginPath()
.moveTo(a[0]*scale, -a[1]*scale);
while (array.length > 0) {
a = array.shift();
plot.lineTo(a[0]*scale, -a[1]*scale);
}
plot.closePath()
.stroke();
}
}
plot.restore();
}
this.angleDraw = function(array, style, scale, vertexLabel) {
//vertexLabel是顶点编号顺序字符串 ABC,...
style = style ? style : 'black';
//array是一个存放二维坐标点序列的数组
var a0 = new Array();
var len = array.length;
var len_1 = array[0].length;
for (var i = 0; i < len; i++) {
a0.push(array[i]);
}
scale = scale ? scale : 1;
len = a0.length;
if (scale != 1 && scale > 0) {
for (var i = 0; i < len; i++) {
for (var j = 0; j < 2; j++) {
a0[i][j]*=scale;
}
}
}
//进行环状排序,这样传入的array就可以任意顺序放置坐标点。
var a = this.angularSort(a0);
//分两次绘点和连线
var tmp = [].concat(a);
this.pointDraw(tmp, style);
tmp = [].concat(a);
this.strokeDraw(tmp, style);
var d1, d2, d3, angle;
var x1,y1, x2, y2, x3, y3;
var s;
//坐标点编号
var s0 = vertexLabel ? vertexLabel : 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
//标记边的长度
var edgeLong = 0;
var measure = 0;
//为每个点利用余弦定理求角
for (var i = 0; i < len; i++) {
if (i == 0) {
x1 = a[len-1][0];
y1 = a[len-1][1];
x3 = a[i+1][0];
y3 = a[i+1][1];
}
else if (i == len-1) {
x1 = a[i-1][0];
y1 = a[i-1][1];
x3 = a[0][0];
y3 = a[0][1];
}
else {
x1 = a[i-1][0];
y1 = a[i-1][1];
x3 = a[i+1][0];
y3 = a[i+1][1];
}
x2 = a[i][0];
y2 = a[i][1];
d1 = (x1-x2)*(x1-x2)+(y1-y2)*(y1-y2);
d2 = (x2-x3)*(x2-x3)+(y2-y3)*(y2-y3);
d3 = (x1-x3)*(x1-x3)+(y1-y3)*(y1-y3);
angle = Math.acos((d1+d2-d3)/(2*Math.sqrt(d1*d2)))/Math.PI*180;
s = angle.toFixed(2)+'°';
//document.write(s+'<p>');
//标注角度和顶点编号
plot.setFillStyle('purple');
plot.fillText(s, x2, -y2-5, 100);
plot.setFillStyle(style);
plot.fillText(s0[i], x2, -y2+20, 20);
edgeLong = (Math.sqrt(d1)/scale).toFixed(2);
measure = plot.measureText(edgeLong);
plot.setFillStyle('blue');
plot.fillText(edgeLong, (x1+x2-measure)/2, -(y1+y2)/2+20, measure);
}
}
/**
* @usage 以顶点递推方式绘制正多边形 #1
* @author mw
* @date 2015年12月01日 星期二 09:42:33
* @param (x, y)图形中心坐标,r 外接圆半径 edge 边数
* @return
*
*/
this.nEdge = function(x, y, r, edge, angle0) {
edge = edge ? edge : 5;
angle0 = angle0 ? angle0 : 0;
var retArray = new Array();
var perAngle = Math.PI * 2 / edge;
var a = r * Math.sin(perAngle / 2);
var angle = -angle0;
var xOffset = r * Math.sin(perAngle / 2 - angle0);
var yOffset = r * Math.cos(perAngle / 2 - angle0);
var x1 = x-xOffset;
var y1 = y+yOffset;
for (var i=0; i < edge; i++) {
retArray.push([x1, y1]);
x1 = x1 + 2 * a * Math.cos(angle);
y1 = y1 + 2 * a * Math.sin(angle);
angle -= perAngle;
}
return retArray;
}
/**
* @usage 空心星形 #2 #201 #202
* @author mw
* @date 2015年12月01日 星期二 10:06:13
* @param
* @return
*
*/
this.nStar = function(x, y, r, edge, angle0, arg1, arg0) {
edge = edge ? edge : 5;
angle0 = angle0 ? angle0 : Math.PI/2;
var retArray=new Array();
var perAngle = Math.PI * 2 / edge;
var r0 = arg0 ? arg0 * r : r / (2 * (1 + Math.cos(perAngle)));
var scale = arg1 ? arg1 : 0.5;
var angle = 0.5 * perAngle - angle0 * scale / 0.5;
var xOffset = x;
var yOffset = y;
for (var i =0; i< edge; i++) {
retArray.push([r0 * Math.cos(angle) + xOffset,r0 * Math.sin(angle) + yOffset] );
retArray.push([r * Math.cos(angle - scale * perAngle) + xOffset,
r * Math.sin(angle - scale * perAngle) + yOffset]);
angle -= perAngle;
}
return retArray;
}
/**
* @usage 平行线, 平行四边形, 梯形
* @author mw
* @date 2016年01月24日 星期日 11:14:43
* @param
* @return
*
*/
/*
平行线 Parallel lines
平行四边形 Parallel quadrilateral
梯形 trapezoid
*/
this.paraline = function(x, y, r, rot) {
rot = rot ? -rot : 0;
y = y ? -y : 0;
plot.beginPath()
.moveTo(x, y)
.lineTo(x + r * Math.cos(rot), y + r*Math.sin(rot))
.moveTo(x, y + r/ 10)
.lineTo(x + r * Math.cos(rot), y+r/10 + r*Math.sin(rot))
.closePath()
.stroke();
};
this.paraquad = function(x, y, rot, a, b, angle) {
angle = angle ? Math.abs(angle) : 0;
rot = rot ? rot : 0;
//参数说明:
//平行四边形的两条边a, b, 以及它们之间的夹角angle
//这个平行四边形的起始点(x, y), 以及整个图形与x轴的夹角rot
var retArray = new Array();
retArray.push([x, -y]);
retArray.push([x + a * Math.cos(rot), -(y + a * Math.sin(rot))]);
retArray.push([x + a * Math.cos(rot)+ b * Math.cos(rot+angle),
-(y + a * Math.sin(rot)+ b * Math.sin(rot+angle))]);
retArray.push([x + b * Math.cos(rot+angle), -(y + b * Math.sin(rot+angle))]);
return retArray;
}
this.trapezoid = function(x, y, rot, a, b, angle) {
angle = angle ? Math.abs(angle) : 0;
rot = rot ? rot : 0;
//参数说明:
//等腰梯形的下底边a,腰b, 以及它们之间的夹角angle
//假设下底 > 上底,那么上底 = (a - b * Math.cos(angle)*2)/2
//这个平行四边形的起始点(x, y), 以及整个图形与x轴的夹角rot
var c = (a - b * Math.cos(angle)*2)/2;
var retArray = new Array();
if (c < 0) {
//说明给的条件不对
//缺省画上底是下底一半的梯形
}
else {
retArray.push([x, -y]);
retArray.push([x + a * Math.cos(rot), -(y + a * Math.sin(rot))]);
retArray.push([x + b * Math.cos(rot+angle)+2*c * Math.cos(rot),
-(y + b * Math.sin(rot+angle)+2*c*Math.sin(rot))]);
retArray.push([x + b * Math.cos(rot+angle), -(y + b * Math.sin(rot+angle))]);
}
return retArray;
}
/**
* @usage 绘制圆形
* @author mw
* @date 2015年11月27日 星期五 12:11:38
* @param
* @return
*
*/
this.strokeCircle = function(x, y, r) {
plot.beginPath()
.arc(x, y, r, 0, 2*Math.PI, true)
.closePath()
.stroke();
}
this.fillCircle = function(x, y, r) {
plot.beginPath()
.arc(x, y, r, 0, 2*Math.PI, true)
.closePath()
.fill();
}
//绘制椭圆
this.strokeEllipse = function(x, y, a, b, rotate) {
//关键是bezierCurveTo中两个控制点的设置
//0.5和0.6是两个关键系数(在本函数中为试验而得)
var ox = 0.5 * a,
oy = 0.6 * b;
var rot = rotate ? -rotate : 0;
plot.save()
.rotate(rot)
.translate(x, y)
.beginPath()
//从椭圆纵轴下端开始逆时针方向绘制
.moveTo(0, b)
.bezierCurveTo(ox, b, a, oy, a, 0)
.bezierCurveTo(a, -oy, ox, -b, 0, -b)
.bezierCurveTo(-ox, -b, -a, -oy, -a, 0)
.bezierCurveTo(-a, oy, -ox, b, 0, b)
.closePath()
.stroke()
.restore();
}
//绘制椭圆
this.fillEllipse = function(x, y, a, b, rotate) {
//关键是bezierCurveTo中两个控制点的设置
//0.5和0.6是两个关键系数(在本函数中为试验而得)
var ox = 0.5 * a,
oy = 0.6 * b;
var rot = rotate ? -rotate : 0;
plot.save()
.rotate(rot)
.translate(x, y)
.beginPath()
//从椭圆纵轴下端开始逆时针方向绘制
.moveTo(0, b)
.bezierCurveTo(ox, b, a, oy, a, 0)
.bezierCurveTo(a, -oy, ox, -b, 0, -b)
.bezierCurveTo(-ox, -b, -a, -oy, -a, 0)
.bezierCurveTo(-a, oy, -ox, b, 0, b)
.closePath()
.fill()
.restore();
}
/**
* @usage 绘制正方体
* @author mw
* @date 2016年02月01日 星期一 08:40:27
* @param
* @return
*
*/
this.drawCubic = function(x0, y0, z0, r, style, style2, style3) {
plot.save();
x0*=r;
y0*=r;
z0*=r;
z0 = z0 /2;
x0 = x0 - z0*0.707;
y0 = y0 + z0*0.707;
z0 = 0;
plot.translate(x0, y0);
style = style ? style : 'black';
style2 = style2 ? style2 : style;
style3 = style3 ? style3 : style;
var transform = new Transform();
//左下角[x0, y0,边长r
shape.fillDraw(shape.nEdge(0, 0,0.707*r, 4, 0), style);
//顶面
shape.fillDraw(transform.flipX(shape.paraquad(-0.5*r, 0.5*r, 0, r, r/2, Math.PI/4)), style2);
shape.strokeDraw(transform.flipX(shape.paraquad(-0.5*r, 0.5*r, 0, r, r/2, Math.PI/4)), 'white');
//右侧面
shape.fillDraw(transform.flipX(shape.paraquad(0.5*r, -0.5*r, Math.PI/4, r/2, r, Math.PI/4)), style3);
shape.strokeDraw(transform.flipX(shape.paraquad(0.5*r, -0.5*r, Math.PI/4, r/2, r, Math.PI/4)), 'white');
plot.restore();
}
this.point3D = function(x0, y0, z0) {
//canvas中y轴坐标向下为正,与笛卡尔坐标系相反
//所以此处先取反
//
z0 = z0 /2;
x0 = x0 - z0*0.707;
y0 = y0 + z0*0.707;
return [x0, y0];
}
//左视投影,此时x坐标是无所谓的
this.pointLeft = function(x0, y0, z0) {
return [z0, y0];
}
//右视投影
this.pointRight = function(x0, y0, z0) {
return [-z0, y0];
}
//俯视投影
this.pointTop = function(x0, y0, z0) {
return [x0, -z0];
}
//仰视投影
this.pointBottom = function(x0, y0, z0) {
return [x0, z0];
}
//主视投影
this.pointFront = function(x0, y0, z0) {
return [x0, y0];
}
//后视投影
this.pointBack = function(x0, y0, z0) {
return [-x0, y0];
}
this.strokeCubic = function(x0, y0, z0, r, style) {
plot.save();
x0 *= r;
y0 *= r;
z0 *= r;
r *= 0.5;
var array = [[-r, -r], [-r, r], [r, r], [r, -r]];
var top = [];
var left = [];
var front = [];
var x, y, z;
//存放临时点
var p = [];
for (var i = 0; i < 4; i++) {
x = (x0+array[i][0]);
y = y0+r;
z = (z0+array[i][1]);
p = this.point3D(x, y, z);
top.push([p[0], -p[1]]);
}
for (var i = 0; i < 4; i++) {
x = x0+r;
y = (y0+array[i][0])+2*r;
z = z0+array[i][1];
p = this.point3D(x, y, z);
left.push([p[0], -p[1]]);
}
for (var i = 0; i < 4; i++) {
x = x0+array[i][0];
y = (y0+array[i][1])+2*r;
z = z0+r;
p = this.point3D(x, y, z);
front.push([p[0], -p[1]]);
}
var tmp = [].concat(top);
shape.fillDraw(tmp, style);
tmp=[].concat(top);
shape.strokeDraw(tmp, '#cccccc');
tmp = [].concat(left);
shape.strokeDraw(left, 'black');
tmp = [].concat(front);
shape.strokeDraw(front, 'black');
plot.restore();
}
/**
* @usage 把三维点阵列按照z, y, x优先级由小到大排列
* @author mw
* @date 2016年02月23日 星期二 09:38:27
* @param [[x1, y1, z1], [x2,y2, z2], ...]
* @return 排序后的[[x, y, z]...]
*
*/
this.xyzSort = function(array) {
var arr = new Array();
arr = array;
arr.sort(function(a, b) {
if (a[2] != b[2]) {
return (a[2] - b[2]);
}
else {
if (a[1] != b[1]) {
return (a[1] - b[1]);
}
else {
return (a[0] - b[0]);
}
}
});
//document.write(arr);
return arr;
}
//把给定的坐标点阵列数组[x, y],...按照距离它们的中心点的角度进行排列
//是为了把无序排列的闭合曲线上的点进行有序排列,后续可再经过连线形成
//可填充的闭合曲线
this.angularSort = function(array) {
var a = new Array();
a = [].concat(array);
var len = a.length, len1 = a[0].length;
//不符合处理条件,不进行处理
if (len <= 0 || len1 != 2) return array;
//求中心点
var xTotal = 0, yTotal = 0, xCenter = 0, yCenter = 0;
for (var i = 0; i < len; i++) {
xTotal += a[i][0];
yTotal += a[i][1];
}
xCenter = xTotal/len;
yCenter = yTotal/len;
//求与中心点夹角并排序
var b = new Array();
var x, y, xdiff, ydiff;
for (var i = 0; i < len; i++) {
x = a[i][0];
y = a[i][1];
xdiff = x-xCenter;
ydiff = y-yCenter;
if (Math.abs(xdiff)<0.0001) {
if (ydiff > 0) {
b.push([x, y, Math.PI/2]);
}
else {
b.push([x, y, Math.PI/2*3]);
}
}
else if ( xdiff >= 0 && ydiff > 0) {//第一象限
b.push([x, y, Math.atan(Math.abs(ydiff/xdiff))]);
}
else if (xdiff < 0 && ydiff >= 0) {//第二象限
b.push([x, y, Math.PI-Math.atan(Math.abs(ydiff/xdiff))]);
}
else if (xdiff <= 0 && ydiff < 0) {//第三象限
b.push([x, y, Math.PI+Math.atan(Math.abs(ydiff/xdiff))]);
}
else {//第四象限
b.push([x, y, Math.PI*2-Math.atan(Math.abs(ydiff/xdiff))]);
}
}
b.sort(function(b1, b2) {
if (Math.abs(b1[2]-b2[2]) < 0.0001) {
//按照与中心点的距离大小排序
var d1 = (b1[0]-xCenter)*(b1[0]-xCenter)+
(b1[1]-yCenter)*(b1[1]-yCenter);
var d2 = (b2[0]-xCenter)*(b2[0]-xCenter)+
(b2[1]-yCenter)*(b2[1]-yCenter);
return -(d1-d2);
}
else {
return (b1[2]-b2[2]);
}
});
var retArray = new Array();
for (var i = 0; i < len; i++) {
//如果两个点在经过中心点的同一直线上,舍弃这个点
//因为它表示点阵列可能不是单一环,或不是闭合曲线
if (i > 0 && Math.abs(b[i][2]-b[i-1][2]) < 0.0001) continue;
retArray.push([b[i][0], b[i][1]]);
}
return retArray;
}
/**
* @usage 三视图
* @author mw
* @date 2016年02月23日 星期二 09:49:23
* @param
* @return
*
*/
this.threeView = function(array, style) {
var cubic = this.xyzSort(array);
plot.save();
plot.setTransform(1, 0, 0, 1, 0, 0)
.translate(300, 200);
//三维图和三视图
var r = 50;
style = style ? style : 'red';
var len = cubic.length;
for (var i = 0; i < len; i++) {
this.drawCubic(cubic[i][0], -cubic[i][1], cubic[i][2], r, style);
}
var height = 400;
r = r/3;
plot.setTransform(1, 0, 0, 1, 0, 0);
plot.fillText('左视图', 20, 20, 100);
plot.fillText('主视图', 20, 20+1*height/3, 100);
plot.fillText('俯视图', 20, 20+2*height/3, 100);
plot.setFillStyle(style)
.setStrokeStyle('white');
//左视图
plot.translate(100, 80);
for (var i = 0; i < len; i++) {
//y, z两坐标,z坐标变为x坐标
this.fillRect(cubic[i][2]*r, -cubic[i][1]*r, r, r);
this.strokeRect(cubic[i][2]*r, -cubic[i][1]*r, r, r);
}
//主视图
plot.translate(0, 130);
for (var i = 0; i < len; i++) {
//x, y两坐标
this.fillRect(cubic[i][0]*r, -cubic[i][1]*r, r, r);
this.strokeRect(cubic[i][0]*r, -cubic[i][1]*r, r, r);
}
//俯视图
plot.translate(0, 100);
for (var i = 0; i < len; i++) {
//x, z两坐标,z坐标变为y坐标
this.fillRect(cubic[i][0]*r, cubic[i][2]*r, r, r);
this.strokeRect(cubic[i][0]*r, cubic[i][2]*r, r, r);
}
plot.restore();
}
//绘制球体
this.sphere = function(pos/*[x, y, z]*/, r, style) {
plot.save();
var x, y;
var p = [].concat(pos);
if (p.length == 2) {
x = p[0];
y = p[1];
}
else if (p.length == 3) {
var p1 = shape.point3D(p[0], -p[1], p[2]);
x = p1[0];
y = p1[1];
}
var r0 = 0.1*r;
var grd = plot.createRadialGradient(x, y, r, x+0.3*r, y-0.3*r, r0);
grd.addColorStop(0, style);
grd.addColorStop(1, 'white');
plot.setFillStyle(grd);
shape.fillCircle(x, y, r);
plot.restore();
}
return {
fillRect:fillRect,
strokeRect:strokeRect,
fillCircle:fillCircle,
strokeCircle:strokeCircle,
strokeEllipse:strokeEllipse,
fillEllipse:fillEllipse,
//绘制点阵列
pointDraw:pointDraw,
multiLineDraw:multiLineDraw,
strokeDraw:strokeDraw,
fillDraw:fillDraw,
//多边形角度标注
angleDraw:angleDraw,
nEdge:nEdge,
nStar:nStar,
paraline:paraline,
paraquad:paraquad,
trapezoid:trapezoid,
//绘制立方体
drawCubic:drawCubic,
strokeCubic:strokeCubic,
//绘制球体
sphere:sphere,
//三维点映射
point3D:point3D,
pointLeft:pointLeft,
pointRight:pointRight,
pointTop:pointTop,
pointBottom:pointBottom,
pointFront:pointFront,
pointBack:pointBack,
//三视图
threeView:threeView,
//顶点排序
xyzSort:xyzSort,
angularSort:angularSort
};
}();
</span>
<span style="font-size:18px;">/**
* @usage 对点阵列数组进行平移,旋转,缩放,对称等变形
* @author mw
* @date 2016年03月20日 星期日 13:24:58
* @param 传入点阵列矩阵
* @return 输出变形后的点阵列矩阵
*
*/
function Transform() {
this.translate = function(array, xOffset, yOffset) {
var len = array.length;
if (len == 0) {
return [];
}
else {
var len1 = array[0].length;
if (len1 != 2) {
//如果不是点阵列[..., [x,y], [x1,y1], ...]的格式,暂时不加处理
return array;
}
else {
var retArray = new Array();
var x = 0, y = 0;
for (var i = 0; i < len; i++) {
x = array[i][0] + xOffset;
y = array[i][1] + yOffset;
retArray.push([x, y]);
}
}
}
return retArray;
}
this.scale = function(array, xScale, yScale) {
var len = array.length;
if (len == 0) {
return [];
}
else {
xScale = xScale ? xScale : 1;
yScale = yScale ? yScale : xScale;
var len1 = array[0].length;
if (len1 != 2) {
//如果不是点阵列[..., [x,y], [x1,y1], ...]的格式,暂时不加处理
return array;
}
else {
var retArray = new Array();
var x = 0, y = 0;
for (var i = 0; i < len; i++) {
x = array[i][0] * xScale;
y = array[i][1] * yScale;
retArray.push([x, y]);
}
}
}
return retArray;
}
this.rotate = function(array, angle) {
var len = array.length;
if (len == 0) {
return [];
}
else {
var len1 = array[0].length;
if (len1 != 2) {
//如果不是点阵列[..., [x,y], [x1,y1], ...]的格式,暂时不加处理
return array;
}
else {
var retArray = new Array();
var x = 0, y = 0;
var sinA, cosA;
for (var i = 0; i < len; i++) {
sinA = Math.sin(angle);
cosA = Math.cos(angle);
x = array[i][0] * cosA - array[i][1]*sinA;
y = array[i][0] * sinA + array[i][1]*cosA;
retArray.push([x, y]);
}
}
}
return retArray;
}
this.flipX = function(array) {
return this.flipImplement(array, 'X');
}
this.flipY = function(array) {
return this.flipImplement(array, 'Y');
}
this.flipXY = function(array) {
return this.flipImplement(array, 'XY');
}
//关于直线y=kx轴对称
this.flip = function(array, slope) {
//slope为斜率k
var mode = slope.toFixed(3);
return this.flipImplement(array, mode);
}
this.flipImplement = function(array, mode) {
var len = array.length;
if (len == 0) {
return [];
}
else {
var len1 = array[0].length;
if (len1 != 2) {
//如果不是点阵列[..., [x,y], [x1,y1], ...]的格式,暂时不加处理
return array;
}
else {
var retArray = new Array();
var x = 0, y = 0;
var sinA, cosA;
var m = 0, n = 0;
if (mode == 'X') {
for (var i = 0; i < len; i++) {
//关于X轴对称,
x = array[i][0];
y = -array[i][1];
retArray.push([x, y]);
}
}
else if (mode == 'Y') {
for (var i = 0; i < len; i++) {
//关于Y轴对称,
x = -array[i][0];
y = array[i][1];
retArray.push([x, y]);
}
}
else if (mode == 'XY') {
for (var i = 0; i < len; i++) {
//中心对称
x = -array[i][0];
y = -array[i][1];
retArray.push([x, y]);
}
}
else {
//模式为斜率 y = kx中k的字符串
k = parseFloat(mode);
for (var i = 0; i < len; i++) {
//可扩展
//此处先放大100倍再缩小是因为对于小尺寸
//计算误差太大,而如果尺寸太大,
//标注会占用太多地方,造成文字拥挤,无法读取
m = array[i][0]*10000;
n = array[i][1]*10000;
//x = (m-2*k+2*k*n-m*k*k)/(1+k*k);
x = (1-k*k)*m+2*k*(n-1)/(1+k*k);
//y = (-n+2*k*m+n*k*k)/(1+k*k);
y = (2*k*m-(1-k*k)*n)/(1+k*k);
retArray.push([x/10000, y/10000]);
}
}
}
}
return retArray;
}
}</span>
<span style="font-size:18px;">/**
* @usage 数学表达式,代数式的书写
* @author mw
* @date 2016年03月12日 星期六 11:05:12
* @param
* @return
*
*/
function MathText() {
//上标标记形式为...^[内容]...
//分数不进行处理, 根式不进行处理,都转成指数式进行
//特殊数学符号设想加\[alpha]进行转义,待续
//可以进行指数上标代数式的书写
//可扩展下标,待续
this.setNormalFont = function() {
plot.setFont("normal normal normal 24px Times Lt Std");
}
this.setScriptFont = function() {
plot.setFont("italic normal bold 16px Dark Courier ");
}
this.print = function(text, xPos, yPos) {
xPos = xPos ? xPos : 0;
yPos = yPos ? yPos : 0;
plot.save();
var s = text ? text : '';
if (s != '') {
s = s.replace(/\/\//ig, '÷');
s = s.replace(/>=/ig, '≥');
s = s.replace(/<=/ig, '≤');
s = s.replace(/!=/ig, '≠');
s = s.replace(/pi/ig, 'π');
}
//字符串长度
var len = s.length;
//不同字体大小设置在此
var r1 = 20;
//单个字符暂存处
var c;
//文本显示位置
var x = xPos, y = yPos;
//正常文本暂存
var s0 = '';
//字符串打印长度
var measure;
//记录上一个x位置,可记录三层
var xMem = [x, x, x];
//记录每一层的左括号位置
var bracketPos = [x, x, x];
//记录括号层次
var bracketsLevel = 0;
//记录根号层次
var radicalLevel = 0;
//记录每一层根号的起始位置和层次数的数组...[[start, end, level], ...]
var radicalSpan = [];
//设置正常字体
this.setNormalFont();
for (var i = 0; i < len; i++) {
if (s[i] == '_') {
//下标开始
//下标标记形式为..._[内容]...
if (s0 != '') { //先把正常字符打印出
if (r1 != 20) { //字体字号大小还在上标状态
r1 = 20;
this.setNormalFont();
}
measure = plot.measureText(s0);
plot.fillText(s0, x, y, measure);
s0 = '';
x += measure;
}
var subScript = '';
var j = 0;
for (j = i+1; s[j]!=']'; j++) {
if (s[j] != '[') {
subScript+=s[j];
}
}
if (r1 != 10) {//正常字体状态,需要改为上标字体
r1 = 10;
this.setScriptFont();
}
measure = plot.measureText(subScript);
plot.fillText(subScript, x, y+8, measure);
if (j < len-1 && s[j+1] == '^') {
}
else {
x += 1.2*measure;
}
i = j;
}
else if (s[i] == '^') {
//上标开始
//上标标记形式为...^[内容]...
if (s0 != '') { //先把正常字符打印出
if (r1 != 20) { //字体字号大小还在上标状态
r1 = 20;
this.setNormalFont();
}
measure = plot.measureText(s0);
plot.fillText(s0, x, y, measure);
s0 = '';
x += measure;
}
var upperScript = '';
var j = 0;
for (j = i+1; s[j]!=']'; j++) {
if (s[j] != '[') {
upperScript+=s[j];
}
}
//二次根式
if (upperScript == '1/2' || upperScript == '0.5') {
var x1, y1;
if (i > 0 && s[i-1] == ')') {
x1 = bracketPos[bracketsLevel];
}
else {
x1 = xMem[bracketsLevel];
}
/* 存疑代码
if (radicalSpan == []) {
radicalLevel = 0;
radicalSpan.push([x1, x, radicalLevel]);
}
else {
var len = radicalSpan.length;
for (var k = 0; k < len; k++) {
if (x1 < radicalSpan[k][0]) {
radicalLevel = radicalSpan[k][2]+1;
break;
}
if (k >= len-1) {
radicalLevel = 0;
}
}
radicalSpan.push([x1, x, radicalLevel]);
}*/
y1 = y-20-5*radicalLevel;
plot.save()
.setLineWidth(1);
plot.beginPath()
.moveTo(x1-5, y+5)
.lineTo(x1-8, y-3)
.moveTo(x1-5, y+5)
.lineTo(x1+5, y1)
.moveTo(x1+5, y1)
.lineTo(x, y1)
.closePath()
.stroke();
plot.restore();
}
else {
if (r1 != 10) {//正常字体状态,需要改为上标字体
r1 = 10;
this.setScriptFont();
}
measure = plot.measureText(upperScript);
plot.fillText(upperScript, x, y-8, measure);
if (j < len-1 && s[j+1] == '_') {
}
else {
x += 1.2*measure;
}
}
//直接跳跃过上标字符区段
i = j;
}
else {
c = s[i];
if (c == ')') {
s0 += c;
bracketsLevel -= 1;
}
else if (c == '(') {
//如果整个括号被开根式,根号在括号左边
bracketPos[bracketsLevel] = x + plot.measureText(s0);
s0 += c;
bracketsLevel+=1;
//过了括号就是过了一道关,要刷新坐标
xMem[bracketsLevel] = x + plot.measureText(s0);
}
else if (c == '+' || c == '-' || c == '*' || c == '/' || c == '÷'
|| c == '=' || c == ' ') {
if (c == '*') {
if (i > 0 && /[0-9]/.test(s[i-1]) && /[0-9]/.test(s[i+1])) {
//对于乘号前后都是数字的情况,把乘号改成叉号
c = ' \u00D7 ';
}
else {
//对于代数式中,乘号改为点号
c = ' \u00B7 ';
}
}
//如果是运算符后的数被开根式,根号在运算符右边
if (c == '-' || c == '/') {
s0 += ' '+c+' ';
}
else {
s0 += c;
}
if (bracketsLevel < 3) {
xMem[bracketsLevel] = x+plot.measureText(s0);
}
}
else {
s0 += c;
}
}
}
if (s0 != '') { //先把正常字符打印出
if (r1 != 20) { //字体字号大小还在上标状态
r1 = 20;
this.setNormalFont();
}
measure = plot.measureText(s0);
plot.fillText(s0, x, y, measure);
x += measure;
}
plot.restore();
}
}
//文本显示方便类
function DrawText() {
this.protype = function(str, xPos, yPos, traits, rotate, style, fontSize, alignment) {
//traits参数指定了显示正常/加粗/斜体等区别
//style 是颜色/渐变的区别
//fontSize是字体字号的区别
//alignment是对齐方式的区别
rotate = rotate ? rotate : 0;
style = style ? style : 'black';
fontSize = fontSize >= 10 ? fontSize : 20;
//左对齐0, 中对齐1, 右对齐2
alignment = alignment ? alignment : 'L';
var tmp = fontSize.toFixed(0)+'px';
var font = '';
if (traits == 'normal') {
font = "normal normal normal "+tmp+" Times New Roman";
}
else if (traits == 'bold') {
font = 'normal normal 800 '+tmp+' Arial';
}
else if (traits == 'italic') {
font = 'italic normal bold '+tmp+' Microsoft Sans Serif';
}
else {
font = "normal normal normal "+tmp+" Times New Roman";
}
plot.save()
.setFont(font)
.setFillStyle(style)
.translate(xPos, yPos)
.rotate(-rotate);
var x = 0, y = 0;
var measure = 0;
var s = '';
//多行
var len = str.length;
for (var i = 0; i < len; i++) {
s = str[i];
measure = plot.measureText(s);
if (alignment == 1 || alignment.toUpperCase() == 'M' || alignment.toUpperCase() == 'C'){
//[x,y]为居中对齐的中点
plot.fillText(s, x-measure/2, y, measure);
}
else if (alignment == 2 || alignment.toUpperCase() == 'R'){
//[x,y]为右对齐的右边边界点
plot.fillText(s, x-measure, y, measure);
}
else {
//于[x,y]处左对齐
plot.fillText(s, x, y, measure);
}
y += fontSize*1.5;
}
plot.restore();
}
this.normal = function(str, xPos, yPos, rotate, style, fontSize, alignment) {
return this.protype(str, xPos, yPos, 'normal', rotate, style, fontSize, alignment);
}
this.bold = function(str, xPos, yPos, rotate, style, fontSize, alignment) {
return this.protype(str, xPos, yPos, 'bold', rotate, style, fontSize, alignment);
}
this.italic = function(str, xPos, yPos, rotate, style, fontSize, alignment) {
return this.protype(str, xPos, yPos, 'italic', rotate, style, fontSize, alignment);
}
}
</span>
当然,每次小伟都只会用到其中的一小部分,但为了防止遗漏,还是都贴出来比较好。
本节到此结束,欲知后事如何,请看下回分解。