mirror of
https://github.com/rough-stuff/rough.git
synced 2026-02-15 16:05:36 -05:00
canvas render - initial code
This commit is contained in:
77
src2/canvas.js
Normal file
77
src2/canvas.js
Normal file
@@ -0,0 +1,77 @@
|
||||
import { RoughRenderer } from './core/renderer.js';
|
||||
|
||||
export default class RoughCanvas {
|
||||
constructor(canvas, useWorker) {
|
||||
this.canvas = canvas;
|
||||
this.ctx = this.canvas.getContext("2d");
|
||||
this.useWorker = useWorker;
|
||||
this.defaultOptions = {
|
||||
maxRandomnessOffset: 2,
|
||||
roughness: 1,
|
||||
bowing: 1,
|
||||
stroke: '#000',
|
||||
strokeWidth: 1,
|
||||
curveTightness: 0,
|
||||
curveStepCount: 9,
|
||||
fill: null,
|
||||
fillStyle: 'hachure',
|
||||
fillWeight: -1,
|
||||
hachureAngle: -41,
|
||||
hachureGap: -1
|
||||
};
|
||||
}
|
||||
|
||||
_options(options) {
|
||||
return options ? Object.assign({}, this.defaultOptions, options) : this.defaultOptions;
|
||||
}
|
||||
|
||||
_draw(ctx, drawing) {
|
||||
if (drawing.type === 'path') {
|
||||
ctx.beginPath();
|
||||
for (let item of drawing.ops) {
|
||||
const data = item.data;
|
||||
switch (item.op) {
|
||||
case 'move':
|
||||
ctx.moveTo(data[0], data[1]);
|
||||
break;
|
||||
case 'bcurveTo':
|
||||
ctx.bezierCurveTo(data[0], data[1], data[2], data[3], data[4], data[5]);
|
||||
break;
|
||||
case 'lineTo':
|
||||
console.warn("lineTo not implemented yet");
|
||||
break;
|
||||
}
|
||||
}
|
||||
ctx.stroke();
|
||||
}
|
||||
}
|
||||
|
||||
async lib() {
|
||||
if (!this._renderer) {
|
||||
if (this.useWorker) {
|
||||
// let Renderer = workly.proxy(RoughRenderer);
|
||||
// this._renderer = await new Renderer();
|
||||
this._renderer = new RoughRenderer();
|
||||
} else {
|
||||
this._renderer = new RoughRenderer();
|
||||
}
|
||||
}
|
||||
return this._renderer;
|
||||
}
|
||||
|
||||
async line(x1, y1, x2, y2, options) {
|
||||
let o = this._options(options);
|
||||
let lib = await this.lib();
|
||||
let drawing = await lib.line(x1, y1, x2, y2, o);
|
||||
let ctx = this.ctx;
|
||||
ctx.save();
|
||||
ctx.strokeStyle = o.stroke;
|
||||
ctx.lineWidth = o.strokeWidth;
|
||||
this._draw(ctx, drawing);
|
||||
ctx.restore();
|
||||
}
|
||||
|
||||
async arc() {
|
||||
// TODO:
|
||||
}
|
||||
}
|
||||
@@ -1,36 +1,17 @@
|
||||
import { RoughHachureIterator } from './geom/hachure-iterator';
|
||||
import { RoughSegmentRelation, RoughSegment } from './geom/segment';
|
||||
import { RoughHachureIterator } from './hachure.js';
|
||||
import { RoughSegmentRelation, RoughSegment } from './segment.js';
|
||||
|
||||
export class RoughRenderer {
|
||||
constructor() {
|
||||
this.defaultOptions = {
|
||||
maxRandomnessOffset: 2,
|
||||
roughness: 1,
|
||||
bowing = 1,
|
||||
stroke: '#000',
|
||||
strokeWidth: 1,
|
||||
curveTightness: 0,
|
||||
curveStepCount: 9,
|
||||
fill: null,
|
||||
fillStyle: 'hachure',
|
||||
fillWeight: -1,
|
||||
hachureAngle: -41,
|
||||
hachureGap: -1
|
||||
};
|
||||
}
|
||||
|
||||
line(x1, y1, x2, y1, options) {
|
||||
const o = this._options(options);
|
||||
let o1 = this._line(x1, y1, x2, y1, o, true, false);
|
||||
let o2 = this._line(x1, y1, x2, y1, o, true, true);
|
||||
line(x1, y1, x2, y2, o) {
|
||||
let o1 = this._line(x1, y1, x2, y2, o, true, false);
|
||||
let o2 = this._line(x1, y1, x2, y2, o, true, true);
|
||||
return {
|
||||
type: "path",
|
||||
type: 'path',
|
||||
ops: o1.concat(o2)
|
||||
};
|
||||
}
|
||||
|
||||
linearPath(points, close, options) {
|
||||
const o = this._options(options);
|
||||
linearPath(points, close, o) {
|
||||
const len = (points || []).length;
|
||||
if (len > 2) {
|
||||
let ops = [];
|
||||
@@ -44,25 +25,24 @@ export class RoughRenderer {
|
||||
let o2 = this._line(points[len - 1][0], points[len - 1][1], points[0][0], points[0][1], o, true, false);
|
||||
ops.concat(o1, o2);
|
||||
}
|
||||
return { type: "path", ops };
|
||||
return { type: 'path', ops };
|
||||
} else if (len === 2) {
|
||||
return this.line(points[0][0], points[0][1], points[1][0], points[1][1], o);
|
||||
}
|
||||
}
|
||||
|
||||
polygon(points, options) {
|
||||
return this.linearPath(points, true, options);
|
||||
polygon(points, o) {
|
||||
return this.linearPath(points, true, o);
|
||||
}
|
||||
|
||||
rectangle(x, y, width, height, options) {
|
||||
rectangle(x, y, width, height, o) {
|
||||
let points = [
|
||||
[x, y], [x + width, y], [x + width, y + height]
|
||||
];
|
||||
return this.polygon(points, options);
|
||||
return this.polygon(points, o);
|
||||
}
|
||||
|
||||
ellipse(x, y, width, height, options) {
|
||||
const o = this._options(options);
|
||||
ellipse(x, y, width, height, o) {
|
||||
width = Math.max(width > 10 ? width - 4 : width - 1, 1);
|
||||
height = Math.max(height > 10 ? height - 4 : height - 1, 1);
|
||||
const increment = (Math.PI / 2) / o.curveStepCount;
|
||||
@@ -72,11 +52,10 @@ export class RoughRenderer {
|
||||
ry += this._getOffset(-ry * 0.05, ry * 0.05, o);
|
||||
let o1 = this._ellipse(increment, x, y, rx, ry, 1, increment * this._getOffset(0.1, this._getOffset(0.4, 1, o), o), o);
|
||||
let o2 = this._ellipse(increment, x, y, rx, ry, 1.5, 0, o);
|
||||
return { type: "path", ops: o1.concat(o2) };
|
||||
return { type: 'path', ops: o1.concat(o2) };
|
||||
}
|
||||
|
||||
hachureFillShape(xCoords, yCoords, options) {
|
||||
const o = this._options(options);
|
||||
hachureFillShape(xCoords, yCoords, o) {
|
||||
if (xCoords && yCoords && xCoords.length && yCoords.length) {
|
||||
let left = xCoords[0];
|
||||
let right = xCoords[0];
|
||||
@@ -121,15 +100,11 @@ export class RoughRenderer {
|
||||
}
|
||||
}
|
||||
}
|
||||
return { type: "path", ops };
|
||||
return { type: 'path', ops };
|
||||
}
|
||||
|
||||
// privates
|
||||
|
||||
_options(options) {
|
||||
return options ? Object.assign({}, this.defaultOptions, options) : this.defaultOptions;
|
||||
}
|
||||
|
||||
_getOffset(min, max, ops) {
|
||||
return ops.roughness * ((Math.random() * (max - min)) + min);
|
||||
}
|
||||
@@ -187,6 +162,7 @@ export class RoughRenderer {
|
||||
]
|
||||
});
|
||||
}
|
||||
return ops;
|
||||
}
|
||||
|
||||
_curve(points, closePoint, o) {
|
||||
@@ -206,6 +182,7 @@ export class RoughRenderer {
|
||||
}
|
||||
if (closePoint && closePoint.length === 2) {
|
||||
let ro = o.maxRandomnessOffset;
|
||||
// TODO: more roughness here?
|
||||
ops.push({ ops: 'lineTo', data: [closePoint[0] + this._getOffset(-ro, ro, o), closePoint[1] + + this._getOffset(-ro, ro, o)] })
|
||||
}
|
||||
} else if (len === 3) {
|
||||
|
||||
Reference in New Issue
Block a user