> ## Content Index
> Fetch the complete content index at: https://blog.hacking.pub/llms.txt
> Use this file to discover other available public pages before exploring further.

# js 鼠标拖动画矩形
- URL: https://blog.hacking.pub/2016/11/10/js-shu-biao-tuo-dong-hua-ju-xing/
- Published: 2016-11-10T09:59:04.000Z
- Updated: 2016-11-24T05:46:51.000Z
- Author: chainhelen
- Tags: js, 矩阵

#### 业务需要扫描一些图形点

目录结构

```
main.html |--
      img |- main.png
      js  |- jquery.js
           - main.js

```

效果图  
![js_rect](https://blog.hacking.pub/qiniu/js_rect/js_rect.png)

#### 居中

首先居中，直接margin:0 auto，没有居中，查看了一下box模型，发现margin都是没有值的。所以给它加了个display: block

```html
<canvas width="900px" height="300px" style="display:block;margin:0 auto">
     您的浏览器不支持canvas标签。
</canvas>

```

#### canvas点击事件

引用："由于事件只能达到Canvas元素这一层，所以，如果想进一步深入，识别点击发生在Canvas内部的哪一个图形上，就需要增加代码来进行处理。"

```js
let can = document.getElementById('mycanvas');
can.addEventListener('click', function(e){
  //...
}, false);

```

> 注意第三个参数false，涉及到**冒泡和捕获**  
> 下图解释比较清楚，具体看结尾[参考](#cankao)  
> ![事件模型](http://image.hacking.pub/s/9zdxwcsegi8aipa/%E4%BA%8B%E4%BB%B6%E6%A8%A1%E5%9E%8B.jpg?dl=0)

接下来获取点击事件在canvas里面的位置

```js
function getEventPosition(ev){
  var x, y;
  if (ev.layerX || ev.layerX == 0) {
    x = ev.layerX;
    y = ev.layerY;
    //兼容一些浏览器，不支持直接获取鼠标在canvas的相对位置（layer）
  } else if (ev.offsetX || ev.offsetX == 0) { // Opera
    x = ev.offsetX;
    y = ev.offsetY;
  }
  return {x: x, y: y};
}

```

#### canvas MouseDown事件

上叙的click其实是不满足题意的，准确的是操作是鼠标 点击按下不放->移动->松开  
所以我加了几个状态，分别代表

```
let ctr = {
    //NODRAW  点击前，初始状态
    //HASDRAWONE　已经点击过一次状态，正在移动
    //FINISHED　　完成状态，目前没用到
    curstatus : "NODRAW",

    curHasTableIndex : [],　　　//已经有的矩阵点
    curDrawOnePoint : null,　　//已经点击过的那个点，即起始点
    curMovePoint : null　　　　//当前正在滑动的鼠标点
}

```

//mousedown代码如下，其他事件类似

```js
cvs.addEventListener('mousedown', (e) => {
    let obj = getEventPosition(e);
    if("NODRAW" == ctr.curstatus) {
        ctr.curDrawOnePoint = obj;
        ctr.curstatus = "HASDRAWONE";
    }
    reDraw();
}, false);

```

#### 添加按钮

- 添加删除按钮，只要把curDrawOnePoint这个数组pop，重绘即可
- 添加上传input按钮，其中input控件一直是"选择文件"，无法改成其他名称 利用隐藏input的方式

```
//html
<input id="openInput" type="file" style="display:none">
<button id="openButton">打开</button>
//js
$("#openButton").on("click", () => {
    $("#openInput").click();
});

```

#### 监听载入图片事件

这样写，直接监听

```js
$("#openInput").click("change", () => {
    let reader = new FileReader();
    let file = document.getElementById("openInput").files[0];
    console.log(file);
    if(file) {
        reader.readAsDataURL(document.getElementById("openInput").files[0]);
    }
});

```

或者下面这样就可以了

```js
//html
<input id="openInput" type="file" value="打开" style="display:none" onchange="triInput(this.id)" >
//js
function triInput(id) {
    console.log(document.getElementById(id).files[0]);
}

```

> 顺便提一下，当input作为输入框的时候，发生改变的事件应该写成

```
    $("#openInput").bind("input propertychange", () => {
    });

```

###### 保存数据

```
var obj_target = document.createElementNS('http://www.w3.org/1999/xhtml', 'a');   
  if(obj_target)//非ie
{
   obj_target.href = ‘13231内容’;
   obj_target.download = ‘a.txt’;	 
   var event = document.createEvent('MouseEvents');
   event.initMouseEvent('click', true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
   obj_target.dispatchEvent(event); 
}
else
{
    var w = window.open('about:blank');
    w.document.write('1232323内容');  
    w.document.execCommand('Saveas',false,'a.txt');
    w.close();
} 

```

#### 细节

1. 比如说，如果按下和放下的是同一个点，就没有必要放在table中
2. 现在的矩阵没有先后顺序，可以加个索引的按钮
3. table push点的时候，如果用户是右下角往左上面滑动，那么end点的x,y值是比start点的x,y小

**未经同意，禁止转载**  
[本文地址 http://blog.hacking.pub/2016/11/10/js-shu-biao-tuo-dong-hua-ju-xing/](https://blog.hacking.pub/2016/11/10/js-shu-biao-tuo-dong-hua-ju-xing/)

#### [参考](#cankao)

- [HTML5 Canvas 的事件处理](http://www.xyhtml5.com/html5-canvas-event-handler.html?ref=blog.hacking.pub)
- [addListener添加事件监听器，时第三个参数useCapture (Boolean) 的作用](http://www.cnblogs.com/arliang/articles/useCapture%5Fin%5FaddListener%5Fjs.html?ref=blog.hacking.pub)
- [js之事件冒泡和事件捕获详细介绍](http://www.jb51.net/article/42492.htm?ref=blog.hacking.pub)
- [【javascript】File API 读取并显示本地图片 -1](http://blog.csdn.net/lizixiang1993/article/details/45197171?ref=blog.hacking.pub)
- [用Canvas 加载一个图片](http://blog.sina.com.cn/s/blog%5F900b32490101omv8.html?ref=blog.hacking.pub)
- [javascript 保存文件到本地实现方法](http://blog.163.com/zhongpenghua@yeah/blog/static/87727415201310975054613/?ref=blog.hacking.pub)