HTML5 之 绘图板
<!DOCTYPE html><html lang="en" xmlns="http://www.
<head>
<meta charset="utf-8" />
<title>HTML5绘图板</title>
<style>
body { background: #abcdef; }
header { width: 1200px; height: 80px; line-height: 80px; font-size: 40px; margin: 0 auto; text-align: center; }
footer { width: 1200px; height: 20px; margin: 0 auto; text-align: center; line-height: 20px; }
.content { width: 1200px; height: 560px; margin: 0 auto; background-color: gray; padding: 1px; }
h3 { height: 25px; line-height: 25px; text-align: center; margin: 0px auto; }
.name { height: 25px; padding: 0px; margin: 0px; }
.name > li { float: left; background-color: #dcdcdc; list-style: none; width: 238px; height: 25px; margin: 0px 1px; }
#funct { height: 82px; padding: 0px; margin: 1px 0px; }
#funct > li { float: left; background-color: #dcdcdc; list-style: none; width: 238px; height: 82px; margin: 0px 1px; }
#funct button { margin: 10px 20px; cursor: pointer; }
#funct img { margin: 5px 0px 5px 30px; height: 25px; width: 35px; border: 1px solid #dcdcdc; cursor: pointer; }
#funct img:hover { margin: 5px 0px 5px 30px; height: 25px; width: 35px; border: 1px solid white; cursor: pointer; }
#funct .line img { margin: 5px 19px 0px 19px; height: 8px; width: 200px; border: 1px solid #dcdcdc; cursor: pointer; }
#funct .line img:hover { margin: 5px 19px 0px 19px; height: 8px; width: 200px; border: 1px solid white; cursor: pointer; }
#funct div { width: 20px; height: 20px; margin: 10px 0px 0px 15px; border: 1px solid #dcdcdc; float: left; cursor: pointer; }
#funct div:hover { width: 20px; height: 20px; margin: 10px 0px 0px 15px; border: 1px solid white; float: left; cursor: pointer; }
.on { background-color: yellow; border: 1px solid white; }
canvas { background-color: white; margin-top: 1px; cursor: crosshair; }
</style>
</head>
<body>
<header>HTML5绘图板</header>
<div class="content">
<ul class="name">
<li><h3>图像</h3></li>
<li><h3>工具</h3></li>
<li><h3>形状</h3></li>
<li><h3>线条</h3></li>
<li><h3>颜色</h3></li>
</ul>
<ul id="funct">
<li><button>重置画布</button></li>
<li>
<img src="images/Brush.png" data-f="brush" />
<img src="images/Eraser.png" data-f="eraser" />
<img src="images/Magnifier.png" data-f="magnifier" />
<img src="images/Paint.png" data-f="paint" />
<img src="images/Straw.png" data-f="straw" />
<img src="images/text.png" data-f="text" />
</li>
<li>
<img src="images/arc.png" data-f="arc-stroke" />
<img src="images/arcfill.png" data-f="arc-fill" />
<img src="images/poly.png" data-f="poly" />
<img src="images/rect.png" data-f="rect-stroke" />
<img src="images/rectfill.png" data-f="rect-fill" />
<img src="images/line.png" data-f="line" />
</li>
<li class="line">
<img src="images/line1px.png" data-l="1" />
<img src="images/line3px.png" data-l="3" />
<img src="images/line5px.png" data-l="5" />
<img src="images/line8px.png" data-l="8" />
</li>
<li>
<div style="background-color:rgb(0,0,0);" data-c="rgb(0,0,0)"></div>
<div style="background-color:rgb(255,0,0);" data-c="rgb(255,0,0)"></div>
<div style="background-color:rgb(0,255,0);" data-c="rgb(0,255,0)"></div>
<div style="background-color:rgb(0,0,255);" data-c="rgb(0,0,255)"></div>
<div style="background-color:rgb(255,255,0);" data-c="rgb(255,255,0)"></div>
<div style="background-color:rgb(0,255,255);" data-c="rgb(0,255,255)"></div>
<div style="background-color:rgb(255,0,255);" data-c="rgb(255,0,255)"></div>
<div style="background-color:rgb(255,255,255);" data-c="rgb(255,255,255)"></div>
<div style="background-color:rgb(255,106,0);" data-c="rgb(255,106,0)"></div>
<div style="background-color:rgb(0,148,255);" data-c="rgb(0,148,255)"></div>
<div style="background-color:rgb(255,0,110);" data-c="rgb(255,0,110)"></div>
<div style="background-color:rgb(178,0,255);" data-c="rgb(178,0,255)"></div>
</li>
</ul>
<canvas id="board" width="1200" height="450"></canvas>
</div>
<footer><small>版权所有,违者不究 @ 冰镇柠檬汁儿</small></footer>
<script>
var func = document.getElementById('funct'),
boar = document.getElementById('board'),
gc = boar.getContext('2d'),
li = func.children,
bott = li[0].children[0],
img1 = li[1].children,
img2 = li[2].children,
line = li[3].children,
cols = li[4].children,
imgs = [],
imgsSign = null, colsSign = 'rgb(0,0,0)',
isMouseDown = false, downX = 0, downY = 0, poly = 3;
imgs = Array.prototype.concat.apply(imgs, img1);
imgs = Array.prototype.concat.apply(imgs, img2);
gc.strokeStyle = 'rgb(0,0,0)';
gc.fillStyle = 'rgb(0,0,0)';
gc.lineWidth = 1;
func.onclick = function (event) {
var e = window.event || event,
tag = e.srcElement || e.target,
par = tag.parentNode,
i = 0, len = 0;
if (tag == bott) {
//点击按钮,重置画布
gc.clearRect(0, 0, 1200, 450);
}
else if (par == li[1] || par == li[2]) {
//点击工具或绘图的内容
for (i = 0, len = imgs.length; i < len; i++) {
if (tag == imgs[i]) {
tag.className = 'on';
//获取需要的工具、形状操作,设置并记录
imgsSign = tag.getAttribute('data-f');
if (imgsSign == 'poly') {
//选择多边形时,提供边数修改
var scale = window.prompt('您想绘制几边形?', '3');
poly = parseInt(scale);
if (isNaN(poly) || poly < 3) {
poly = 3;
}
}
else if (imgsSign == 'magnifier') {
//使用缩放时,提供比例修改
var text = window.prompt('请输入要放大的百分比', '100');
if (!isNaN(text)) {
text = parseInt(text);
//放大缩小,使用style,会让像素等比例缩放,使用width和height属性,会出现错误
boar.style.width = parseInt(1200 * text / 100) + 'px';
boar.style.height = parseInt(450 * text / 100) + 'px';
}
}
}
else {
imgs[i].className = '';
}
}
}
else if (par == li[3]) {
//线条选择
for (i = 0, len = line.length; i < len; i++) {
if (tag == line[i]) {
tag.className = 'on';
//直接设置线条DOM元素设置的线条宽度
gc.lineWidth = parseInt(tag.getAttribute('data-l'));
}
else {
line[i].className = '';
}
}
}
else if (par == li[4]) {
//颜色选择
for (i = 0, len = cols.length; i < len; i++) {
if (tag == cols[i]) {
tag.style.border = '1px solid white';
//获取颜色,并设置给填充和画线样式
colsSign = tag.getAttribute('data-c');
gc.fillStyle = colsSign;
gc.strokeStyle = colsSign;
}
else {
cols[i].style.border = '1px solid #dcdcdc';
}
}
}
};
//鼠标按下事件
boar.onmousedown = function (event) {
var e = window.event || event,
ex = e.x || e.pageX, ey = e.y || e.pageY,
startX = ex - this.offsetLeft, startY = ey - this.offsetTop;
//设置鼠标一定按下状态
isMouseDown = true;
gc.beginPath();
if (imgsSign == 'brush' || imgsSign == 'line') {
//画笔和画直线使用相同的初始设置
gc.moveTo(startX, startY);
gc.strokeStyle = colsSign;
}
else if (imgsSign == 'eraser') {
//橡皮擦初始设置和画笔、直线相似,只是画线的颜色为白色
gc.moveTo(startX, startY);
gc.strokeStyle = 'rgb(255,255,255)';
//当然这里也可以使用clearRect方法在移动事件中进行,懒得这么写了
}
else if (imgsSign == 'arc-stroke' || imgsSign == 'arc-fill'
|| imgsSign == 'rect-stroke' || imgsSign == 'rect-fill'
|| imgsSign == 'poly') {
//形状中圆形(实心、空心)、矩形(实心、空心)和多边形(只有空心)所需的起始点
downX = startX;
downY = startY;
}
else if (imgsSign == 'paint') {
gc.fillRect(0, 0, 1200, 450);
}
else if (imgsSign == 'straw') {
var cr = gc.getImageData(startX, startY, 1, 1);
gc.strokeStyle = 'rgb(' + cr.data[0] + ',' + cr.data[1] + ',' + cr.data[2] + ')';
gc.fillStyle = 'rgb(' + cr.data[0] + ',' + cr.data[1] + ',' + cr.data[2] + ')';
}
else if (imgsSign == 'text') {
var text = window.prompt('请输入文字信息', '');
if (text) {
gc.font = '24px 宋体';
gc.fillText(text, startX, startY);
}
gc.closePath();
}
};
//鼠标移动事件
boar.onmousemove = function (event) {
var e = window.event || event,
ex = e.x || e.pageX, ey = e.y || e.pageY,
lineX = ex - this.offsetLeft, lineY = ey - this.offsetTop;
if (imgsSign == 'brush' || imgsSign == 'eraser') {
//画线和橡皮擦,鼠标在按住并移动时进行绘图
if (isMouseDown) {
gc.lineTo(lineX, lineY);
gc.stroke();
}
}
};
//鼠标移出画布和鼠标抬起事件,处理方式相同
boar.onmouseout = boar.onmouseup = function (event) {
var e = window.event || event,
ex = e.x || e.pageX, ey = e.y || e.pageY,
endX = ex - this.offsetLeft, endY = ey - this.offsetTop;
if (imgsSign == 'line') {
//绘制直线
if (isMouseDown) {
gc.lineTo(endX, endY);
gc.stroke();
}
}
else if (imgsSign == 'arc-stroke' || imgsSign == 'arc-fill') {
//绘制圆形(实心、空心)
if (isMouseDown) {
gc.arc(downX, downY, Math.sqrt(Math.pow(endX - downX, 2) + Math.pow(endY - downY, 2)), 0, 2 * Math.PI);
imgsSign == 'arc-stroke' ? gc.stroke() : gc.fill();
}
}
else if (imgsSign == 'rect-stroke' || imgsSign == 'rect-fill') {
//绘制矩形(实心、空心)
if (isMouseDown) {
gc.rect(downX, downY, endX - downX, endY - downY);
imgsSign == 'rect-stroke' ? gc.stroke() : gc.fill();
}
}
else if (imgsSign == 'poly') {
//绘制空心多边形
if (isMouseDown) {
var rr = Math.sqrt(Math.pow(endX - downX, 2) + Math.pow(endY - downY, 2)), //计算起始点到终止点的距离,作为半径
i = 1,
dalte = 2 * Math.PI / poly, //计算每次需要累加的弧度(弧度制角度)
angle = poly % 2 == 0 ? Math.PI / poly : 0; //如果是偶数多边形,在多边形起始点不设置在正中,采用对称方式,多加一个角度(弧度制)
//多边形起始点,点的计算:x = 圆心x + 半径r * sin(弧度),y = 圆心y - 半径r * cos(弧度)
gc.moveTo(downX + rr * Math.sin(angle), downY - rr * Math.cos(angle));
for (; i <= poly; i++) {
//累加弧度、计算下一个点,绘制线段
angle += dalte;
gc.lineTo(downX + rr * Math.sin(angle), downY - rr * Math.cos(angle));
}
gc.stroke();
}
}
isMouseDown = false;
gc.closePath();
};
</script>
</body>
</html>