1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
|
import div from require 'mmm.dom'
if MODE ~= 'CLIENT'
class Dummy
render: =>
div 'Interactive Example not available with Server-Side rendering', style:
position: 'relative'
resize: 'horizontal'
overflow: 'hidden'
width: '480px'
height: '270px'
'min-width': '270px'
'max-width': '100%'
margin: 'auto'
padding: '10px'
boxSizing: 'border-box'
background: 'var(--gray-bright)'
return {
UIDemo: Dummy
Example: Dummy
}
import CanvasApp from require 'mmm.canvasapp'
class UIDemo extends CanvasApp
width: nil
height: nil
new: () =>
super!
@canvas.width = nil
@canvas.height = nil
@canvas.style.width = '100%'
@canvas.style.height = '100%'
@canvas.style.border = '2px solid var(--gray-dark)'
@node = div @canvas, style: {
position: 'relative'
resize: 'horizontal'
overflow: 'hidden'
width: '480px'
height: '270px'
minWidth: '270px'
maxWidth: '100%'
margin: 'auto'
padding: '10px'
boxSizing: 'border-box'
}
-- match size of current parent element and return it (for interactive resizing in the demo)
updateSize: =>
{ :clientWidth, :clientHeight } = @canvas.parentElement
@canvas.width, @canvas.height = clientWidth, clientHeight
@canvas.width, @canvas.height
-- set up a coordinate system such that the virtual viewport
-- of size (w, h) is centered on (0,0) and fills the canvas
-- returns remaining margins on the two axes
fit: (w, h) =>
width, height = @updateSize!
@ctx\translate width/2, height/2
-- maximum scale without cropping either axis
scale = math.min (width/w), (height/h)
@ctx\scale scale, scale
-- calculate remaining space on x/y axis
rx = (width/scale) - w
ry = (height/scale) - h
-- margins are half of the remaining space
rx / 2, ry / 2
strokeRect: (cx, cy, w, h) =>
lw = @ctx.lineWidth / 2
@ctx\strokeRect cx - w/2 + lw, cy - h/2 + lw,
w - 2*lw, h - 2*lw,
class Box
new: (@cx, @cy, @w, @h) =>
rect: =>
@cx, @cy, @w, @h
class Example extends UIDemo
click: =>
if @naive
@naive = false
else
if @show_boxes
@naive = true
@show_boxes = not @show_boxes
text: (box, text, align='center', my=.5) =>
mx = .1
@ctx.textAlign = align
if align == 'left'
@ctx\fillText text, box.cx + mx - box.w/2, box.cy + my
else if align == 'center'
@ctx\fillText text, box.cx, box.cy + my
if align == 'right'
@ctx\fillText text, box.cx - mx + box.w/2, box.cy + my
{
:UIDemo
:Example
:Box
}
|