代码改变世界

利用canvas制作最简易的画板

2012-08-14 12:33  @影子@  阅读(1784)  评论(1编辑  收藏  举报

HTML5 横空出世,怎能不提神奇的 canvas。还记得多年前小探 GDI 和 opengl 时的心潮澎湃,那时一心想在web中实现画板功能,但困惑于如何在 html 中嵌入 c++ 编译后的 exe 文件。后来,flash 和 flash3D 的发展让人没理由再去纠结这个问题,在 web 中嵌入一个 swf 相比 exe 要轻松多啦。直到有一天,WHATWG 的那组人向世界宣称 HTML5 添加了对脚本和布局之间的原生交互能力,他们的目标是和插件说再见。哇,这太让人激动,当禁用屏蔽安装失败的隐患消除之后,世界将变得更加和谐,于是渺小的我,从 canvas 开始,开启 Html5 的入门之旅。

首先要提的是 canvas 不是所有浏览器都支持,到目前为止,最新的 chrome,firefox,safari,opera 都支持 canvas,except 万恶的IE,IE真是说有多么可恶就有多么可恶啊!!

<!--[if lt IE 9]>
 <script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->

其次,canvas 的使用方式基本遵循如下的顺序:

1、获取 canvas 对象,可以用 getElementById 可以用 querySelector (也是IE不支持) 还可以用 jquery 的选择器,var canvas = document.querySelector('canvas');

2、关联到 canvas 的上下文,指定 2D 的模式。 var context = canvas.getContext('2d');

3、保存之前的绘图 save

4、应用变形,scale、transform、shdow

5、开始记录需要绘制的路径,可以是直线,曲线

6、填充或者绘图,stroke、fill

7、重置 restore

最后,来小试牛刀,想要实现简易的画板,那么只要完成几个步骤

1、鼠标在 canvas 里面 mousemove 的时候要获取鼠标的位置 (posX,posY)

2、获取 canvas 顶点的坐标, canvas.left(), canvas.top()

3、由此可以获得 mousemovede 的时候鼠标点 point 相对于 canvas 原点的坐标为 (posX-canvas.left(),posY-canvas.top())

4、以鼠标 point 的位置为圆心,小圆点作为笔触

代码贴在后面供参考,其中获取canvas起点的坐标用了三种写法,分别为(其中的优缺点不言自明,推崇第二种写法):

screenPosition(canvas).left canvas.left()、getLeft(canvas)
screenPosition(canvas).top canvas.top()、getTop(canvas)
<!DOCTYPE html>
<html>
  <title>HTML5 Canvas Example</title>

  <style type="text/css">
    canvas {background-image: url("flower.jpg");
            border: 1px solid ; 
  }
  </style>

  <h1>Magical Canvas,Let's begin!</h1>
  <canvas class="clear" width="300" height="300"> </canvas>
  <button>Reset</button>
  <script>
  var resetBtn = document.querySelector('button');
  var canvas = document.querySelector('canvas');
  var context = canvas.getContext('2d');

  function reset(){
    context.clearRect(0,0,300,300);
    
  }

  function move(e){
    var posX = mousePosition(e).x;
    var posY = mousePosition(e).y;
    var x = posX - canvas.left();
    var y = posY - canvas.top();
    drawHeatPoint(x, y, context);
  }

  function drawHeatPoint(x,y,context){
    context.save();
    context.fillStyle = 'yellow';

    context.beginPath();
    context.arc(x,y,3,0,Math.PI*2,true);
    context.closePath();
    context.fill();
    context.restore();
  }

  function mousePosition(e) {  
  return {  
          x : e.clientX + document.documentElement.scrollLeft - document.documentElement.clientLeft,  
          y : e.clientY + document.documentElement.scrollTop - document.documentElement.clientTop  
      };  
  } 

  function screenPosition(e){
    var offsetTop=e.offsetTop;
    var offsetLeft=e.offsetLeft;
     if(e.offsetParent!=null){
        offsetTop += arguments.callee(e.offsetParent);
        offsetLeft += arguments.callee(e.offsetParent);
     } 
    return{
      top:offsetTop,
      left:offsetLeft
    };
  }

  canvas.top = function(){
      var offset=this.offsetTop;
      if(this.offsetParent!=null) offset+=getTop(this.offsetParent);
      return offset;
  }

  canvas.left = function(){
      var offset=this.offsetLeft;
      if(this.offsetParent!=null) offset+=getLeft(this.offsetParent);
      return offset;
  }

  //获取元素的纵坐标
  function getTop(e){
  var offset=e.offsetTop;
  if(e.offsetParent!=null) offset+=getTop(e.offsetParent);
  return offset;
  }
  //获取元素的横坐标
  function getLeft(e){
  var offset=e.offsetLeft;
  if(e.offsetParent!=null) offset+=getLeft(e.offsetParent);
  return offset;
  } 

   resetBtn.addEventListener('click',reset,true);
   canvas.addEventListener('mousemove',move,true);
  </script>
</html>