├── screenshot
└── movie.gif
├── src
├── index.js
├── component
│ ├── Canvas.css
│ ├── App.css
│ ├── App.js
│ └── Canvas.js
├── index.css
└── services
│ └── draw.js
├── .gitignore
├── README.md
├── public
├── manifest.json
└── index.html
├── package.json
└── LICENSE
/screenshot/movie.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/open-canvas-ui/canvas2dDraw/HEAD/screenshot/movie.gif
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import ReactDOM from "react-dom";
3 | import App from "./component/App";
4 |
5 | ReactDOM.render(, document.getElementById("root"));
--------------------------------------------------------------------------------
/src/component/Canvas.css:
--------------------------------------------------------------------------------
1 | .canvas-wrap {
2 | height: 150px;
3 | }
4 |
5 | .button-wrap span {
6 | font-size: 14px;
7 | margin-right: 15px;
8 | line-height: 45px;
9 | }
10 |
--------------------------------------------------------------------------------
/src/index.css:
--------------------------------------------------------------------------------
1 | html {
2 | font-size: 10px;
3 | }
4 |
5 | body {
6 | background-color: black;
7 | margin: 0;
8 | padding: 0;
9 | font-family: sans-serif;
10 | }
11 |
12 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See http://help.github.com/ignore-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | node_modules
5 |
6 | # testing
7 | coverage
8 |
9 | # production
10 | build
11 |
12 | # misc
13 | .DS_Store
14 | npm-debug.log
15 |
--------------------------------------------------------------------------------
/src/component/App.css:
--------------------------------------------------------------------------------
1 | .component-app {
2 | display: flex;
3 | flex-direction: column;
4 | flex-wrap: wrap;
5 | height: 100%;
6 | }
7 |
8 | .component-app h3 {
9 | line-height: 40px;
10 | text-align: center;
11 | color: #666;
12 | font-size: 16px;
13 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | canvas2dDraw
2 | ---
3 |
4 |
5 |

6 |
7 |
8 |
Design Sketch
9 |
10 |
11 | Install
12 | ---
13 |
14 | `npm install`
15 |
16 | Usage
17 | ---
18 |
19 | `npm start`
20 |
21 | License
22 | ---
23 |
24 | MIT
--------------------------------------------------------------------------------
/src/component/App.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import Canvas from './Canvas';
3 | import "./App.css";
4 |
5 | export default class App extends React.PureComponent {
6 |
7 | render() {
8 | return (
9 |
10 |
draw below
11 |
12 |
13 | );
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "Calculator",
3 | "name": "React Calculator Example App",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "64x64 32x32 24x24 16x16",
8 | "type": "image/x-icon"
9 | }
10 | ],
11 | "start_url": "./index.html",
12 | "display": "standalone",
13 | "theme_color": "#000000",
14 | "background_color": "#ffffff"
15 | }
16 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "canvas2dDraw",
3 | "version": "0.1.0",
4 | "license": "MIT",
5 | "homepage": "https://github.com/open-canvas-ui/canvas2dDraw",
6 | "devDependencies": {
7 | "react-scripts": "^1.1.4"
8 | },
9 | "dependencies": {
10 | "react": "^16.4.0",
11 | "react-dom": "^16.4.0"
12 | },
13 | "scripts": {
14 | "start": "react-scripts start",
15 | "build": "react-scripts build",
16 | "test": "react-scripts test --env=jsdom",
17 | "eject": "react-scripts eject",
18 | "deploy": "gh-pages -d build"
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | canvas2dDraw
9 |
10 |
11 |
14 |
15 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/src/component/Canvas.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import Draw from "../services/draw";
3 | import "./Canvas.css";
4 |
5 | export default class App extends React.PureComponent {
6 | /* 重置功能 */
7 | reset() {
8 | Draw.clear();
9 | }
10 |
11 | /* 导出 */
12 | exp() {
13 | let exportImg = Draw.exportImg();
14 | console.log('exportImg: ', exportImg);
15 | if(exportImg === -1) {
16 | return console.log('please draw!');
17 | }
18 | this.refs['imgC'].src = exportImg;
19 | }
20 |
21 | render() {
22 | return (
23 |
24 |
25 |
26 | reset
27 | export
28 |
29 |
![]()
30 |
31 | );
32 | }
33 |
34 | componentDidMount() {
35 | Draw.init(this.refs['canvas-wrap']);
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 Andrew H Farmer
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/src/services/draw.js:
--------------------------------------------------------------------------------
1 | /* 此模块用于实现签名绘图功能 */
2 |
3 | // 需要用到的变量定义
4 | let clickX = new Array();
5 | let clickY = new Array();
6 | let clickDrag = new Array();
7 | let paint;
8 | let point = {notFirst:false};
9 |
10 | let canvasDiv = null; // 初始化画布父盒子
11 | let canvas = document.createElement('canvas'); // 创建画板
12 | let context = canvas.getContext("2d"); // 创建2d画布
13 | let canvasWidth = 0; // 初始化画布宽度
14 | let canvasHeight = 0; // 初始化画布高度
15 |
16 | // 可导出图片的标识
17 | let _exportable = false;
18 |
19 | /* ------------ 需要用到的一些功能函数 ------------ */
20 | function addClick(x, y, dragging) {
21 | clickX.push(x);
22 | clickY.push(y);
23 | clickDrag.push(dragging);
24 | }
25 |
26 | function draw(){
27 | _exportable = true;
28 | while (clickX.length > 0 ) {
29 | point.bx = point.x;
30 | point.by = point.y;
31 | point.x = clickX.pop();
32 | point.y = clickY.pop();
33 | point.drag = clickDrag.pop();
34 | context.beginPath();
35 | if (point.drag && point.notFirst) {
36 | context.moveTo(point.bx, point.by);
37 | } else {
38 | point.notFirst = true;
39 | context.moveTo(point.x - 1, point.y);
40 | }
41 | context.lineTo(point.x, point.y);
42 | context.closePath();
43 | context.stroke();
44 | }
45 | }
46 |
47 | /* 创建画布背景和画笔 */
48 | function create() {
49 | // 以下是创建画布背景
50 | context.rect(0, 0, canvasWidth, canvasHeight);
51 | context.fillStyle="#f2f2f2"; // 图片北京色是灰色,此处去除会变黑色
52 | context.fill();
53 | // 设置画笔属性
54 | context.strokeStyle = "#666";
55 | context.lineJoin = "round";
56 | context.lineWidth = 2;
57 | // 默认值清理
58 | clickX = new Array();
59 | clickY = new Array();
60 | clickDrag = new Array();
61 | _exportable = false;
62 | }
63 |
64 | export default {
65 | /* 初始化 */
66 | init(canvasDivDom, classname) {
67 | canvasDiv = canvasDivDom; // 传入画布父盒子
68 | canvasWidth = canvasDiv.clientWidth; // 获取父盒子宽度
69 | canvasHeight = canvasDiv.clientHeight; // 获取父盒子高度
70 | // 设置属性并追加元素
71 | canvas.setAttribute('width', canvasWidth);
72 | canvas.setAttribute('height', canvasHeight);
73 | canvasDiv.appendChild(canvas);
74 | // 创建画布背景和画笔
75 | create();
76 | // 开始监控画图
77 | this.listen(classname);
78 | },
79 |
80 | /* 画图时的监控 */
81 | listen(classname) {
82 | // 获取盒子需要的参数
83 | let left = canvas.getBoundingClientRect().left;
84 | let top = canvas.getBoundingClientRect().top;
85 | // 支持 移动端
86 | canvasDiv.addEventListener("touchstart", function(e){
87 | paint = true;
88 | classname && (this.className = classname);
89 | (e.touches) && (e = e.touches[0]);
90 | addClick(e.pageX - left, e.pageY - top);
91 | draw();
92 | });
93 |
94 | canvasDiv.addEventListener("touchmove", function(e){
95 | if(!paint) {
96 | return;
97 | }
98 | (e.touches) && (e = e.touches[0]);
99 | addClick(e.pageX - left, e.pageY - top, true);
100 | draw();
101 | });
102 |
103 | canvasDiv.addEventListener("touchend", function(e){
104 | paint = false;
105 | });
106 |
107 | // 支持 PC 端
108 | canvasDiv.addEventListener("mousedown", function(e){
109 | paint = true;
110 | classname && (this.className = classname);
111 | addClick(e.pageX - left, e.pageY - top);
112 | draw();
113 | });
114 |
115 | canvasDiv.addEventListener("mousemove", function(e){
116 | if(!paint) {
117 | return;
118 | }
119 | addClick(e.pageX - left, e.pageY - top, true);
120 | draw();
121 | });
122 |
123 | canvasDiv.addEventListener("mouseup", function(e){
124 | paint = false;
125 | });
126 |
127 | canvasDiv.addEventListener("mouseleave", function(e){
128 | paint = false;
129 | });
130 | },
131 |
132 | /* 清理 */
133 | clear() {
134 | // 使用此方式来清理画布
135 | canvas.width = canvas.width;
136 | canvas.height = canvas.height;
137 | create(); // 重新创建画布背景和画笔
138 | _exportable = false; // 清理之后无法导出
139 | },
140 |
141 | /* 导出图片 */
142 | exportImg() {
143 | if(!_exportable) {
144 | return -1; // 说明此处无法导出图片
145 | }
146 | return canvas.toDataURL("image/png");
147 | }
148 | }
--------------------------------------------------------------------------------