<bmx-cad-viewer>
A viewer for CAD drawings in DXF - the format AutoCAD, BricsCAD, DraftSight, LibreCAD, QCAD, FreeCAD, SolidWorks, Inventor, Revit and ArchiCAD all write: model space and the layouts with their viewports; lines, arcs, circles, ellipses, polylines, splines, texts, blocks however deep, hatches, dimensions and leaders in their colours, linetypes and lineweights. Pan, zoom and switch layers; point at anything to read what it is; measure distances, areas and angles with snaps; find text; mark it up with rectangles, clouds, arrows, notes and freehand; save the view or the whole as PNG, SVG or PDF. The file is read and drawn in the browser: nothing is uploaded.
12 properties · 8 events · 20 methods · 0 parts
Example
Try it with your own files in confidence: they are opened by your browser, on your device. Nothing is uploaded, no copy reaches us or anyone else, and nothing is kept once you close this tab.
An invented flat, written out as a DXF by this page: walls and their hatching, doors and windows inserted as blocks, furniture, floor patterns, room names, dimensions, a grid on a dashed linetype, and an A3 sheet with the plan at 1:50 and the kitchen at 1:20. Pan and zoom; click anything to see what it is; measure distances, areas and angles - they snap to ends, middles and centres; find text; mark the drawing up; save it as PNG, SVG or PDF. Switch layers on and off: A-AREA starts off, as the drawing saved it.
Show markup
<bmx-cad-viewer id="ex-cad" style="--bmx-cad-viewer-height: 34rem"></bmx-cad-viewer>
<p class="note">An invented flat, written out as a DXF by this page: walls and their hatching, doors and windows inserted as blocks, furniture, floor patterns, room names, dimensions, a grid on a dashed linetype, and an A3 sheet with the plan at 1:50 and the kitchen at 1:20. Pan and zoom; click anything to see what it is; measure distances, areas and angles - they snap to ends, middles and centres; find text; mark the drawing up; save it as PNG, SVG or PDF. Switch layers on and off: A-AREA starts off, as the drawing saved it.</p>
<div class="row" style="gap: 0.75rem; flex-wrap: wrap; align-items: center; margin-block: 0.5rem 1.5rem">
<label>Open a drawing of your own <input type="file" id="ex-cad-file" accept=".dxf" /></label>
<button type="button" id="ex-cad-sample">Show the sample again</button>
</div>
<p class="note" id="ex-cad-out" role="status"></p>
<script type="module">
await customElements.whenDefined('bmx-cad-viewer');
const viewer = document.getElementById('ex-cad');
const out = document.getElementById('ex-cad-out');
/** A small DXF writer: group codes and values, a line each. */
function sampleDxf() {
const L = [];
const g = (code, value) => L.push(String(code), typeof value === 'number' ? String(Math.round(value * 1000) / 1000) : String(value));
const ent = (type, layer, ...pairs) => {
g(0, type);
g(8, layer);
for (let k = 0; k < pairs.length; k += 2) g(pairs[k], pairs[k + 1]);
};
const line = (layer, x1, y1, x2, y2, ...extra) => ent('LINE', layer, 10, x1, 20, y1, 11, x2, 21, y2, ...extra);
const circle = (layer, x, y, r, ...extra) => ent('CIRCLE', layer, 10, x, 20, y, 40, r, ...extra);
const arc = (layer, x, y, r, a0, a1) => ent('ARC', layer, 10, x, 20, y, 40, r, 50, a0, 51, a1);
const poly = (layer, pts, closed = true, ...extra) => {
ent('LWPOLYLINE', layer, 90, pts.length, 70, closed ? 1 : 0, ...extra);
for (const p of pts) {
g(10, p[0]);
g(20, p[1]);
if (p[2]) g(42, p[2]);
}
};
const rect = (layer, x, y, w, h) =>
poly(layer, [
[x, y],
[x + w, y],
[x + w, y + h],
[x, y + h],
]);
const text = (layer, x, y, h, words, opts = {}) =>
ent('TEXT', layer, 10, x, 20, y, 11, x, 21, y, 40, h, 1, words, 7, 'NOTES', 72, opts.h ?? 1, 73, opts.v ?? 2, ...(opts.rot ? [50, opts.rot] : []));
const mtext = (layer, x, y, h, words) => ent('MTEXT', layer, 10, x, 20, y, 40, h, 71, 5, 7, 'NOTES', 1, words);
const insert = (block, layer, x, y, rot = 0, ...extra) => ent('INSERT', layer, 2, block, 10, x, 20, y, 50, rot, ...extra);
/** A hatch of polyline paths: solid, or with pattern lines [angle, base x, base y, offset x, offset y, dashes]. */
const hatch = (layer, paths, pattern) => {
g(0, 'HATCH');
g(8, layer);
g(2, pattern ? 'USER' : 'SOLID');
g(70, pattern ? 0 : 1);
g(91, paths.length);
paths.forEach((pts, k) => {
g(92, k ? 2 : 3);
g(72, 0);
g(73, 1);
g(93, pts.length);
for (const p of pts) {
g(10, p[0]);
g(20, p[1]);
}
g(97, 0);
});
g(75, 0);
g(76, 1);
if (pattern) {
g(78, pattern.length);
for (const [a, bx, by, ox, oy, dashes = []] of pattern) {
g(53, a);
g(43, bx);
g(44, by);
g(45, ox);
g(46, oy);
g(79, dashes.length);
for (const d of dashes) g(49, d);
}
}
};
const box = (x, y, w, h) => [
[x, y],
[x + w, y],
[x + w, y + h],
[x, y + h],
];
// Header: millimetres, linetype scale for a 1:50 sheet.
g(0, 'SECTION');
g(2, 'HEADER');
g(9, '$ACADVER');
g(1, 'AC1015');
g(9, '$INSUNITS');
g(70, 4);
g(9, '$LTSCALE');
g(40, 25);
g(0, 'ENDSEC');
// Tables: linetypes, layers, a text style.
g(0, 'SECTION');
g(2, 'TABLES');
g(0, 'TABLE');
g(2, 'LTYPE');
for (const [name, pattern] of [
['CONTINUOUS', []],
['CENTER', [31.75, -6.35, 6.35, -6.35]],
['DASHED', [12.7, -6.35]],
]) {
g(0, 'LTYPE');
g(2, name);
g(73, pattern.length);
for (const d of pattern) g(49, d);
}
g(0, 'ENDTAB');
g(0, 'TABLE');
g(2, 'LAYER');
for (const [name, color, lt = 'CONTINUOUS', weight = -3] of [
['0', 7],
['A-WALL', 7, 'CONTINUOUS', 50],
['A-WALL-HATCH', 8],
['A-DOOR', 3],
['A-GLAZ', 4],
['A-FURN', 30],
['A-FIXT', 5],
['A-FLOR-PATT', 253],
['A-ANNO-TEXT', 7],
['A-ANNO-DIMS', 1],
['A-GRID', 8, 'CENTER'],
['A-AREA', -6, 'DASHED'],
]) {
g(0, 'LAYER');
g(5, `L-${name}`);
g(2, name);
g(70, 0);
g(62, color);
g(6, lt);
g(370, weight);
}
g(0, 'ENDTAB');
g(0, 'TABLE');
g(2, 'BLOCK_RECORD');
for (const [handle, name] of [
['1E', '*Model_Space'],
['1F', '*Paper_Space'],
]) {
g(0, 'BLOCK_RECORD');
g(5, handle);
g(2, name);
}
g(0, 'ENDTAB');
g(0, 'TABLE');
g(2, 'STYLE');
g(0, 'STYLE');
g(2, 'NOTES');
g(3, 'arial.ttf');
g(40, 0);
g(41, 1);
g(0, 'ENDTAB');
g(0, 'ENDSEC');
// Blocks: a door, a window, a chair, a bed, a hob ring, a north arrow, a title block, and three dimensions.
g(0, 'SECTION');
g(2, 'BLOCKS');
const block = (name, draw) => {
g(0, 'BLOCK');
g(2, name);
g(70, name.startsWith('*') ? 1 : 0);
g(10, 0);
g(20, 0);
draw();
g(0, 'ENDBLK');
};
block('DOOR-900', () => {
line('0', 0, 0, 0, 900);
arc('0', 0, 0, 900, 0, 90);
});
block('WINDOW-1200', () => {
rect('0', 0, 0, 1200, 250);
line('0', 0, 125, 1200, 125);
});
block('CHAIR', () => {
poly('0', [
[-225, -225, 0],
[225, -225, 0],
[225, 150, 0.4],
[-225, 150, 0],
]);
line('0', -225, 225, 225, 225);
});
block('BED-1600', () => {
rect('0', 0, 0, 1600, 2000);
poly('0', [
[80, 1600, 0],
[740, 1600, 0.3],
[740, 1900, 0],
[80, 1900, 0.3],
]);
poly('0', [
[860, 1600, 0],
[1520, 1600, 0.3],
[1520, 1900, 0],
[860, 1900, 0.3],
]);
line('0', 0, 1450, 1600, 1450);
});
block('HOB-RING', () => {
circle('0', 0, 0, 110);
circle('0', 0, 0, 60);
});
block('NORTH', () => {
circle('0', 0, 0, 400);
ent('SOLID', '0', 10, 0, 20, 380, 11, -150, 21, -250, 12, 0, 22, -120, 13, 0, 23, -120);
text('0', 0, 560, 220, 'N');
});
block('TITLE', () => {
rect('0', 0, 0, 5200, 1100);
line('0', 0, 550, 5200, 550);
line('0', 3600, 0, 3600, 1100);
text('0', 200, 820, 260, 'Flat 3B, level 2', { h: 0, v: 2 });
text('0', 200, 270, 150, 'General arrangement, scale 1:50', { h: 0, v: 2 });
text('0', 3800, 820, 160, 'Sheet', { h: 0, v: 2 });
});
const dim = (name, horizontal, a, b, at, value) =>
block(name, () => {
const ext = horizontal ? [a, 0, a, at, b, 0, b, at] : [0, a, at, a, 0, b, at, b];
line('0', ext[0], ext[1], ext[2], ext[3]);
line('0', ext[4], ext[5], ext[6], ext[7]);
if (horizontal) {
line('0', a, at, b, at);
for (const x of [a, b]) line('0', x - 90, at - 90, x + 90, at + 90);
mtext('0', (a + b) / 2, at + 180, 200, String(value));
} else {
line('0', at, a, at, b);
for (const y of [a, b]) line('0', at - 90, y - 90, at + 90, y + 90);
ent('MTEXT', '0', 10, at - 180, 20, (a + b) / 2, 40, 200, 71, 5, 50, 90, 1, String(value));
}
});
block('*Paper_Space', () => {});
dim('*D1', true, 0, 12000, -900, 12000);
dim('*D2', false, 0, 8000, -900, 8000);
dim('*D3', true, 5050, 11750, 8700, 6700);
g(0, 'ENDSEC');
// Model space.
g(0, 'SECTION');
g(2, 'ENTITIES');
// Walls: the outer ring hatched between its two outlines, and the partitions.
rect('A-WALL', 0, 0, 12000, 8000);
rect('A-WALL', 250, 250, 11500, 7500);
hatch('A-WALL-HATCH', [box(0, 0, 12000, 8000), box(250, 250, 11500, 7500)]);
const partitions = [
[4950, 250, 100, 750],
[4950, 1900, 100, 3600],
[4950, 6400, 100, 1350],
[7950, 250, 100, 3700],
[5050, 3950, 4150, 100],
[10100, 3950, 1650, 100],
];
for (const [x, y, w, h] of partitions) {
rect('A-WALL', x, y, w, h);
hatch('A-WALL-HATCH', [box(x, y, w, h)]);
}
// Doors (blocks, turned to their walls) and windows.
insert('DOOR-900', 'A-DOOR', 4950, 1000, 90);
insert('DOOR-900', 'A-DOOR', 4950, 5500, 90);
insert('DOOR-900', 'A-DOOR', 9200, 4050, 0);
for (const [x, y, rot] of [
[1200, 0, 0],
[3000, 0, 0],
[9500, 0, 0],
[1800, 7750, 0],
[7000, 7750, 0],
[9800, 7750, 0],
[12000, 5400, 90],
])
insert('WINDOW-1200', 'A-GLAZ', x, y, rot);
// Living room: sofa, oval rug, a round table and its four chairs.
poly('A-FURN', [
[600, 5600, 0],
[3000, 5600, 0],
[3000, 6500, 0],
[2800, 6500, 0],
[2800, 5850, -0.2],
[800, 5850, 0],
[800, 6500, 0],
[600, 6500, 0],
]);
ent('ELLIPSE', 'A-FURN', 10, 1800, 20, 4300, 11, 1300, 21, 0, 40, 0.55, 41, 0, 42, Math.PI * 2);
ent('SPLINE', 'A-FURN', 70, 8, 71, 3, 72, 0, 73, 6, 74, 0, ...[[300, 2300], [900, 3200], [1900, 2600], [2700, 3400], [3600, 2500], [4400, 3000]].flatMap(p => [10, p[0], 20, p[1]]));
circle('A-FURN', 2600, 1500, 550);
for (const rot of [0, 90, 180, 270]) {
const r = (rot * Math.PI) / 180;
insert('CHAIR', 'A-FURN', 2600 - Math.sin(r) * 850, 1500 + Math.cos(r) * 850, rot + 180);
}
// Bedroom.
insert('BED-1600', 'A-FURN', 7200, 5650);
rect('A-FURN', 10400, 6600, 1200, 1000);
// Bathroom: bath, basin and WC; floor tiles.
poly('A-FIXT', [
[5150, 300, 0],
[7850, 300, 0],
[7850, 1050, 0],
[5150, 1050, 0],
]);
poly('A-FIXT', [
[5350, 400, 0],
[7400, 400, 0.4],
[7400, 950, 0],
[5350, 950, 0],
]);
ent('ELLIPSE', 'A-FIXT', 10, 7400, 20, 3500, 11, 0, 21, 280, 40, 0.75, 41, 0, 42, Math.PI * 2);
ent('ELLIPSE', 'A-FIXT', 10, 6100, 20, 3550, 11, 0, 21, 330, 40, 0.65, 41, 0, 42, Math.PI * 2);
rect('A-FIXT', 5750, 3700, 700, 200);
hatch('A-FLOR-PATT', [box(5050, 250, 2900, 3700)], [
[0, 5050, 250, 0, 300],
[90, 5050, 250, -300, 0],
]);
// Kitchen: worktop, hob (a 2 by 2 array of one block), sink; floor tiles.
poly('A-FIXT', [
[8050, 250, 0],
[11750, 250, 0],
[11750, 3950, 0],
[11150, 3950, 0],
[11150, 850, 0],
[8050, 850, 0],
]);
insert('HOB-RING', 'A-FIXT', 9000, 400, 0, 70, 2, 71, 2, 44, 300, 45, 300);
poly('A-FIXT', [
[11250, 2000, 0.4],
[11650, 2000, 0],
[11650, 2700, 0.4],
[11250, 2700, 0],
]);
hatch('A-FLOR-PATT', [box(8050, 850, 3100, 3100)], [
[45, 8050, 850, -212.13, 212.13],
[135, 8050, 850, -212.13, -212.13],
]);
// Living floor: boards, joints staggered.
hatch('A-FLOR-PATT', [box(250, 250, 4700, 7500)], [[0, 250, 250, 400, 150, [1200, -12]]]);
// Room names with their areas, and the room outlines on the A-AREA layer (switched off).
for (const [name, x, y, w, h] of [
['Living', 250, 250, 4700, 7500],
['Bedroom', 5050, 4050, 6700, 3700],
['Bathroom', 5050, 250, 2900, 3700],
['Kitchen', 8050, 250, 3700, 3700],
]) {
mtext('A-ANNO-TEXT', x + w / 2, y + h / 2 + (name === 'Living' ? 1000 : name === 'Kitchen' ? 600 : 0), 220, `${name}\\P${((w * h) / 1e6).toFixed(1)} m²`);
rect('A-AREA', x, y, w, h);
}
// Dimensions, drawn into their blocks; the grid; a north arrow; the title block with its sheet number.
ent('DIMENSION', 'A-ANNO-DIMS', 2, '*D1', 10, 12000, 20, -900, 11, 6000, 21, -720, 70, 32, 42, 12000);
ent('DIMENSION', 'A-ANNO-DIMS', 2, '*D2', 10, -900, 20, 8000, 11, -1080, 21, 4000, 70, 33, 42, 8000);
ent('DIMENSION', 'A-ANNO-DIMS', 2, '*D3', 10, 11750, 20, 8700, 11, 8400, 21, 8880, 70, 32, 42, 6700);
for (const [x, name] of [
[0, 'A'],
[5000, 'B'],
[12000, 'C'],
]) {
line('A-GRID', x, -1600, x, 9700);
circle('A-GRID', x, 10050, 350);
text('A-GRID', x, 10050, 280, name);
}
insert('NORTH', 'A-ANNO-TEXT', 13600, 7000);
g(0, 'INSERT');
g(8, 'A-ANNO-TEXT');
g(66, 1);
g(2, 'TITLE');
g(10, 6800);
g(20, -2900);
g(0, 'ATTRIB');
g(8, 'A-ANNO-TEXT');
g(10, 10650);
g(20, -2700);
g(40, 300);
g(1, 'A-101');
g(2, 'SHEET');
g(70, 0);
g(7, 'NOTES');
g(0, 'SEQEND');
// The A3 sheet (in millimetres): a border, the plan at 1:50, the kitchen at 1:20 without its dimensions, and their titles.
const paper = (type, layer, ...pairs) => ent(type, layer, 67, 1, ...pairs);
paper('LWPOLYLINE', 'A-ANNO-TEXT', 90, 4, 70, 1, 10, 10, 20, 10, 10, 410, 20, 10, 10, 410, 20, 287, 10, 10, 20, 287);
paper('VIEWPORT', '0', 10, 210, 20, 148.5, 40, 420, 41, 297, 69, 1, 12, 210, 22, 148.5, 45, 297);
paper('VIEWPORT', '0', 10, 140, 20, 160, 40, 240, 41, 220, 69, 2, 12, 6600, 22, 3700, 45, 11000);
paper('VIEWPORT', '0', 10, 337, 20, 175, 40, 125, 41, 150, 69, 3, 12, 10000, 22, 2250, 45, 3900, 341, 'L-A-ANNO-DIMS', 341, 'L-A-ANNO-TEXT');
for (const [x, y, h, words] of [
[140, 38, 5, 'Plan 1:50'],
[337, 88, 5, 'Kitchen 1:20'],
[320, 30, 6, 'Flat 3B, level 2 - A-101'],
])
paper('TEXT', 'A-ANNO-TEXT', 10, x, 20, y, 11, x, 21, y, 40, h, 1, words, 7, 'NOTES', 72, 1, 73, 2);
g(0, 'ENDSEC');
// The layouts: the model, and the sheet.
g(0, 'SECTION');
g(2, 'OBJECTS');
for (const [name, order, record, extra] of [
['Model', 0, '1E', []],
['A3 sheet', 1, '1F', [10, 0, 20, 0, 11, 420, 21, 297]],
]) {
g(0, 'LAYOUT');
g(100, 'AcDbPlotSettings');
g(1, name);
g(44, 420);
g(45, 297);
g(72, 1);
g(100, 'AcDbLayout');
g(1, name);
g(71, order);
for (let k = 0; k < extra.length; k += 2) g(extra[k], extra[k + 1]);
g(330, record);
}
g(0, 'ENDSEC');
g(0, 'EOF');
return L.join('\n');
}
const showSample = () => viewer.load(sampleDxf(), 'flat-3b.dxf');
viewer.addEventListener('bmxLoad', e => {
const i = e.detail;
out.textContent = `${i.name}: ${i.entities} items on ${i.layers} layers, ${i.blocks} blocks, in ${i.unitName || 'drawing units'}.`;
});
viewer.addEventListener('bmxError', e => (out.textContent = e.detail.message));
document.getElementById('ex-cad-file').addEventListener('change', e => {
const file = e.target.files[0];
if (file) viewer.load(file).catch(() => undefined);
});
document.getElementById('ex-cad-sample').addEventListener('click', showSample);
await showSample();
</script>
<bmx-cad-viewer src="plans/level-1.dxf"></bmx-cad-viewer>
Properties
| Property | Attribute | Type | Default | Description |
|---|---|---|---|---|
author |
author |
string |
— | Written into each new markup. |
background |
background |
'auto' | 'dark' | 'light' |
'auto' |
The background: the theme's (auto), or the dark or light ground CAD programs use. |
label |
label |
string |
— | The element's accessible name. |
lineweights |
lineweights |
boolean |
false |
Lines drawn at their lineweights (as printed), rather than all fine. |
locale |
locale |
string |
— | The locale for numbers. Unset: the page's lang. |
markups |
markups |
BmxCadMarkup[] | string |
[] |
The markups (an array, or its JSON): kept by the page, shown on the drawing. |
readOnly |
read-only |
boolean |
false |
Offers no markup tools. |
showLayers |
show-layers |
boolean |
true |
The side panel: layers, find and markups. |
space |
space |
string |
'Model' |
The space shown: Model, or a layout's name. |
src |
src |
string |
— | A DXF file to fetch and show (same origin, or served with CORS). |
strings |
strings |
Partial<BmxCadViewerStrings> | string |
— | Replacements for any of the wording (an object, or its JSON). |
tool |
tool |
BmxCadViewerTool |
'pan' |
The tool in use: pan (and point to choose), a measurement, or a markup. |
Events
| Event | Detail | Description |
|---|---|---|
bmxError |
BmxCadViewerErrorDetail |
Fired when a file cannot be read (a DWG, a binary DXF, not a drawing, or a failed fetch). |
bmxLayerChange |
{ layers: BmxCadViewerLayer[]; } |
Fired when layers are switched on or off. |
bmxLoad |
BmxCadViewerInfo |
Fired when a drawing has been read and shown. |
bmxMarkupChange |
{ markups: BmxCadMarkup[]; } |
Fired when markups are added, deleted or cleared: store markups to keep them. |
bmxMeasure |
BmxCadViewerMeasure |
Fired when a measurement is taken. |
bmxSelect |
BmxCadViewerSelection | null |
Fired when an entity is chosen by pointing at it (null when let go). |
bmxSpaceChange |
{ space: string; } |
Fired when the model or another layout is shown. |
bmxViewChange |
BmxCadViewerView |
Fired when the view pans or zooms. |
Methods
| Method | Signature | Description |
|---|---|---|
clear |
clear() => Promise<void> |
Closes the drawing. |
clearMarkups |
clearMarkups() => Promise<void> |
Removes every markup. |
findText |
findText(query: string) => Promise<{ text: string; layer: string; box: BmxCadBox; }[]> |
The texts holding some words, in reading order, with where they are. |
fit |
fit() => Promise<void> |
Fits the whole drawing (or the layout's sheet) in view. |
getInfo |
getInfo() => Promise<BmxCadViewerInfo | null> |
What is open, or null. |
getLayers |
getLayers() => Promise<BmxCadViewerLayer[]> |
The drawing's layers, in name order. |
getMarkups |
getMarkups() => Promise<BmxCadMarkup[]> |
The markups, all spaces. |
getSelection |
getSelection() => Promise<BmxCadViewerSelection | null> |
The entity chosen, or null. |
getSpaces |
getSpaces() => Promise<string[]> |
The spaces it can show: Model, then the layouts with something on their sheets. |
getView |
getView() => Promise<BmxCadViewerView> |
The view: the drawing's point in the middle, and pixels per drawing unit. |
load |
load(input: string | Blob | ArrayBuffer | Uint8Array, name?: string) => Promise<BmxCadViewerInfo> |
Opens a drawing: DXF text, its bytes, or a file. Resolves with what was opened (or rejects with why not). |
saveAs |
saveAs(kind: "png" | "png-all" | "svg" | "pdf") => Promise<void> |
Saves the PNG, SVG or PDF (the reader's browser downloads it). |
selectAt |
selectAt(x: number | null, y?: number) => Promise<BmxCadViewerSelection | null> |
Chooses the entity at a drawing point (as a click there does), or lets go with null. |
setLayerVisible |
setLayerVisible(names: string | string[], visible: boolean) => Promise<void> |
Switches layers on or off. |
setView |
setView(view: Partial<BmxCadViewerView>) => Promise<void> |
Sets the view. |
toPdf |
toPdf(options?: { page?: BmxCadPdfOptions["page"]; landscape?: boolean; area?: "view" | "all"; }) => Promise<Uint8Array> |
The shown space as a one-page PDF in vector (a layout on its own sheet, the model fitted to A3 unless said), on white. |
toPng |
toPng(options?: { area?: "view" | "all"; width?: number; }) => Promise<Blob | null> |
A PNG picture: of the view as it is (default) or of the whole, width pixels wide. |
toSvg |
toSvg(options?: { area?: "view" | "all"; width?: number; background?: "light" | "dark"; }) => Promise<string> |
The shown space (and visible layers) as SVG, the markups on top; the view's ground unless background is given. |
zoom |
zoom(factor: number) => Promise<void> |
Zooms by a factor about the middle of the view (2 doubles the size). |
zoomTo |
zoomTo(box: BmxCadBox) => Promise<void> |
Zooms to show a box of the drawing: [min x, min y, max x, max y]. |
CSS custom properties
| Property | Description |
|---|---|
--bmx-cad-viewer-background |
The drawing's ground (when the background is auto). |
--bmx-cad-viewer-font |
Font for the drawing's texts whose own font is a CAD font. |
--bmx-cad-viewer-height |
Height of the viewer. |
--bmx-cad-viewer-layers-width |
Width of the layers panel. |
--bmx-cad-viewer-radius |
Corner radius of the frame. |