123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388 |
- class Point {
- constructor(x, y, time) {
- this.x = x;
- this.y = y;
- this.isControl = false;
- this.time = Date.now();
- this.lineWidth = 0;
- this.isAdd = false;
- }
- }
- class Line {
- constructor() {
- this.points = new Array();
- this.changeWidthCount = 0;
- this.lineWidth = 10;
- }
- }
- class HandwritingSelf {
- constructor(canvas,w,h,line_w=8,line_color='#ff0000') {
-
- this.canvas = {width:w,height:h};
- this.ctx = canvas
- var context = this.ctx;
- this.ctx.ellipse = function( x, y, a, b){
-
- }
-
- this.line = new Line();
- this.pointLines = new Array();
- this.k = 0.5;
- this.begin = null;
- this.middle = null;
- this.end = null;
- this.preTime = null;
- this.lineWidth = line_w;
- this.lineColor = line_color;
- this.isDown = false;
- }
- down(x, y) {
- this.isDown = true;
- this.line = new Line();
- this.line.lineWidth = this.lineWidth;
- let currentPoint = new Point(x, y, Date.now());
- this.addPoint(currentPoint);
- this.preTime = Date.now();
- }
- move(x, y) {
-
- if (this.isDown) {
- let currentPoint = new Point(x, y, Date.now())
- this.addPoint(currentPoint);
- this.draw();
- }
- }
- up(x, y) {
-
- let currentPoint = new Point(x, y, Date.now())
- this.addPoint(currentPoint);
-
- this.draw(true);
- this.pointLines.push(this.line);
- this.begin = null;
- this.middle = null;
- this.end = null;
- this.isDown = false;
- }
- draw(isUp = false) {
-
- this.ctx.setStrokeStyle(this.lineColor)
-
- this.pointLines.forEach((line, index) => {
- let points = line.points;
- this.ctx.beginPath();
- this.ctx.ellipse(points[0].x - 1.5, points[0].y, 6, 3, Math.PI / 4, 0, Math.PI * 2);
- this.ctx.fill();
- this.ctx.beginPath();
- this.ctx.moveTo(points[0].x, points[0].y);
- let lastW = line.lineWidth;
- this.ctx.setLineWidth(line.lineWidth);
- this.ctx.setLineJoin("round");
- this.ctx.setLineCap( "round");
- let minLineW = line.lineWidth / 4;
- let isChangeW = false;
- let changeWidthCount = line.changeWidthCount;
- for (let i = 1; i <= points.length; i++) {
- if (i == points.length) {
- this.ctx.stroke();
- break;
- }
- if (i > points.length - changeWidthCount) {
- if (!isChangeW) {
- this.ctx.stroke();
- isChangeW = true;
- if (i > 1 && points[i - 1].isControl)
- continue;
- }
- let w = (lastW - minLineW) / changeWidthCount * (points.length - i) + minLineW;
- points[i - 1].lineWidth = w;
- this.ctx.beginPath();
-
- this.ctx.setLineWidth(w);
- this.ctx.moveTo(points[i - 1].x, points[i - 1].y);
- this.ctx.lineTo(points[i].x, points[i].y);
- this.ctx.stroke();
- } else {
- if (points[i].isControl && points[i + 1]) {
- this.ctx.quadraticCurveTo(points[i].x, points[i].y, points[i + 1].x, points[i + 1].y);
- } else if (i >= 1 && points[i - 1].isControl) {
- } else
- this.ctx.lineTo(points[i].x, points[i].y);
- }
- }
- })
-
- let points;
- if (isUp)
- points = this.line.points;
- else
- points = [...this.line.points];
-
- let count = 0;
- let insertCount = 0;
- let i = points.length - 1;
- let endPoint = points[i];
- let controlPoint;
- let startPoint;
- while (i >= 0) {
- if (points[i].isControl == true) {
- controlPoint = points[i];
- count++;
- } else {
- startPoint = points[i];
- }
- if (startPoint && controlPoint && endPoint) {
- let dis = this.z_distance(startPoint, controlPoint) + this.z_distance(controlPoint, endPoint);
- let insertPoints = this.BezierCalculate([startPoint, controlPoint, endPoint], Math.floor(dis / 6) + 1);
- insertCount += insertPoints.length;
- var index = i;
-
- insertPoints.unshift(index, 1);
- Array.prototype.splice.apply(points, insertPoints);
-
- endPoint = startPoint;
- startPoint = null;
- }
- if (count >= 6)
- break;
- i--;
- }
-
- let changeWidthCount = count + insertCount;
- if (isUp)
- this.line.changeWidthCount = changeWidthCount;
-
-
- this.ctx.fillStyle = "rgba(255,20,87,1)"
- this.ctx.beginPath();
- this.ctx.ellipse(points[0].x - 1.5, points[0].y, 6, 3, Math.PI / 4, 0, Math.PI * 2);
- this.ctx.fill();
- this.ctx.draw(true);
-
- this.ctx.beginPath();
- this.ctx.moveTo(points[0].x, points[0].y);
- let lastW = this.line.lineWidth;
- this.ctx.setLineWidth(this.line.lineWidth);
- this.ctx.setLineJoin("round");
- this.ctx.setLineCap( "round");
- let minLineW = this.line.lineWidth / 4;
- let isChangeW = false;
- for (let i = 1; i <= points.length; i++) {
- if (i == points.length) {
- this.ctx.stroke();
- break;
- }
-
- if (i > points.length - changeWidthCount) {
- if (!isChangeW) {
- this.ctx.stroke();
- isChangeW = true;
- if (i > 1 && points[i - 1].isControl)
- continue;
- }
-
- let w = (lastW - minLineW) / changeWidthCount * (points.length - i) + minLineW;
- points[i - 1].lineWidth = w;
- this.ctx.beginPath();
-
- this.ctx.setLineWidth(w);
- this.ctx.moveTo(points[i - 1].x, points[i - 1].y);
- this.ctx.lineTo(points[i].x, points[i].y);
- this.ctx.stroke();
- } else {
- if (points[i].isControl && points[i + 1]) {
- this.ctx.quadraticCurveTo(points[i].x, points[i].y, points[i + 1].x, points[i + 1].y);
- } else if (i >= 1 && points[i - 1].isControl) {
- } else
- this.ctx.lineTo(points[i].x, points[i].y);
- }
- }
- this.ctx.draw(true);
- }
- addPoint(p) {
- if (this.line.points.length >= 1) {
- let last_point = this.line.points[this.line.points.length - 1]
- let distance = this.z_distance(p, last_point);
- if (distance < 10) {
- return;
- }
- }
- if (this.line.points.length == 0) {
- this.begin = p;
- p.isControl = true;
- this.pushPoint(p);
- } else {
- this.middle = p;
- let controlPs = this.computeControlPoints(this.k, this.begin, this.middle, null);
- this.pushPoint(controlPs.first);
- this.pushPoint(p);
- p.isControl = true;
- this.begin = this.middle;
- }
- }
- addOtherPoint(p1, p2, w1, w2) {
- let otherPoints = new Array();
- let dis = this.z_distance(p1, p2);
- if (dis >= 25) {
- otherPoints.push(p1);
- let insertPCount = Math.floor(dis / 20);
- for (let j = 0; j < insertPCount; j++) {
- let insertP = new Point(p1.x + (j + 1) / (insertPCount + 1) * (p2.x - p1.x), p1.y + (j + 1) / (insertPCount + 1) * (p2.y - p1.y))
- insertP.isAdd = true;
- otherPoints.push(insertP);
- }
- otherPoints.push(p2);
- }
- let count = otherPoints.length;
- if (count > 0) {
- console.log("addOtherPoint")
- debugger
- let diffW = (w2 - w1) / (count - 1);
- for (let i = 1; i < count; i++) {
- let w = w1 + diffW * i;
- this.ctx.beginPath();
- this.ctx.setLineWidth(w);
- this.ctx.moveTo(otherPoints[i - 1].x, otherPoints[i - 1].y);
- this.ctx.lineTo(otherPoints[i].x, otherPoints[i].y)
- this.ctx.stroke();
- }
- }
- return otherPoints
- }
- pushPoint(p) {
-
- if (this.line.points.length >= 1 && this.line.points[this.line.points.length - 1].x == p.x && this.line.points[this.line.points.length - 1].y == p.y)
- return;
- this.line.points.push(p);
- }
- computeControlPoints(k, begin, middle, end) {
- if (k > 0.5 || k <= 0)
- return;
- let diff1 = new Point(middle.x - begin.x, middle.y - begin.y)
- let diff2 = null;
- if (end)
- diff2 = new Point(end.x - middle.x, end.y - middle.y)
-
-
- let first = new Point(middle.x - (k * diff1.x), middle.y - (k * diff1.y))
- let second = null;
- if (diff2)
- second = new Point(middle.x + (k * diff2.x), middle.y + (k * diff2.y))
- return { first: first, second: second }
- }
-
-
-
-
-
-
-
-
- z_linewidth(b, e, bwidth, step) {
- if (e.time == b.time)
- return bwidth;
- let max_speed = 2.0;
- let d = this.z_distance(b, e);
- let s = d / (e.time - b.time);
- console.log("s", e.time - b.time, s)
- s = s > max_speed ? max_speed : s;
-
- let w = 0.5 / s;
- let max_dif = d * step;
- console.log(w, bwidth, max_dif)
- if (w < 0.05) w = 0.05;
- if (Math.abs(w - bwidth) > max_dif) {
- if (w > bwidth)
- w = bwidth + max_dif;
- else
- w = bwidth - max_dif;
- }
-
- return w;
- }
- z_distance(b, e) {
- return Math.sqrt(Math.pow(e.x - b.x, 2) + Math.pow(e.y - b.y, 2));
- }
- BezierCalculate(poss, precision) {
-
- let dimersion = 2;
-
- let number = poss.length;
-
- if (number < 2 || dimersion < 2)
- return null;
- let result = new Array();
-
- let mi = new Array();
- mi[0] = mi[1] = 1;
- for (let i = 3; i <= number; i++) {
- let t = new Array();
- for (let j = 0; j < i - 1; j++) {
- t[j] = mi[j];
- }
- mi[0] = mi[i - 1] = 1;
- for (let j = 0; j < i - 2; j++) {
- mi[j + 1] = t[j] + t[j + 1];
- }
- }
-
- for (let i = 0; i < precision; i++) {
- let t = i / precision;
- let p = new Point(0, 0);
- p.isAdd = true;
- result.push(p);
- for (let j = 0; j < dimersion; j++) {
- let temp = 0.0;
- for (let k = 0; k < number; k++) {
- temp += Math.pow(1 - t, number - k - 1) * (j == 0 ? poss[k].x : poss[k].y) * Math.pow(t, k) * mi[k];
- }
- j == 0 ? p.x = temp : p.y = temp;
- }
- }
- return result;
- }
- }
- export default HandwritingSelf;
|