console
var canvas = new fabric.Canvas('c');
fabric.Image.fromURL('https://ss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=18242127,1432314284&fm=26&gp=0.jpg',function(image){
canvas.add(image);
(function(fabric){
fabric.PencilBrushw = fabric.util.createClass(fabric.BaseBrush, {
initialize: function(canvas,opt) {
this.canvas = canvas;
this._points = [];
this.width = 20;
},
_drawSegment: function (ctx, p1, p2) {
var midPoint = p1.midPointFrom(p2);
var radgrad = ctx.createRadialGradient(
p1.x,p1.y,10,p1.x,p1.y,20);
radgrad.addColorStop(0, 'rgba(243,245,246,1)');
radgrad.addColorStop(0.5, 'rgba(243,245,246,0.4)');
radgrad.addColorStop(1, 'rgba(243,245,246,0)');
ctx.fillStyle = radgrad;
ctx.fillRect(p1.x-20, p1.y-20, 40, 40);
return midPoint;
},
onMouseDown: function(pointer) {
this._prepareForDrawing(pointer);
this._captureDrawingPath(pointer);
this._render();
},
onMouseMove: function(pointer) {
if (this._captureDrawingPath(pointer) && this._points.length > 1) {
if (this.needsFullRender) {
this.canvas.clearContext(this.canvas.contextTop);
this._render();
}
else {
var points = this._points, length = points.length, ctx = this.canvas.contextTop;
this._saveAndTransform(ctx);
if (this.oldEnd) {
ctx.beginPath();
ctx.moveTo(this.oldEnd.x, this.oldEnd.y);
}
this.oldEnd = this._drawSegment(ctx, points[length - 2], points[length - 1], true);
ctx.stroke();
ctx.restore();
}
}
},
onMouseUp: function() {
this.oldEnd = undefined;
},
_prepareForDrawing: function(pointer) {
var p = new fabric.Point(pointer.x, pointer.y);
this._reset();
this._addPoint(p);
this.canvas.contextTop.moveTo(p.x, p.y);
},
_addPoint: function(point) {
if (this._points.length > 1 && point.eq(this._points[this._points.length - 1])) {
return false;
}
this._points.push(point);
return true;
},
_reset: function() {
this._points.length = 0;
this._setBrushStyles();
var color = new fabric.Color(this.color);
this.needsFullRender = (color.getAlpha() < 1);
this._setShadow();
},
_captureDrawingPath: function(pointer) {
var pointerPoint = new fabric.Point(pointer.x, pointer.y);
return this._addPoint(pointerPoint);
},
_render: function() {
var ctx = this.canvas.contextTop, i, len,
p1 = this._points[0],
p2 = this._points[1];
console.log('p1',p1,'p2',p2);
this._saveAndTransform(ctx);
ctx.beginPath();
if (this._points.length === 2 && p1.x === p2.x && p1.y === p2.y) {
var width = this.width / 1000;
p1 = new fabric.Point(p1.x, p1.y);
p2 = new fabric.Point(p2.x, p2.y);
p1.x -= width;
p2.x += width;
}
ctx.moveTo(p1.x, p1.y);
var radgrad = ctx.createRadialGradient(
p1.x,p1.y,10,p1.x,p1.y,20);
radgrad.addColorStop(0, 'rgba(243,245,246,1)');
radgrad.addColorStop(0.5, 'rgba(243,245,246,0.5)');
radgrad.addColorStop(1, 'rgba(243,245,246,0)');
ctx.fillStyle = radgrad;
ctx.fillRect(p1.x-20, p1.y-20, 40, 40);
for (i = 1, len = this._points.length; i < len; i++) {
this._drawSegment(ctx, p1, p2);
p1 = this._points[i];
p2 = this._points[i + 1];
}
ctx.stroke();
ctx.restore();
},
convertPointsToSVGPath: function(points) {
var path = [], i, width = this.width / 1000,
p1 = new fabric.Point(points[0].x, points[0].y),
p2 = new fabric.Point(points[1].x, points[1].y),
len = points.length, multSignX = 1, multSignY = 1, manyPoints = len > 2;
if (manyPoints) {
multSignX = points[2].x < p2.x ? -1 : points[2].x === p2.x ? 0 : 1;
multSignY = points[2].y < p2.y ? -1 : points[2].y === p2.y ? 0 : 1;
}
path.push('M ', p1.x - multSignX * width, ' ', p1.y - multSignY * width, ' ');
for (i = 1; i < len; i++) {
if (!p1.eq(p2)) {
var midPoint = p1.midPointFrom(p2);
path.push('Q ', p1.x, ' ', p1.y, ' ', midPoint.x, ' ', midPoint.y, ' ');
}
p1 = points[i];
if ((i + 1) < points.length) {
p2 = points[i + 1];
}
}
if (manyPoints) {
multSignX = p1.x > points[i - 2].x ? 1 : p1.x === points[i - 2].x ? 0 : -1;
multSignY = p1.y > points[i - 2].y ? 1 : p1.y === points[i - 2].y ? 0 : -1;
}
path.push('L ', p1.x + multSignX * width, ' ', p1.y + multSignY * width);
return path;
},
createPath: function(pathData,points,ctx) {
var path = new fabric.Path(pathData, {
fill: null,
stroke: this.color,
strokeWidth: this.width,
strokeLineCap: this.strokeLineCap,
strokeMiterLimit: this.strokeMiterLimit,
strokeLineJoin: this.strokeLineJoin,
strokeDashArray: this.strokeDashArray,
});
console.log('points',points);
var position = new fabric.Point(path.left + path.width / 2, path.top + path.height / 2);
position = path.translateToGivenOrigin(position, 'center', 'center', path.originX, path.originY);
path.top = position.y;
path.left = position.x;
if (this.shadow) {
this.shadow.affectStroke = true;
path.setShadow(this.shadow);
}
return path;
},
_finalizeAndAddPath: function() {
var ctx = this.canvas.contextTop;
ctx.closePath();
var pathData = this.convertPointsToSVGPath(this._points).join('');
console.log('pathData',pathData);
if (pathData === 'M 0 0 Q 0 0 0 0 L 0 0') {
this.canvas.requestRenderAll();
return;
}
console.log('this._points',this._points);
var path = this.createPath(pathData,this._points,ctx);
this.canvas.clearContext(this.canvas.contextTop);
console.log(path);
this.canvas.add(path);
console.log('this.canvas',this.canvas);
this.canvas.renderAll();
path.setCoords();
this._resetShadow();
this.canvas.fire('path:created', { path: path });
}
});
})(fabric);
canvas.isDrawingMode= true;
canvas.freeDrawingBrush = new fabric.PencilBrushw(canvas);
})
canvas.isDrawingMode= true;
<canvas id="c" width="600" height="600"></canvas>
canvas {
border: 1px solid #999;
}