Image drawing widget

This commit is contained in:
ziajka 2018-05-16 14:29:54 +02:00
parent 230ae32f0e
commit 0b47232f89
6 changed files with 128 additions and 0 deletions

View File

@ -0,0 +1,15 @@
import { DrawingElement } from "./drawing-element";
export class EllipseElement implements DrawingElement {
height: number;
width: number;
cx: number;
cy: number;
fill: string;
fill_opacity: number;
rx: number;
ry: number;
stroke: string;
stroke_width: number;
}

View File

@ -0,0 +1,8 @@
import { DrawingElement } from "./drawing-element";
export class ImageElement implements DrawingElement {
height: number;
width: number;
data: string;
}

View File

@ -0,0 +1,13 @@
import { DrawingElement } from "./drawing-element";
export class LineElement implements DrawingElement {
height: number;
width: number;
stroke: string;
stroke_width: number;
x1: number;
x2: number;
y1: number;
y2: number;
}

View File

@ -0,0 +1,11 @@
import { DrawingElement } from "./drawing-element";
export class RectElement implements DrawingElement {
height: number;
width: number;
fill: string;
fill_opacity: number;
stroke: string;
stroke_width: number;
}

View File

@ -0,0 +1,43 @@
import { TestSVGCanvas } from "../../../testing";
import { Drawing } from "../../models/drawing";
import { ImageDrawingWidget } from "./image-drawing";
import { ImageElement } from "../../models/drawings/image-element";
describe('ImageDrawingWidget', () => {
let svg: TestSVGCanvas;
let widget: ImageDrawingWidget;
let drawing: Drawing;
beforeEach(() => {
svg = new TestSVGCanvas();
drawing = new Drawing();
widget = new ImageDrawingWidget();
});
afterEach(() => {
svg.destroy();
});
it('should draw image drawing', () => {
const image = new ImageElement();
image.width = 100;
image.height = 200;
image.data = "DATA";
drawing.element = image;
const drawings = svg.canvas.selectAll<SVGGElement, Drawing>('g.drawing').data([drawing]);
const drawings_enter = drawings.enter().append<SVGGElement>('g').classed('drawing', true);
const drawings_merge = drawings.merge(drawings_enter);
widget.draw(drawings_merge);
const drew = drawings_merge.selectAll<SVGImageElement, ImageElement>('image.image_element');
expect(drew.size()).toEqual(1);
const image_element = drew.nodes()[0];
expect(image_element.getAttribute('width')).toEqual('100');
expect(image_element.getAttribute('height')).toEqual('200');
expect(image_element.getAttribute('href')).toEqual('data:image/svg+xml;base64,REFUQQ==');
});
});

View File

@ -0,0 +1,38 @@
import { SVGSelection } from "../../models/types";
import { Drawing } from "../../models/drawing";
import { ImageElement } from "../../models/drawings/image-element";
export class ImageDrawingWidget {
public draw(view: SVGSelection) {
const drawing = view
.selectAll<SVGImageElement, ImageElement>('image.image_element')
.data((d: Drawing) => {
return (d.element && d.element instanceof ImageElement) ? [d.element] : [];
});
const drawing_enter = drawing
.enter()
.append<SVGImageElement>('image')
.attr('class', 'image_element noselect');
const merge = drawing.merge(drawing_enter);
merge
.attr('xlink:href', (image: ImageElement) => {
let svg = image.data;
if (svg.indexOf("xmlns") < 0) {
svg = svg.replace('svg', 'svg xmlns="http://www.w3.org/2000/svg"');
}
return 'data:image/svg+xml;base64,' + btoa(svg);
})
.attr('width', (image) => image.width)
.attr('height', (image) => image.height);
drawing
.exit()
.remove();
}
}