Files
rough/bin/svg.js
2018-06-18 13:08:58 -07:00

148 lines
5.7 KiB
JavaScript

import { RoughGenerator } from './generator';
import { RoughRenderer } from './renderer';
const hasDocument = typeof document !== 'undefined';
export class RoughSVG {
constructor(svg, config) {
this.svg = svg;
this.gen = new RoughGenerator(config || null, this.svg);
}
get generator() {
return this.gen;
}
static createRenderer() {
return new RoughRenderer();
}
get defs() {
if (hasDocument) {
if (!this._defs) {
const doc = this.svg.ownerDocument || document;
const dnode = doc.createElementNS('http://www.w3.org/2000/svg', 'defs');
if (this.svg.firstChild) {
this.svg.insertBefore(dnode, this.svg.firstChild);
}
else {
this.svg.appendChild(dnode);
}
this._defs = dnode;
}
}
return this._defs || null;
}
line(x1, y1, x2, y2, options) {
const d = this.gen.line(x1, y1, x2, y2, options);
return this.draw(d);
}
rectangle(x, y, width, height, options) {
const d = this.gen.rectangle(x, y, width, height, options);
return this.draw(d);
}
ellipse(x, y, width, height, options) {
const d = this.gen.ellipse(x, y, width, height, options);
return this.draw(d);
}
circle(x, y, diameter, options) {
const d = this.gen.circle(x, y, diameter, options);
return this.draw(d);
}
linearPath(points, options) {
const d = this.gen.linearPath(points, options);
return this.draw(d);
}
polygon(points, options) {
const d = this.gen.polygon(points, options);
return this.draw(d);
}
arc(x, y, width, height, start, stop, closed = false, options) {
const d = this.gen.arc(x, y, width, height, start, stop, closed, options);
return this.draw(d);
}
curve(points, options) {
const d = this.gen.curve(points, options);
return this.draw(d);
}
path(d, options) {
const drawing = this.gen.path(d, options);
return this.draw(drawing);
}
draw(drawable) {
const sets = drawable.sets || [];
const o = drawable.options || this.gen.defaultOptions;
const doc = this.svg.ownerDocument || (hasDocument && document);
const g = doc.createElementNS('http://www.w3.org/2000/svg', 'g');
for (const drawing of sets) {
let path = null;
switch (drawing.type) {
case 'path': {
path = doc.createElementNS('http://www.w3.org/2000/svg', 'path');
path.setAttribute('d', this.opsToPath(drawing));
path.style.stroke = o.stroke;
path.style.strokeWidth = o.strokeWidth + '';
path.style.fill = 'none';
break;
}
case 'fillPath': {
path = doc.createElementNS('http://www.w3.org/2000/svg', 'path');
path.setAttribute('d', this.opsToPath(drawing));
path.style.stroke = 'none';
path.style.strokeWidth = '0';
path.style.fill = o.fill;
break;
}
case 'fillSketch': {
path = this.fillSketch(doc, drawing, o);
break;
}
case 'path2Dfill': {
path = doc.createElementNS('http://www.w3.org/2000/svg', 'path');
path.setAttribute('d', drawing.path || '');
path.style.stroke = 'none';
path.style.strokeWidth = '0';
path.style.fill = o.fill;
break;
}
case 'path2Dpattern': {
const size = drawing.size;
const pattern = doc.createElementNS('http://www.w3.org/2000/svg', 'pattern');
const id = `rough-${Math.floor(Math.random() * (Number.MAX_SAFE_INTEGER || 999999))}`;
pattern.setAttribute('id', id);
pattern.setAttribute('x', '0');
pattern.setAttribute('y', '0');
pattern.setAttribute('width', '1');
pattern.setAttribute('height', '1');
pattern.setAttribute('height', '1');
pattern.setAttribute('viewBox', `0 0 ${Math.round(size[0])} ${Math.round(size[1])}`);
pattern.setAttribute('patternUnits', 'objectBoundingBox');
const patternPath = this.fillSketch(doc, drawing, o);
pattern.appendChild(patternPath);
this.defs.appendChild(pattern);
path = doc.createElementNS('http://www.w3.org/2000/svg', 'path');
path.setAttribute('d', drawing.path || '');
path.style.stroke = 'none';
path.style.strokeWidth = '0';
path.style.fill = `url(#${id})`;
break;
}
}
if (path) {
g.appendChild(path);
}
}
return g;
}
opsToPath(drawing) {
return this.gen.opsToPath(drawing);
}
fillSketch(doc, drawing, o) {
let fweight = o.fillWeight;
if (fweight < 0) {
fweight = o.strokeWidth / 2;
}
const path = doc.createElementNS('http://www.w3.org/2000/svg', 'path');
path.setAttribute('d', this.opsToPath(drawing));
path.style.stroke = o.fill;
path.style.strokeWidth = fweight + '';
path.style.fill = 'none';
return path;
}
}