您的位置:首页 > Web前端 > HTML5

【实例】html5-canvas绘制线段、矩形和圆

2015-08-15 19:50 756 查看

关键点

鼠标按住之后实现绘图的预览,松手之后才真正画在canvas中
绘制圆形的时候需要对圆的大小方位进行控制
需要对当前鼠标的坐标进行精准的定位

代码实现

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style type="text/css">
#canvas {
border: thin solid black;
cursor: crosshair;
}
</style>
</head>
<body>
<div id="controls">
辅助线间距<input id="step" type="number"/>
辅助线颜色
<select id="color">
<option value="rgba(255,0,0,0.2)">红</option>
<option value="rgba(0,255,0,0.2)">绿</option>
<option value="rgba(0,0,255,0.2)">蓝</option>
</select>
<input type="button" value="生成" id="createButton">
类型:
<label for="line">线段
<input type="radio" name="drawType" id="line" value="line" checked="checked" onclick="drawType='line'"/>
</label>
 
<label for="rect">长方形
<input type="radio" name="drawType" id="rect" value="rect"  onclick="drawType='rect'"/>
</label>
 
<label for="circle">圆形
<input type="radio" name="drawType" id="circle" value="circle"  onclick="drawType='circle'"/>
</label>
<p id="message"></p>
</div>
<canvas id="canvas" width="1200" height="800"></canvas>
</body>
<script type="text/javascript">
var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
//当前绘制线段的起点
var startPoint = {};
//是否进行绘制的开关
var isDraw = false;
//保存鼠标拖动之前canvas的数据
var contextDate = null;
//绘制的图形,默认是线段
var drawType = "line";

var createButton = document.getElementById("createButton");
createButton.onclick = function() {
var step = document.getElementById("step").value;
var color = document.getElementById("color").value;
drawGuidesLine(parseInt(step), color);
}

//绘制水平线,水平线只有y坐标会变,横坐标一直是从0到canvas.width
function drawHorizontalLine(y) {
context.beginPath();
context.moveTo(0, y);
context.lineTo(canvas.width, y);
context.stroke();
}
//绘制竖直线,竖直线只有x坐标会变,纵坐标一直是从0到canvas.height
function drawVerticalLine(x) {
context.beginPath();
context.moveTo(x, 0);
context.lineTo(x, canvas.height);
context.stroke();
}
//绘制辅助线
function drawGuidesLine(step ,color) {
context.clearRect(0, 0, canvas.width, canvas.height);
context.strokeStyle = color;
for(var i = 0; i < canvas.height; i+=step) {
drawHorizontalLine(i+0.5);
}
for(var i = 0; i < canvas.width; i+=step) {
drawVerticalLine(i+0.5);
}
}
function getLocation(e) {
var bbox = document.getElementById("canvas").getBoundingClientRect();
return {
x: e.clientX - bbox.left * (canvas.width/bbox.width),
y: e.clientY - bbox.top * (canvas.height/bbox.height)
};
}
function drawLine(startPoint,  endPoint) {
context.save();
context.beginPath();
context.moveTo(startPoint.x, startPoint.y);
context.lineTo(endPoint.x, endPoint.y);
context.stroke();
context.closePath();
}
//绘制矩形方法
function drawRect(startPoint, endPoint) {
context.save();
context.beginPath();
context.strokeRect(startPoint.x, startPoint.y,
endPoint.x-startPoint.x, endPoint.y-startPoint.y);
context.stroke();
context.closePath();
}
//绘制圆形方法
function drawCircle(startPint, endPoint) {
context.save();
context.beginPath();
//按照windows自带的画图工具的样子
//先假想画出一个正方形
//实际绘制的是与这个矩形四条边都相切的圆形
//我想到了arcTo

//坐标转换,因为画的是正圆形,所以虚拟的那个矩形就只能是正方形,我们画出来的线段应该是正方形的对角线
//可如果不能满足正方形对角线的条件的话,我们就得转化了。
//转化方式是以画出矩形的最短的那个边为正方形的边,绘制新的正方形(虚拟)
//起始点和终止点之间横纵坐标的差值
var distX = Math.abs(endPoint.x - startPoint.x);
var distY = Math.abs(endPoint.y - startPoint.y);
if(distX > distY) {
//我们需要把起点到终点的X轴距离也设置成distY
if(endPoint.x > startPoint.x) {
//终点在起点之后
endPoint.x = startPint.x + distY;
} else {
//终点在起点之前
endPoint.x = startPoint.x - distY;
}
} else {
if(endPoint.y > startPoint.y) {
//终点在起点之后
endPoint.y = startPint.y + distX;
} else {
//终点在起点之前
endPoint.y = startPoint.y - distX;
}
}
//			drawRect(startPoint, endPoint);
//此时我们才有了真正需要的正方形的坐标(其实是他的对角线)
var radius = Math.abs(endPoint.x - startPoint.x) / 2;
if(startPoint.x > endPoint.x) {
context.moveTo(startPoint.x - radius, startPoint.y);
} else {
context.moveTo(startPoint.x + radius, startPoint.y);
}

context.arcTo(endPoint.x, startPoint.y, endPoint.x, endPoint.y, radius);
context.arcTo(endPoint.x, endPoint.y, startPoint.x, endPoint.y, radius);
context.arcTo(startPoint.x, endPoint.y, startPoint.x, startPoint.y, radius);
if(startPint.x > endPoint.x) {
context.arcTo(startPoint.x, startPoint.y, startPoint.x - radius, startPoint.y, radius);
} else {
context.arcTo(startPoint.x, startPoint.y, startPoint.x + radius, startPoint.y, radius);
}

context.stroke();
context.closePath();
}
//保存当前画布的数据,主要用来在鼠标按住拖动的时候恢复到鼠标按下时时的样子,防止在鼠标拖动过程中绘制图像上去
function saveImageData() {
contextDate = context.getImageData(0, 0, canvas.width, canvas.height);
}
function restoreImageData() {
context.putImageData(contextDate, 0, 0);
}
canvas.onmousedown = function(e) {
context.strokeStyle = "black";
startPoint = getLocation(e);
isDraw = true;
saveImageData();
};
canvas.onmousemove = function(e) {
if(isDraw) {
restoreImageData();
//通过对drawType来辨别应该画什么图形
if(drawType == "line") {
drawLine(startPoint, getLocation(e));
} else if(drawType == "rect"){
drawRect(startPoint, getLocation(e));
} else if(drawType == "circle") {
drawCircle(startPoint, getLocation(e));
}
}
};
canvas.onmouseup = function(e) {
isDraw = false;
};
</script>
</html>
在线演示

其实这个Demo没什么技术含量,其中绘制圆形的时候我不是通过arc而是先假想的绘制出一个正方形,之后在那个正方形中内切一个圆形来实现的。现在想想用arc方法应该更容易一吧。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: