最新文章专题视频专题问答1问答10问答100问答1000问答2000关键字专题1关键字专题50关键字专题500关键字专题1500TAG最新视频文章推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37视频文章20视频文章30视频文章40视频文章50视频文章60 视频文章70视频文章80视频文章90视频文章100视频文章120视频文章140 视频2关键字专题关键字专题tag2tag3文章专题文章专题2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章专题3
当前位置: 首页 - 科技 - 知识百科 - 正文

html5自己做一个类似windows的画图软件的方法

来源:动视网 责编:小采 时间:2020-11-27 15:28:22
文档

html5自己做一个类似windows的画图软件的方法

html5自己做一个类似windows的画图软件的方法:这个绘图工具,我还没有做完,不过已经实现了总架构,以及常见的简易图形绘制功能:1,可以绘制直线,圆,矩形,正多边形【已完成】2,填充颜色和描边颜色的选择【已完成】3,描边和填充功能的选择【已完成】后续版本:橡皮擦,坐标系,线形设置,箭头,其他
推荐度:
导读html5自己做一个类似windows的画图软件的方法:这个绘图工具,我还没有做完,不过已经实现了总架构,以及常见的简易图形绘制功能:1,可以绘制直线,圆,矩形,正多边形【已完成】2,填充颜色和描边颜色的选择【已完成】3,描边和填充功能的选择【已完成】后续版本:橡皮擦,坐标系,线形设置,箭头,其他
 这个绘图工具,我还没有做完,不过已经实现了总架构,以及常见的简易图形绘制功能:

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的应用

文档

html5自己做一个类似windows的画图软件的方法

html5自己做一个类似windows的画图软件的方法:这个绘图工具,我还没有做完,不过已经实现了总架构,以及常见的简易图形绘制功能:1,可以绘制直线,圆,矩形,正多边形【已完成】2,填充颜色和描边颜色的选择【已完成】3,描边和填充功能的选择【已完成】后续版本:橡皮擦,坐标系,线形设置,箭头,其他
推荐度:
标签: 软件 Windows 工具
  • 热门焦点

最新推荐

猜你喜欢

热门推荐

专题
Top