[Canvas绘图] 第02节 今日看“点"

本节目标:
(1) 封装map类
(2) 绘制坐标系
(3) 简单函数绘制


实现步骤:

续前节,有了画布,就想要画一些东西,就从最简单的“点”开始吧。点是和函数关系在一起的,怎样画出漂亮的函数图形呢?

在画出函数以前,我先想到了一个问题,怎样查看函数上各个点的坐标值?

今天就从这里开始。

我第一步,建立了一个Html表,用于显示数值,设计得非常简单。这个表通过一个函数给它刷数据:

/**
* @usage   查看数据的表格
* @author  mw
* @date    2015年11月28日  星期六  13:00:45 
* @param
* @return
*
*/
	function mytable() {
		var table = $$("table");
		
		//找<tbody>
		var node = table.firstChild;

		while (null != node) {
		/*
			想知道都有哪些子节点,用这个
				var text = document.createTextNode(node.nodeName);
				document.body.appendChild(text);
		*/
				
			if ("TBODY" == node.nodeName) 
				break;			

			node = node.nextSibling;
		}
		
		//生成映射数据
		var xArray = genData(10);
		var yArray = linearMap(xArray);

		//单元格插入
		for (var i = 0; i<10; i++) {
			//插入<tr>			
			var tr = document.createElement("tr")			
			
			//插入<td> x
			var td = document.createElement("td");
			var x = document.createTextNode(xArray[i].toFixed(3));
			td.appendChild(x);
			tr.appendChild(td);
			
			//插入<td> y
			var td = document.createElement("td");
			var y = document.createTextNode(yArray[i].toFixed(3));
			td.appendChild(y);
			tr.appendChild(td);

			
			node.appendChild(tr);
		}		
	}

下面来看看效果怎样:


验证可行,接着进行下一步。

这里用到一个随机数生成函数,这样就可以省去没有数据可用的麻烦,这个函数很小巧。

/**
* @usage   生成X轴测试随机数据
* @author  mw
* @date    2015年11月28日  星期六  12:10:34 
* @param
* @return
*
*/	
	function genData(n) {
		var xArray = new Array();
		
		//生成n个随机数
		for (var i = 0; i < n; i++) {
			var x = Math.random() * 200 - 100;
			xArray.push(x); //值在-100到100之间
		}
		
		return xArray;
	
	}

然后定义了两个简单的函数,分别是一个直线方程,和一个sin函数。

/**
* @usage   直线函数映射
* @author  mw
* @date    2015年11月28日  星期六  12:11:59 
* @param
* @return
*
*/
	function linearMap(xArray) {
		var yArray = new Array();
		//直线方程y = kx + b
		var k = -1;
		var b = 0;
		for (var i = 0; i < xArray.length; i++) {
			var y = k * xArray[i] + b;
			yArray.push(y);
		}
		
		return yArray;
	}
	
	
/**
* @usage   正弦函数映射
* @author  mw
* @date    2015年11月28日  星期六  14:10:11 
* @param
* @return
*
*/			

	function sinMap(xArray) {
		var yArray = new Array();
		//方程y = sin(x)

		for (var i = 0; i < xArray.length; i++) {
			var y = 100* Math.sin(xArray[i]/100*Math.PI*2);
			yArray.push(y);
		}
		
		return yArray;
	}

有了这两个函数,就可以去验证接下来要设计的map容器的可靠程度了。

于是去设计map。

/**
* @usage  映射类map
* @author  mw
* @date    2015年11月28日  星期六  08:01:13 
* @param
* @return
*
*/

function Map(){  
    /** 存放键的数组(遍历用到) */    
    this.keys = new Array();     
    /** 存放数据 */    
    this.data = new Object();     
         
    /**   
     * 放入一个键值对   
     * @param {String} key   
     * @param {Object} value   
     */    
    this.put = function(key, value) {     
        if(this.data[key] == null){     
            this.keys.push(key);    
			this.data[key] = new Array();
        }     
        this.data[key].push(value);     
    };     
         
    /**   
     * 获取某键对应的值   
     * @param {String} key   
     * @return {Object} value   
     */    
    this.get = function(key) {     
        return this.data[key];     
    };     
         
    /**   
     * 删除一个键值对   
     * @param {String} key   
     */    
    this.remove = function(key) {     
        this.keys.remove(key);     
        this.data[key] = null;     
    };     
         
    /**   
     * 遍历Map,执行处理函数   
     *    
     * @param {Function} 回调函数 function(key,value,index){..}   
     */    
    this.each = function(fn){     
        if(typeof fn != 'function'){     
            return;     
        }     
        var len = this.keys.length;     
        for(var i=0;i<len;i++){     
            var k = this.keys[i];     
            fn(k,this.data[k],i);     
        }     
    };     
         
    /**   
     * 获取键值数组(类似Java的entrySet())   
     * @return 键值对象{key,value}的数组   
     */    
    this.entrys = function() {     
        var len = this.keys.length;     
        var entrys = new Array(len);     
        for (var i = 0; i < len; i++) {     
            entrys[i] = {     
                key : this.keys[i],     
                value : this.data[i]     
            };     
        }     
        return entrys;     
    };     
         
    /**   
     * 判断Map是否为空   
     */    
    this.isEmpty = function() {     
        return this.keys.length == 0;     
    };     
         
    /**   
     * 获取键值对数量   
     */    
    this.size = function(){     
        return this.keys.length;     
    };     
         
    /**   
     * 重写toString    
     */    
    this.toString = function(){     
        var s = "{";     
        for(var i=0;i<this.keys.length;i++,s+=','){     
            var k = this.keys[i];     
            s += k+"=";
			for (var j=0; j<this.data[k].length;j++,s+=',') {
				s+=this.data[k][j];   
			}
        }     
        s+="}";     
        return s;     
    };   
}  

现在好像材料都准备好了,可以写个绘图试试。

/**
* @usage   绘制Demo
* @author  mw
* @date    2015年11月28日  星期六  13:00:45 
* @param
* @return
*
*/
	function myplot_2015_11_28() {
		setPreference();			

		//生成映射数据
		var xArray = genData(100);
		xArray = xArray.sort();
		var yArray = linearMap(xArray);
		
		var xArray2 = genData(100);
		var yArray2= sinMap(xArray2);
		
		axis(300,200,190);
		
		//绘制
		plot.setTransform(1.5,0,0,1.5, 300,200);		
		
		/*
		//第一种取数据法
		for (var i=0; i<xArray.length; i++) {
			fillCircle(xArray[i],-yArray[i],2);
		}
		*/

		//第二种取数据法
		var xyMap = new Map();
		//第一个函数
		for (var i = 0; i < xArray.length; i++) {
			xyMap.put(xArray[i], yArray[i]);
		}
		//第二个函数
		for (var i = 0; i < xArray2.length; i++) {
			xyMap.put(xArray2[i], yArray2[i]);
		}
		
		//绘出映射
		if (!xyMap.isEmpty()) {
			
			for (var i=0; i <xyMap.size(); i++) {
				var x = xyMap.keys[i];
				var y = xyMap.get(x);
				
				for (var j=0;j<y.length;j++) {
					fillCircle(x,y[j],2);
				}	
			}
		}
		
		/*
		//数据检查
		var text = document.createTextNode(xyMap.toString());
		document.body.appendChild(text);
		*/

	}

有了map,图形可以更精彩,来看看效果吧。


坐标轴的函数,还是比较费事的。

/**
* @usage   绘制直角坐标系
* @author  mw
* @date    2015年11月28日  星期六  14:17:34 
* @param
* @return
*
*/

	function axis(x, y, r) {
		plot.beginPath()
			.moveTo(x-r,y)
			.lineTo(x+r,y)
			.closePath()
			.stroke();
			
		plot.beginPath()
			.moveTo(x,y-r)
			.lineTo(x,y+r)
			.closePath()
			.stroke();
		
		plot.setFillStyle('black');
		
		var r0 = 10;
		
		//x轴箭头
		plot.beginPath()
			.moveTo(x+r- r0*Math.cos(Math.PI/3), y-r0*Math.sin(Math.PI/3))
			.lineTo(x+r+r0*Math.sin(Math.PI/3), y)
			.lineTo(x+r -r0*Math.cos(Math.PI/3), y+r0*Math.sin(Math.PI/3))
			.closePath()
			.fill()
		
		//y轴箭头
		plot.beginPath()
			.moveTo(x+ r0*Math.sin(Math.PI/3), y-r+r0*Math.cos(Math.PI/3))
			.lineTo(x, y-r-r0*Math.sin(Math.PI/3))
			.lineTo(x-r0*Math.sin(Math.PI/3), y-r+r0*Math.cos(Math.PI/3))
			.closePath()
			.fill()
		
		plot.setFillStyle('#666666');
}
这一节就到这里。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值