您的位置:首页 > 其它

Canvas---Canvas版画图,坐标轴绘制,网格绘制,橡皮筋式画直线

2015-01-25 17:32 375 查看
使用Canvas实现画图程序。


这个量还是比较大的,请允许我慢慢来。

目前做到了:坐标轴的绘制,网格绘制,橡皮筋式画直线

目前的不足:没有应用多个图层将网格,坐标轴与实际绘画区域分离

接下要做:为橡皮筋式画直线添加上辅助线选项

----------------------------------------------------------------------



----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

下面是源码:

①本体代码

<!docutype html>
<!--date 2014-12-28-->
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<style type="text/css">
canvas{

}
</style>
<script type = "text/javascript" src ="mikuCanvasAxes.js"></script>
</head>
<body>
<div class="controls">
网格线<input  id="gridCheckBox" type="checkbox" checked="checked" >
坐标轴<input  id="axesCheckBox" type="checkbox" checked="checked" >
<input type="button" value="清除画布" id="eraseAllButton">
</div>
<!--canvas默认大小300*150-->
<canvas id="canvas" width="800" height="500">
</canvas>
</body>
<script type="text/javascript">
//Vars--------------------------------------------------------
var canvas =document.getElementById("canvas"),
context =canvas.getContext("2d"),
//正在绘制的绘图表面变量
drawingSurfaceImageData,
//鼠标按下相关对象
mousedown = {},
//橡皮筋矩形对象
rubberbandRect = {},
//拖动标识变量
dragging = false;
//控制对象
var eraseAllButton = document.getElementById("eraseAllButton"),
axesCheckBox = document.getElementById("axesCheckBox"),
//检测axesCheckBox是否被选中
haveAxes = axesCheckBox.checked;
var gridCheckBox = document.getElementById("gridCheckBox");
var haveGrid = gridCheckBox.checked;
//Functions---------------------------------------------------
//将窗口坐标转换为Canvas坐标
//传入参数:窗口坐标(x,y)
function windowToCanvas(x,y){
//获取canvas元素的边距对象
var bbox = canvas.getBoundingClientRect();
//返回一个坐标对象
//类似json的一种写法
return {
x : x - bbox.left*(canvas.width/bbox.width),
y : y - bbox.top*(canvas.height/bbox.height)
};
}
//保存当前绘图表面数据
function saveDrawingSurface(){
//从上下文中获取绘图表面数据
drawingSurfaceImageData = context.getImageData(0,0,canvas.width,canvas.height);
}
//还原当前绘图表面
function restoreDrawingSurface(){
//将绘图表面数据还原给上下文
context.putImageData(drawingSurfaceImageData,0,0);
}
//橡皮筋相关函数

//更新橡皮筋矩形+对角线
//传入参数:坐标对象loc
function updateRubberband(loc){
updateRubberbandRectangle(loc);
drawRubberbandShape(loc);
}
//更新橡皮筋矩形
//传入参数:坐标对象loc
function updateRubberbandRectangle(loc){
//获得矩形的宽
rubberbandRect.width = Math.abs(loc.x - mousedown.x);
//获得矩形的高
rubberbandRect.height = Math.abs(loc.y - mousedown.y);
//获得矩形顶点的位置(left,top)
//如果鼠标按下的点(起点)在当前点的的左侧
//这里画一下图就懂了
if(loc.x > mousedown.x){
rubberbandRect.left = mousedown.x;
}else{
rubberbandRect.left = loc.x;
}
if(loc.y > mousedown.y){
rubberbandRect.top = mousedown.y;
}else{
rubberbandRect.top = loc.y;
}
}
//绘制橡皮筋矩形的对角线
//传入参数:坐标对象loc
function drawRubberbandShape(loc){
//alert("draw");
context.beginPath();
context.moveTo(mousedown.x,mousedown.y);
context.lineTo(loc.x,loc.y);
context.stroke();
}
//事件处理-----------------------------------------------------
canvas.onmousedown = function(e){
var loc =windowToCanvas(e.clientX,e.clientY);
e.preventDefault();
saveDrawingSurface();
mousedown.x = loc.x;
mousedown.y = loc.y;
dragging = true;
}

canvas.onmousemove = function(e){
var loc;
if(dragging){
e.preventDefault();
loc = windowToCanvas(e.clientX,e.clientY);
restoreDrawingSurface();
updateRubberband(loc);
}
}
canvas.onmouseup = function(e){
loc = windowToCanvas(e.clientX,e.clientY);
restoreDrawingSurface();
updateRubberband(loc);
dragging = false;
}
eraseAllButton.onclick = function(e){
context.clearRect(0,0,canvas.width,canvas.height);
initialization();
saveDrawingSurface();
}
axesCheckBox.onchange = function(e){
haveAxes = axesCheckBox.checked;
initialization();
}
gridCheckBox.onchange = function(e){
haveGrid = gridCheckBox.checked;
initialization();
}
//Initialization----------------------------------------------
function initialization(){
//清除画布
context.clearRect(0,0,canvas.width,canvas.height);
if(haveAxes){
drawAxes(context,40);
}
if(haveGrid){
drawGrid(context,10,10);
}
}
//入口
initialization();
</script>
</html>

②绘制网格与坐标轴的js文件

//Classes----------------------------------------------------
function mikuLoc(locX,locY){
this.x = locX;
this.y = locY;
}
//Contents---------------------------------------------------
var GRID_STYLE  = "lightgray",
GRID_LINE_WIDTH = 0.5;

var AXES_STYLE  = "#a2a2a2",
AXES_LINE_WIDTH = 1,
VERTICAL_TICK_SPACING = 10,
HORIZONTAL_TIKE_SPACING = 10,
TICK_WIDTH = 10;
//Function---------------------------------------------------
//绘制网格
//传入参数为:绘图环境,x轴间隔,y轴间隔
function drawGrid(context,stepx,stepy){
context.save();
context.strokeStyle = GRID_STYLE;
//设置线宽为0.5
context.lineWidth   = GRID_LINE_WIDTH;
//绘制x轴网格
//注意:canvas在两个像素的边界处画线
//由于定位机制,1px的线会变成2px
//于是要+0.5
for(var i=stepx+0.5;i<context.canvas.width;i=i+stepx){
//开启路径
context.beginPath();
context.moveTo(i,0);
context.lineTo(i,context.canvas.height);
context.stroke();
}
//绘制y轴网格
for(var i=stepy+0.5;i<context.canvas.height;i=i+stepy){
context.beginPath();
context.moveTo(0,i);
context.lineTo(context.canvas.width,i);
context.stroke();
}
context.restore();
};
//Function---------------------------------------------------
//绘制坐标轴
//传入参数为:绘图环境,坐标轴边距
function drawAxes(context,axesMargin){
//保存样式
context.save();
var originLoc = new mikuLoc(axesMargin, context.canvas.height-axesMargin);
var axesW = context.canvas.width  - (axesMargin*2),
axesH = context.canvas.height - (axesMargin*2);
//设置坐标绘图样式绘图样式
context.strokeStyle   =  AXES_STYLE;
context.lineWidth =   AXES_LINE_WIDTH;
//绘制x,y轴
drawHorizontalAxis();
drawVerticalAxis();
drawVerticalAxisTicks();
drawHorizontalAxisTicks();
//恢复样式
context.restore();

//绘制x轴
function drawHorizontalAxis(){
context.beginPath();
context.moveTo(originLoc.x, originLoc.y);
context.lineTo(originLoc.x + axesW, originLoc.y);
context.stroke();
}
//绘制y轴
function drawVerticalAxis(){
context.beginPath();
context.moveTo(originLoc.x, originLoc.y);
context.lineTo(originLoc.x, originLoc.y - axesH);
context.stroke();
}
//绘制垂直轴小标标
function drawVerticalAxisTicks(){
var deltaX;
//当前垂直tick的y轴坐标
var nowTickY =originLoc.y-VERTICAL_TICK_SPACING;
for(var i=1;i<=(axesH/VERTICAL_TICK_SPACING);i++){
if(i%5 === 0){
deltaX=TICK_WIDTH;
}else {
deltaX=TICK_WIDTH/2;
}
context.beginPath();
//移动到当前的tick起点
context.moveTo(originLoc.x-deltaX,nowTickY);
context.lineTo(originLoc.x+deltaX,nowTickY);
context.stroke();
nowTickY=nowTickY-VERTICAL_TICK_SPACING;
}
}
//绘制水平轴小标标
function drawHorizontalAxisTicks(){
var deltaY;
var nowTickX = originLoc.x+HORIZONTAL_TIKE_SPACING;
for(var i=1;i<=(axesW/HORIZONTAL_TIKE_SPACING);i++){
if(i%5 === 0){
deltaY = TICK_WIDTH;
}else{
deltaY = TICK_WIDTH/2;
}
context.beginPath();
context.moveTo(nowTickX,originLoc.y+deltaY);
context.lineTo(nowTickX,originLoc.y-deltaY);
context.stroke();
nowTickX = nowTickX + HORIZONTAL_TIKE_SPACING;
}
}
};



内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: