Style
Diagram have a style property that can be used to style the diagram.
Here are the style properties that is available for Diagrams.
stroke : string,
fill : string,
opacity : number,
stroke-width : number,
stroke-linecap : string,
stroke-dasharray : number[],
stroke-linejoin : string,
vector-effect : string,
Diagramatics provide a set of color that can be used to style the diagram.
The colors is based on tab20 color scheme.
Styling Diagram
let sq = square(10).fill('blue');
draw(sq);
Diagram.fill (
color
:
string )
:
Diagram
let sq = square(10).fill('blue');
draw(sq);
// color can be given as colorname or hex color code
let sq = square(10).fill('#d62728');
draw(sq);
// color can be given as colorname or hex color code
let sq = square(10).fill('#d62728');
draw(sq);
let sq = square(10).stroke('red');
draw(sq);
Diagram.stroke (
color
:
string )
:
Diagram
let sq = square(10).stroke('red');
draw(sq);
// opacity is between 0 and 1
let sq = square(10).fill('blue').opacity(0.5);
draw(sq);
Diagram.opacity (
opacity
:
number )
:
Diagram
// opacity is between 0 and 1
let sq = square(10).fill('blue').opacity(0.5);
draw(sq);
let sq = square(10).strokewidth(4);
draw(sq);
Diagram.strokewidth (
width
:
number )
:
Diagram
let sq = square(10).strokewidth(4);
draw(sq);
Styling Stroke
let l = line(V2(0,0), V2(0,1)).strokewidth(12);
let l0 = l.strokelinecap('butt');
let l1 = l.strokelinecap('square');
let l2 = l.strokelinecap('round');
let ls = distribute_horizontal([l0,l1,l2], 0.2);
// highlight to make it easier to see
let lhighlight = ls.children.map(x => l.stroke('lightred').strokewidth(2).position(x.origin));
draw(ls, ...lhighlight);
Diagram.strokelinecap (
linecap
:
'butt' | 'round' | 'square' )
:
Diagram
let l = line(V2(0,0), V2(0,1)).strokewidth(12);
let l0 = l.strokelinecap('butt');
let l1 = l.strokelinecap('square');
let l2 = l.strokelinecap('round');
let ls = distribute_horizontal([l0,l1,l2], 0.2);
// highlight to make it easier to see
let lhighlight = ls.children.map(x => l.stroke('lightred').strokewidth(2).position(x.origin));
draw(ls, ...lhighlight);
// this style is based on svg w3c standard
// more info : https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin
let c = curve([V2(0,0), V2(0.5,0.5), V2(1,0)]).strokewidth(12);
let c0 = c.strokelinejoin('miter');
let c1 = c.strokelinejoin('round');
let c2 = c.strokelinejoin('bevel');
let cs = distribute_vertical([c0,c1,c2], 0.2);
// highlight to make it easier to see
let chighlight = cs.children.map(x => c.stroke('lightred').strokewidth(2).position(x.origin));
draw(cs, ...chighlight);
Diagram.strokelinejoin (
linejoin
:
'miter' | 'round' | 'bevel' )
:
Diagram
// this style is based on svg w3c standard
// more info : https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin
let c = curve([V2(0,0), V2(0.5,0.5), V2(1,0)]).strokewidth(12);
let c0 = c.strokelinejoin('miter');
let c1 = c.strokelinejoin('round');
let c2 = c.strokelinejoin('bevel');
let cs = distribute_vertical([c0,c1,c2], 0.2);
// highlight to make it easier to see
let chighlight = cs.children.map(x => c.stroke('lightred').strokewidth(2).position(x.origin));
draw(cs, ...chighlight);
// this style is based on svg w3c standard
// more info : https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray
let l = line(V2(0,0), V2(1,0)).strokewidth(12);
// Dashes and gaps of the same size
let l0 = l.strokedasharray([20]);
let l1 = l.strokedasharray([10]);
// Dashes starting with a gap
let l2 = l.strokedasharray([0,10,0]);
// Dashes and gaps of different sizes
let l3 = l.strokedasharray([40,10]);
// Dashes and gaps of various sizes with an odd number of values
let l4 = l.strokedasharray([40,10,20]);
// Dashes and gaps of various sizes with an even number of values
let l5 = l.strokedasharray([40,10,20,30]);
let lines = distribute_vertical([l0,l1,l2,l3,l4,l5], 0.2);
draw(lines);
Diagram.strokedasharray (
dasharray
:
number[] )
:
Diagram
// this style is based on svg w3c standard
// more info : https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray
let l = line(V2(0,0), V2(1,0)).strokewidth(12);
// Dashes and gaps of the same size
let l0 = l.strokedasharray([20]);
let l1 = l.strokedasharray([10]);
// Dashes starting with a gap
let l2 = l.strokedasharray([0,10,0]);
// Dashes and gaps of different sizes
let l3 = l.strokedasharray([40,10]);
// Dashes and gaps of various sizes with an odd number of values
let l4 = l.strokedasharray([40,10,20]);
// Dashes and gaps of various sizes with an even number of values
let l5 = l.strokedasharray([40,10,20,30]);
let lines = distribute_vertical([l0,l1,l2,l3,l4,l5], 0.2);
draw(lines);
let l = line(V2(0,0), V2(2,0));
// the default is 'non-scaling-stroke', which is calculated relative to the screen.
// so a strokewidth 1 will always be 1 pixel wide,
// and doesn't care about the coordinate system of the diagram.
let l0 = l.vectoreffect('non-scaling-stroke').strokewidth(1);
// if using 'none', the strokewidth will be relative to the coordinate system of the diagram.
// for example, this line have the length of 2 unit
// so a strokewidth of 1 will be 1 unit wide on the coordinate system of the diagram.
let l1 = l.vectoreffect('none').strokewidth(1);
let lines = distribute_vertical([l0,l1], 1.5);
draw(lines);
Diagram.vectoreffect (
vectoreffect
:
'none' | 'non-scaling-stroke' )
:
Diagram
let l = line(V2(0,0), V2(2,0));
// the default is 'non-scaling-stroke', which is calculated relative to the screen.
// so a strokewidth 1 will always be 1 pixel wide,
// and doesn't care about the coordinate system of the diagram.
let l0 = l.vectoreffect('non-scaling-stroke').strokewidth(1);
// if using 'none', the strokewidth will be relative to the coordinate system of the diagram.
// for example, this line have the length of 2 unit
// so a strokewidth of 1 will be 1 unit wide on the coordinate system of the diagram.
let l1 = l.vectoreffect('none').strokewidth(1);
let lines = distribute_vertical([l0,l1], 1.5);
draw(lines);
Styling Text
let sq = square(10).stroke('lightgrey');
let tx = text('hello').fontfamily('sans-serif');
draw(sq, tx);
Diagram.fontfamily (
fontfamily
:
string )
:
Diagram
let sq = square(10).stroke('lightgrey');
let tx = text('hello').fontfamily('sans-serif');
draw(sq, tx);
let sq = square(10).stroke('lightgrey');
let tx = text('hello').fontsize(50);
draw(sq, tx);
Diagram.fontsize (
fontsize
:
number )
:
Diagram
let sq = square(10).stroke('lightgrey');
let tx = text('hello').fontsize(50);
draw(sq, tx);
let sq = square(10).stroke('lightgrey');
let tx = text('hello').fontweight('bold');
draw(sq, tx);
Diagram.fontweight (
fontweight
:
'normal' | 'bold' | 'bolder' | 'lighter' | number )
:
Diagram
let sq = square(10).stroke('lightgrey');
let tx = text('hello').fontweight('bold');
draw(sq, tx);
let sq = square(10).stroke('lightgrey');
let tx = text('hello').fontstyle('italic');
draw(sq, tx);
Diagram.fontstyle (
fontstyle
:
'normal' | 'italic' )
:
Diagram
let sq = square(10).stroke('lightgrey');
let tx = text('hello').fontstyle('italic');
draw(sq, tx);
// anchors can be :
// 'top-left', 'top-center', 'top-right',
// 'center-left', 'center-center', 'center-right',
// 'bottom-left', 'bottom-center', 'bottom-right',
let sq = square(10).stroke('lightgrey');
let tx1 = text('hello').move_origin_text('bottom-right').position(V2(0,0));
let tx2 = text('there').move_origin_text('top-left').position(V2(0,0));
draw(sq, tx1, tx2);
Diagram.move_origin_text (
anchor
:
string )
:
Diagram
// anchors can be :
// 'top-left', 'top-center', 'top-right',
// 'center-left', 'center-center', 'center-right',
// 'bottom-left', 'bottom-center', 'bottom-right',
let sq = square(10).stroke('lightgrey');
let tx1 = text('hello').move_origin_text('bottom-right').position(V2(0,0));
let tx2 = text('there').move_origin_text('top-left').position(V2(0,0));
draw(sq, tx1, tx2);
let sq = square(10).stroke('lightgrey');
let tx = text('hello').textangle(to_radian(45));
draw(sq, tx);
Diagram.textangle (
angle
:
number )
:
Diagram
let sq = square(10).stroke('lightgrey');
let tx = text('hello').textangle(to_radian(45));
draw(sq, tx);
// just like stroke's vectoreffect property
// texts can also be automatically scaled to the screen
// or scaled relative to the coordinate system of the diagram by putting in a number
let sq = square(10).stroke('lightgrey');
let txa = text('auto').fontsize(24).fontscale('auto') .translate(V2(0,1));
let txb = text('absolute').fontsize(24).fontscale(0.1).translate(V2(0,-1));
draw(sq, txa, txb);
Diagram.fontscale (
fontscale
:
'auto' | number )
:
Diagram
// just like stroke's vectoreffect property
// texts can also be automatically scaled to the screen
// or scaled relative to the coordinate system of the diagram by putting in a number
let sq = square(10).stroke('lightgrey');
let txa = text('auto').fontsize(24).fontscale('auto') .translate(V2(0,1));
let txb = text('absolute').fontsize(24).fontscale(0.1).translate(V2(0,-1));
draw(sq, txa, txb);
// the square here is 2 times bigger than the previous example
// notice that the 'absolute' text stays the same size
// relative to the coordinate system of the diagram
let sq = square(20).stroke('lightgrey');
let txa = text('auto').fontsize(24).fontscale('auto') .translate(V2(0,2));
let txb = text('absolute').fontsize(24).fontscale(0.1).translate(V2(0,-2));
draw(sq, txa, txb);
// the square here is 2 times bigger than the previous example
// notice that the 'absolute' text stays the same size
// relative to the coordinate system of the diagram
let sq = square(20).stroke('lightgrey');
let txa = text('auto').fontsize(24).fontscale('auto') .translate(V2(0,2));
let txb = text('absolute').fontsize(24).fontscale(0.1).translate(V2(0,-2));
draw(sq, txa, txb);
let sq = square(10).stroke('lightgrey');
let tx = text('hello').textfill('blue');
draw(sq, tx);
Diagram.textfill (
color
:
string )
:
Diagram
let sq = square(10).stroke('lightgrey');
let tx = text('hello').textfill('blue');
draw(sq, tx);
let sq = square(10).stroke('lightgrey');
let tx = text('hello').fontweight('bold').textstroke('blue');
draw(sq, tx);
Diagram.textstroke (
color
:
string )
:
Diagram
let sq = square(10).stroke('lightgrey');
let tx = text('hello').fontweight('bold').textstroke('blue');
draw(sq, tx);
let sq = square(10).stroke('lightgrey');
let tx = text('hello').fontweight('bold').textstroke('blue').textstrokewidth(5);
draw(sq, tx);
Diagram.textstrokewidth (
width
:
number )
:
Diagram
let sq = square(10).stroke('lightgrey');
let tx = text('hello').fontweight('bold').textstroke('blue').textstrokewidth(5);
draw(sq, tx);
// convert the text into mathematical italic
// equivalent to using `textvar`
let sq = square(10).stroke('lightgrey');
let tx = text('hello').text_tovar();
draw(sq, tx);
Diagram.text_tovar (
)
:
Diagram
// convert the text into mathematical italic
// equivalent to using `textvar`
let sq = square(10).stroke('lightgrey');
let tx = text('hello').text_tovar();
draw(sq, tx);
// convert the text from mathematical italic
let sq = square(10).stroke('lightgrey');
let tx = text('hello').text_tovar().text_totext();
draw(sq, tx);
Diagram.text_totext (
)
:
Diagram
// convert the text from mathematical italic
let sq = square(10).stroke('lightgrey');
let tx = text('hello').text_tovar().text_totext();
draw(sq, tx);
Applying the same style multiple time
Let's say you want to draw multiple objects with the same style.
You can try to apply the style to each object, but that's tedious.
And if you want to change the style, you have to manually change it for each object.
let p3 = regular_polygon(3,10).position(V2(-10,10))
.fill('lightblue').stroke('blue').strokewidth(2).strokedasharray([5]);
let p4 = regular_polygon(4,10).position(V2(-10,-10))
.fill('lightblue').stroke('blue').strokewidth(2).strokedasharray([5]);
let p5 = regular_polygon(5,10).position(V2(10,10))
.fill('lightblue').stroke('blue').strokewidth(2).strokedasharray([5]);
let p6 = regular_polygon(6,10).position(V2(10,-10))
.fill('lightblue').stroke('blue').strokewidth(2).strokedasharray([5]);
draw(p3,p4,p5,p6);
let p3 = regular_polygon(3,10).position(V2(-10,10))
.fill('lightblue').stroke('blue').strokewidth(2).strokedasharray([5]);
let p4 = regular_polygon(4,10).position(V2(-10,-10))
.fill('lightblue').stroke('blue').strokewidth(2).strokedasharray([5]);
let p5 = regular_polygon(5,10).position(V2(10,10))
.fill('lightblue').stroke('blue').strokewidth(2).strokedasharray([5]);
let p6 = regular_polygon(6,10).position(V2(10,-10))
.fill('lightblue').stroke('blue').strokewidth(2).strokedasharray([5]);
draw(p3,p4,p5,p6);
To make it simpler, you can use
Diagram.apply
and passing it a function that will style the diagram.
let style = (d) => d.fill('lightblue').stroke('blue').strokewidth(2).strokedasharray([5]);
let p3 = regular_polygon(3,10).position(V2(-10, 10)).apply(style);
let p4 = regular_polygon(4,10).position(V2(-10,-10)).apply(style);
let p5 = regular_polygon(5,10).position(V2( 10, 10)).apply(style);
let p6 = regular_polygon(6,10).position(V2( 10,-10)).apply(style);
draw(p3,p4,p5,p6);
Diagram.apply (
func
:
(d : Diagram) => Diagram )
:
Diagram
let style = (d) => d.fill('lightblue').stroke('blue').strokewidth(2).strokedasharray([5]);
let p3 = regular_polygon(3,10).position(V2(-10, 10)).apply(style);
let p4 = regular_polygon(4,10).position(V2(-10,-10)).apply(style);
let p5 = regular_polygon(5,10).position(V2( 10, 10)).apply(style);
let p6 = regular_polygon(6,10).position(V2( 10,-10)).apply(style);
draw(p3,p4,p5,p6);
You can also combine the diagram first, and style the parent Diagram. This will apply the styles to all the children.
let p3 = regular_polygon(3,10).position(V2(-10, 10));
let p4 = regular_polygon(4,10).position(V2(-10,-10));
let p5 = regular_polygon(5,10).position(V2( 10, 10));
let p6 = regular_polygon(6,10).position(V2( 10,-10));
let ps = diagram_combine(p3,p4,p5,p6)
.fill('lightblue').stroke('blue').strokewidth(2).strokedasharray([5]);
draw(ps);
diagram_combine (
...diagrams
:
Diagram[] )
:
Diagram
let p3 = regular_polygon(3,10).position(V2(-10, 10));
let p4 = regular_polygon(4,10).position(V2(-10,-10));
let p5 = regular_polygon(5,10).position(V2( 10, 10));
let p6 = regular_polygon(6,10).position(V2( 10,-10));
let ps = diagram_combine(p3,p4,p5,p6)
.fill('lightblue').stroke('blue').strokewidth(2).strokedasharray([5]);
draw(ps);
Or you can change the default style of the diagram by changing the values is
default_diagram_style
.
default_diagram_style["fill"] = 'lightblue';
default_diagram_style["stroke"] = 'blue';
default_diagram_style["stroke-width"] = 2;
default_diagram_style["stroke-dasharray"] = [5];
let p3 = regular_polygon(3,10).position(V2(-10, 10));
let p4 = regular_polygon(4,10).position(V2(-10,-10));
let p5 = regular_polygon(5,10).position(V2( 10, 10));
let p6 = regular_polygon(6,10).position(V2( 10,-10));
draw(p3,p4,p5,p6);
default_diagram_style["fill"] = 'lightblue';
default_diagram_style["stroke"] = 'blue';
default_diagram_style["stroke-width"] = 2;
default_diagram_style["stroke-dasharray"] = [5];
let p3 = regular_polygon(3,10).position(V2(-10, 10));
let p4 = regular_polygon(4,10).position(V2(-10,-10));
let p5 = regular_polygon(5,10).position(V2( 10, 10));
let p6 = regular_polygon(6,10).position(V2( 10,-10));
draw(p3,p4,p5,p6);
This also works for
default_text_diagram_style
and
default_textdata
.
// "fill" : string,
// "stroke" : string,
// "stroke-width" : number,
// "stroke-linecap" : string,
// "stroke-dasharray" : number[],
// "stroke-linejoin" : string,
// "vector-effect" : string,
// "opacity" : number,
default_text_diagram_style
// "fill" : string,
// "stroke" : string,
// "stroke-width" : number,
// "stroke-linecap" : string,
// "stroke-dasharray" : number[],
// "stroke-linejoin" : string,
// "vector-effect" : string,
// "opacity" : number,
// "text" : string,
// "font-family" : string,
// "font-size" : number,
// "font-weight" : string,
// "text-anchor" : string,
// "dominant-baseline" : string,
// "angle" : number,
// "font-style" : string,
// "font-scale" : number,
// "text" : string,
// "font-family" : string,
// "font-size" : number,
// "font-weight" : string,
// "text-anchor" : string,
// "dominant-baseline" : string,
// "angle" : number,
// "font-style" : string,
// "font-scale" : number,
You can reset the default style by calling
reset_default_styles()
.