@disjukr/croquis-js
Version:
drawing tool library
135 lines (134 loc) • 4.55 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
var stylus_1 = require("../stylus");
var misc_1 = require("../misc");
exports.defaultBrushConfig = Object.freeze({
ctx: misc_1.dummyCanvasContext,
color: '#000',
size: 10,
});
exports.stroke = {
resume: function (config, prevState) {
return getDrawingContext(exports.stroke, config, prevState);
},
down: function (config, curr) {
var state = {
prev: stylus_1.cloneStylusState(curr),
};
var drawingContext = getDrawingContext(exports.stroke, config, state);
if (curr.pressure <= 0)
return drawingContext;
config.ctx.save();
config.ctx.fillStyle = config.color;
drawCircle(config.ctx, stylusStateToCircle(curr, config.size));
config.ctx.restore();
return drawingContext;
},
};
function getDrawingContext(stroke, config, state) {
return {
getConfig: function (target) {
if (!target || target === stroke)
return config;
throw undefined;
},
getState: function (target) {
if (!target || target === stroke)
return state;
throw undefined;
},
move: function (curr) {
var c1 = stylusStateToCircle(state.prev, config.size);
var c2 = stylusStateToCircle(curr, config.size);
config.ctx.save();
config.ctx.fillStyle = config.color;
drawCapsule(config.ctx, c1, c2);
stylus_1.copyStylusState(state.prev, curr);
config.ctx.restore();
},
up: function (curr) {
var c1 = stylusStateToCircle(state.prev, config.size);
var c2 = stylusStateToCircle(curr, config.size);
config.ctx.save();
config.ctx.fillStyle = config.color;
drawCapsule(config.ctx, c1, c2);
stylus_1.copyStylusState(state.prev, curr);
config.ctx.restore();
return {
// boundingRect: state.boundingRect,
};
},
};
}
function stylusStateToCircle(stylusState, size) {
return { x: stylusState.x, y: stylusState.y, r: stylusState.pressure * size * 0.5 };
}
function drawCapsule(ctx, c1, c2) {
var c1IsBig = c1.r > c2.r;
var big = c1IsBig ? c1 : c2;
var small = c1IsBig ? c2 : c1;
var d = Math.sqrt(Math.pow((c2.x - c1.x), 2) + Math.pow((c2.y - c1.y), 2));
if (big.r > small.r + d)
return drawCircle(ctx, big);
if (big.r === small.r) {
drawCapsuleCase1(ctx, big, small);
}
else {
drawCapsuleCase2(ctx, big, small);
}
}
function drawCircle(ctx, circle) {
ctx.beginPath();
ctx.moveTo(circle.x + circle.r, circle.y);
ctx.arc(circle.x, circle.y, circle.r, 0, Math.PI * 2);
ctx.closePath();
ctx.fill();
}
var quarter = Math.PI / 2;
function drawCapsuleCase1(ctx, c1, c2) {
drawCircle(ctx, c1);
drawCircle(ctx, c2);
var c = Math.atan2(c2.y - c1.y, c2.x - c1.x);
var i = c - quarter;
var j = c + quarter;
var idx = Math.cos(i) * c2.r;
var idy = Math.sin(i) * c2.r;
var jdx = Math.cos(j) * c2.r;
var jdy = Math.sin(j) * c2.r;
ctx.beginPath();
ctx.moveTo(c2.x + idx, c2.y + idy);
ctx.lineTo(c1.x + idx, c1.y + idy);
ctx.lineTo(c1.x + jdx, c1.y + jdy);
ctx.lineTo(c2.x + jdx, c2.y + jdy);
ctx.closePath();
ctx.fill();
}
function drawCapsuleCase2(ctx, c1, c2) {
drawCircle(ctx, c1);
drawCircle(ctx, c2);
var x = c2.x - c1.x || 1e-9;
var y = c2.y - c1.y;
var r = c1.r - c2.r;
var r2 = r * r;
var x2 = x * x;
var x3 = x * x * x;
var y2 = y * y;
var ax = (x === 0 ? c1.r : (y * Math.sqrt(r2 * x2 * (-r2 + x2 + y2)) + r2 * x2) / (x3 + x * y2)) + c1.x;
var ay = (r2 * y - Math.sqrt(r2 * x2 * (-r2 + x2 + y2))) / (x2 + y2) + c1.y;
var bx = (x === 0 ? -c1.r : (-(y * Math.sqrt(r2 * x2 * (-r2 + x2 + y2))) + r2 * x2) / (x3 + x * y2)) +
c1.x;
var by = (r2 * y + Math.sqrt(r2 * x2 * (-r2 + x2 + y2))) / (x2 + y2) + c1.y;
var i = Math.atan2(ay - c1.y, ax - c1.x);
var j = Math.atan2(by - c1.y, bx - c1.x);
var idx = Math.cos(i) * c2.r;
var idy = Math.sin(i) * c2.r;
var jdx = Math.cos(j) * c2.r;
var jdy = Math.sin(j) * c2.r;
ctx.beginPath();
ctx.moveTo(c2.x + idx, c2.y + idy);
ctx.lineTo(ax + idx, ay + idy);
ctx.lineTo(bx + jdx, by + jdy);
ctx.lineTo(c2.x + jdx, c2.y + jdy);
ctx.closePath();
ctx.fill();
}