这个绘图工具,我还没有做完,不过已经实现了总架构,以及常见的简易图形绘制功能:

1,可以绘制直线,圆,矩形,正多边形【已完成】

2,填充颜色和描边颜色的选择【已完成】

3,描边和填充功能的选择【已完成】

后续版本:

橡皮擦,坐标系,线形设置,箭头,其他流程图形,裁剪与调整图形。。。。。

终极目标:

流程绘制软件

我是之前看见一位朋友在我的博客中留言说:

非常感谢这个朋友,今天终于抽出时间完成非常非常小的雏形!

完整的雏形代码,请自行打开,复制到本地测试.

 <head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>windows简易画图工具 - by ghostwu</title>
</head> <body>
<div class="paint">
<div class="paint-header">
<ul>
<li class="active">形状</li>
<li>颜色</li>
<li>绘制类型</li>
<li>线条宽度</li>
<li>橡皮擦</li>
</ul>
</div>
<div class="paint-body">
<div class="siderbar">
<div class="item active" data-type="paint-shape">
<ul>
<li class="active" data-role="line">线条</li>
<li data-role="circle">圆形</li>
<li data-role="rect">矩形</li>
<li data-role="polygon">正多边形</li>
<li data-role="arrow">箭头</li>
</ul>
</div>
<div class="item" data-type="paint-color">
<ul>
<li data-role="strokeStyle">
<input type="color" data-role="strokeStyle">
</li>
<li data-role="fillStyle">
<input type="color" data-role="fillStyle">
</li>
</ul>
</div>
<div class="item" data-type="paint-type">
<ul>
<li data-role="stroke">描边</li>
<li data-role="fill">填充</li>
</ul>
</div>
<div class="item" data-type="paint-line">
<ul>
<li data-role="1">小号</li>
<li data-role="4">中号</li>
<li data-role="7">大号</li>
<li>
<input type="number" data-role="line-size" placeholder="请输入数字">
</li>
</ul>
</div>
<div class="item" data-type="paint-erase">
<ul>
<li>
<input type="number" data-role="erase-size" placeholder="请输入数字">
</li>
</ul>
</div>
</div>
</div>
</div>
<script>// <![CDATA[
var oPaintBody = document.querySelector( '.paint-body' );
var oC = document.createElement( 'canvas' );
oC.setAttribute( 'width', '830' );
oC.setAttribute( 'height', '500' );
oPaintBody.appendChild( oC );
var aHeaderLi = document.querySelectorAll('.paint-header li'),
aItem = document.querySelectorAll('.paint-body .item'),
oCanvas = document.querySelector('.paint canvas'),
oGc = oCanvas.getContext('2d'),
cWidth = oCanvas.width, cHeight = oCanvas.height,
curItem = aItem[0],
aItemLi = curItem.querySelectorAll('li'); for (let i = 0, len = aHeaderLi.length; i < len; i++) { //头部选项卡切换功能
aHeaderLi[i].onclick = function () {
for (let j = 0; j < len; j++) {
aHeaderLi[j].classList.remove('active');
aItem[j].style.display = 'none';
}
aItem[i].style.display = "block";
this.classList.add('active');
curItem = aItem[i];
aItemLi = curItem.querySelectorAll('li');
activeItem(aItemLi);
}
}
activeItem(aItemLi);
var role = null;
function activeItem(aItemLi) { //canvas左侧选项卡切换功能
for (let i = 0, len = aItemLi.length; i < len; i++) {
aItemLi[i].onclick = function () {
checkPaintType(this); //绘制类型
for (let j = 0; j < len; j++) {
aItemLi[j].classList.remove('active');
}
this.classList.add('active');
}
}
} function Shape(canvasObj, cxtObj, w, h) {
this.oCanvas = canvasObj;
this.oGc = cxtObj;
this.oCanvas.width = w;
this.oCanvas.height = h;
this.fillStyle = '#000';
this.storkeStyle = '#000';
this.lineWidth = 1;
this.drawType = 'line';
this.paintType = 'stroke';
this.nums = 6; //正多边形的边数
} Shape.prototype = {
init: function () {
this.oGc.fillStyle = this.fillStyle;
this.oGc.strokeStyle = this.strokeStyle;
this.oGc.lineWidth = this.lineWidth;
},
draw: function () {
var _this = this;
this.oCanvas.onmousedown = function (ev) {
_this.init();
var oEvent = ev || event,
startX = oEvent.clientX - _this.oCanvas.offsetLeft,
startY = oEvent.clientY - _this.oCanvas.offsetTop;
_this.oCanvas.onmousemove = function (ev) {
_this.oGc.clearRect(0, 0, _this.oCanvas.width, _this.oCanvas.height);
var oEvent = ev || event,
endX = oEvent.clientX - _this.oCanvas.offsetLeft,
endY = oEvent.clientY - _this.oCanvas.offsetTop;
_this[_this.drawType](startX, startY, endX, endY);
};
_this.oCanvas.onmouseup = function () {
_this.oCanvas.onmousemove = null;
_this.oCanvas.onmouseup = null;
}
}
},
line: function (x1, y1, x2, y2) {
this.oGc.beginPath();
this.oGc.moveTo(x1, y1);
this.oGc.lineTo(x2, y2);
this.oGc.closePath();
this.oGc.stroke();
},
circle: function (x1, y1, x2, y2) {
this.oGc.beginPath();
var r = Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2));
this.oGc.arc(x1, y1, r, 0, 2 * Math.PI, false);
this.oGc.closePath();
this.oGc[this.paintType]();
},
rect: function (x1, y1, x2, y2) {
this.oGc.beginPath();
this.oGc.rect(x1, y1, x2 - x1, y2 - y1);
this.oGc[this.paintType]();
},
polygon: function (x1, y1, x2, y2) {
var angle = 360 / this.nums * Math.PI / 180;//边对应的角的弧度
var r = Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2));
this.oGc.beginPath();
for (var i = 0; i < this.nums; i++) {
this.oGc.lineTo(x1 + r * Math.cos(angle * i), y1 + r * Math.sin(angle * i));
}
this.oGc.closePath();
this.oGc[this.paintType]();
}
} var oShape = new Shape(oCanvas, oGc, cWidth, cHeight);
function checkPaintType(liType) {
var dataType = liType.parentNode.parentNode.dataset.type;
var curType = liType.dataset.role;
switch (dataType) {
case 'paint-shape': //形状
oShape.drawType = curType;
if (curType == 'polygon') {
oShape.nums = prompt("请输入边数", 6);
}
oShape.draw();
break;
case 'paint-color': //绘制颜色
liType.children[0].onchange = function () {
oShape[this.dataset.role] = this.value;
}
oShape.draw();
break;
case 'paint-type': //绘制类型
oShape.paintType = curType;
oShape.draw();
break;
}
}
// ]]></script>
<style>
.paint * {
margin: 0;
padding: 0;
} .paint ul,
.paint li {
list-style: none;
} .paint li:hover {
cursor: pointer;
} .paint {
width: 980px;
margin: 20px auto;
border: 1px solid #ccc;
overflow: hidden;
} .paint .paint-header ul {
width: 980px;
height: 40px;
line-height: 40px;
border-bottom: 1px solid #ccc;
} .paint .paint-header li {
float: left;
width: 120px;
height: 40px;
line-height: 40px;
text-align: center;
} .paint li.active {
box-shadow: #666 0px 1px 8px inset;
} .paint .paint-body .siderbar {
float: left;
width: 150px;
height: 500px;
} .paint .paint-body .item {
width: 150px;
overflow: hidden;
display: none;
height: 500px;
border-right: 1px solid #ccc;
} .paint .paint-body canvas {
float: right;
} .paint .paint-body .item li {
height: 40px;
text-align: center;
border-bottom: 1px solid #ccc;
line-height: 40px;
} .paint .paint-body .active {
display: block;
}
</style>
</body>

关于流程设计,后期要做的功能,思路基本上已经有了,好了,圆规正传,想要完成这个终极目标,完成一个画图工具应该就能接近目标了。先体验下目前的简易功能,下面是可以正常画图的,【需要你的浏览器支持canvas才可以额】

  • 形状
  • 颜色
  • 绘制类型
  • 线条宽度
  • 橡皮擦
  • 线条
  • 圆形
  • 矩形
  • 正多边形
  • 箭头
  • 描边
  • 填充
  • 小号
  • 中号
  • 大号

主要来讲下目标的雏形架构:

1,图形绘制部分,我封装了一个类Shape

 function Shape(canvasObj, cxtObj, w, h) {
this.oCanvas = canvasObj;
this.oGc = cxtObj;
this.oCanvas.width = w;
this.oCanvas.height = h;
this.fillStyle = '#000';
this.storkeStyle = '#000';
this.lineWidth = 1;
this.drawType = 'line';
this.paintType = 'stroke';
this.nums = 6; //正多边形的边数
}

canvasObj: 就是canvas画布对象

cxtObj: 就是上下文绘图环境

w: canvas的宽度

h:  canvas的高度

fillStyle: 填充颜色

strokeStyle: 描边颜色

lineWidth: 线宽

drawType: 默认为画直线

paintType: stroke/fill 两种选择( 描边/填充)

2,在原型对象上扩展一个公共方法draw用来绘制图形

draw方法,主要获取起始点坐标(startX, startY),以及终点坐标( endX, endY );

然后调用init方法来获取绘制状态,绘制具体的图形靠下面这个关键方法:

_this[_this.drawType](startX, startY, endX, endY)

这个方法的drawType会根据界面的实时选择,变换对应的绘制类型,如:

_this['line']( startX, startY, endX, endY )

调用的就是oShape对象中的line,画直线的方法

 Shape.prototype = {
init: function () {
this.oGc.fillStyle = this.fillStyle;
this.oGc.strokeStyle = this.strokeStyle;
this.oGc.lineWidth = this.lineWidth;
},
draw: function () {
var _this = this;
this.oCanvas.onmousedown = function ( ev ) {
_this.init();
var oEvent = ev || event,
startX = oEvent.clientX - _this.oCanvas.offsetLeft,
startY = oEvent.clientY - _this.oCanvas.offsetTop;
_this.oCanvas.onmousemove = function ( ev ) {
_this.oGc.clearRect( 0, 0, _this.oCanvas.width, _this.oCanvas.height );
var oEvent = ev || event,
endX = oEvent.clientX - _this.oCanvas.offsetLeft,
endY = oEvent.clientY - _this.oCanvas.offsetTop;
_this[_this.drawType](startX, startY, endX, endY);
};
_this.oCanvas.onmouseup = function(){
_this.oCanvas.onmousemove = null;
_this.oCanvas.onmouseup = null;
}
}
},
line: function ( x1, y1, x2, y2 ) {
this.oGc.beginPath();
this.oGc.moveTo( x1, y1 );
this.oGc.lineTo( x2, y2 );
this.oGc.closePath();
this.oGc.stroke();
},
circle : function( x1, y1, x2, y2 ){
this.oGc.beginPath();
var r = Math.sqrt( Math.pow( x2 - x1, 2 ) + Math.pow( y2 - y1, 2 ) );
this.oGc.arc( x1, y1, r, 0, 2 * Math.PI, false );
this.oGc.closePath();
this.oGc[this.paintType]();
},
rect : function( x1, y1, x2, y2 ){
this.oGc.beginPath();
this.oGc.rect( x1, y1, x2 - x1, y2 - y1 );
this.oGc[this.paintType]();
},
polygon : function( x1, y1, x2, y2 ){
var angle = 360 / this.nums * Math.PI / 180;//边对应的角的弧度
var r = Math.sqrt( Math.pow( x2 - x1, 2 ) + Math.pow( y2 - y1, 2 ) );
this.oGc.beginPath();
for( var i = 0; i < this.nums; i ++ ){
this.oGc.lineTo( x1 + r * Math.cos( angle * i ), y1 + r * Math.sin( angle * i ) );
}
this.oGc.closePath();
this.oGc[this.paintType]();
}
}

3,界面操作很简单,基本是选项卡的操作+html5的自定义属性+classList的应用

[js高手之路]html5 canvas动画教程 - 自己动手做一个类似windows的画图软件的更多相关文章

  1. [js高手之路]html5 canvas动画教程 - 边界判断与小球粒子模拟喷泉,散弹效果

    备注:本文后面的代码,如果加载了ball.js,那么请使用这篇文章[js高手之路] html5 canvas动画教程 - 匀速运动的ball.js代码. 本文,我们要做点有意思的效果,首先,来一个简单 ...

  2. [js高手之路]html5 canvas动画教程 - 边界判断与反弹

    备注:本文后面的代码,如果加载了ball.js,那么请使用这篇文章[js高手之路] html5 canvas动画教程 - 匀速运动的ball.js代码. 边界反弹: 当小球碰到canvas的四个方向的 ...

  3. [js高手之路] html5 canvas动画教程 - 实时获取鼠标的当前坐标

    有了前面的canvas基础之后,现在开始就精彩了,后面写的canvas教程都是属于综合应用,前面已经写了常用的canvas基础知识,参考链接如下: [js高手之路] html5 canvas系列教程 ...

  4. [js高手之路]html5 canvas动画教程 - 下雪效果

    利用canvas,实现一个下雪的效果,我们先预览下效果: 我们先分析下这个效果: 1,随机产生雪花 2,雪花的产生不是同时产生,而是有先后顺序的 3,雪花怎么表示 4,怎么源源不断的下雪 5,雪花有大 ...

  5. [js高手之路]html5 canvas动画教程 - 跟着鼠标移动消失的一堆炫彩小球

    综合利用前面所学,实现一个绚丽的小球动画,这个实例用到的知识点,在我的博客全部都有,可以去这里查看所有的canvas教程 <head> <meta charset='utf-8' / ...

  6. [js高手之路] html5 canvas动画教程 - 匀速运动

    匀速运动:指的是物体在一条直线上运动,并且物体在任何相等时间间隔内通过的位移都是相等的.其实就是匀速直线运动,它的特点是加速度为0,从定义可知,在任何相等的时间间隔内,速度大小和方向是相同的. < ...

  7. [js高手之路]html5 canvas动画教程 - 重力、摩擦力、加速、抛物线运动

    上节,我们讲了匀速运动,本节分享的运动就更有意思了: 加速运动 重力加速度 抛物线运动 摩擦力 加速运动: <head> <meta charset='utf-8' /> &l ...

  8. [js高手之路] html5 canvas系列教程 - 状态详解(save与restore)

    本文内容与路径([js高手之路] html5 canvas系列教程 - 开始路径beginPath与关闭路径closePath详解)是canvas中比较重要的概念.掌握理解他们是做出复杂canvas动 ...

  9. [js高手之路] html5 canvas系列教程 - 掌握画直线图形的常用API

    我们接着上文[js高手之路] html5 canvase系列教程 - 认识canvas以及基本使用方法继续. 一.直线的绘制 cxt.moveTo( x1, y1 ): 将画笔移动到x1, y1这个点 ...

随机推荐

  1. KVM网页管理工具WebVirtMgr部署

    KVM-WebVirtMgr 0ther https://github.com/retspen/webvirtmgr/wiki System Optimization(Only CentOS6.X) ...

  2. 一些LVS实验配置、工具和方案

    最近做了一些LVS配置和方案的验证实验,将过程中用到的一些配置.工具和具体的解决方案记录一下.使用DR模式.验证一种不中断业务的RealServer升级或者重启方案. 网络规划: 节点 IP地址 ce ...

  3. 【1414软工助教】团队作业2——需求分析&原型设计 得分榜

    题目 团队作业2--需求分析&原型设计 作业提交情况情况 本次作业所有团队都按时提交作业. 往期成绩 个人作业1:四则运算控制台 结对项目1:GUI 个人作业2:案例分析 结对项目2:单元测试 ...

  4. Java 第六周总结

    1. 本周学习总结 1.1 面向对象学习暂告一段落,请使用思维导图,以封装.继承.多态为核心概念画一张思维导图,对面向对象思想进行一个总结. 注1:关键词与内容不求多,但概念之间的联系要清晰,内容覆盖 ...

  5. 201521123044 《Java程序设计》第6周学习总结

    1. 本章学习总结 1.1 面向对象学习暂告一段落,请使用思维导图,以封装.继承.多态为核心概念画一张思维导图,对面向对象思想进行一个总结. 注1:关键词与内容不求多,但概念之间的联系要清晰,内容覆盖 ...

  6. 201521123087 《Java程序设计》第5周学习总结

    1. 本周学习总结 2. 书面作业 作业参考文件下载 代码阅读:Child压缩包内源代码1.1 com.parent包中Child.java文件能否编译通过?哪句会出现错误?试改正该错误.并分析输出结 ...

  7. 201521123007《Java程序设计》第3周学习总结

    1. 本周学习总结 初学面向对象,会学习到很多碎片化的概念与知识.尝试学会使用思维导图将这些碎片化的概念.知识组织起来.请使用纸笔或者下面的工具画出本周学习到的知识点.截图或者拍照上传. 2. 书面作 ...

  8. 201521123104《Java程序设计》第1周学习总结

    1. 本章学习总结 1.初步了解了什么是Java,以及该如何编写简单的Java程序: 2.认识到相比于C和C++来说,Java更复杂一些,所以学习要花费更大的精力: 3.在编写Java程序过程中,认识 ...

  9. 2017年9月19日 JavaScript语法操作

    关于JavaScript个人还是觉得比较有意思的 {在</html>后面写或者在</body>前面写(必须紧贴</body>)} <script> va ...

  10. linux(4) vi编辑/删除、复制、粘贴 /bash shell 环境变量设置/数据流重定向 | 的用法

    一.vi文字处理器1.vi与vimvi:文字处理器vim:程序开发工具2.vi介绍三种模式:一般模式(vi刚进入的,不可编辑),编辑模式(按i后,左下方是insert)和命令行模式(按esc退出,:w ...