5 CLICK_FUZ = 10 # this far away from things is close enough to be "clicked on"
6 PROX_MAX = CLICK_FUZ * CLICK_FUZ
15 # json (compiled to javascript and minified) is ~8% smaller than the resulting xml
16 json_to_svg = (json) ->
17 for tag, attrs of json
18 el = document.createElementNS 'http://www.w3.org/2000/svg', tag
22 el.appendChild json_to_svg child
27 # public vars: x, y, width, height, el
29 constructor: (args) ->
33 @width = args?.width ? 50
34 @height = args?.height ? 34
40 proximity: (xy) -> # return the square of the distance to your visible bits
43 return if @style is style
44 if style is STYLE_NORMAL
45 @el.setAttribute 'style', 'filter: url(#crayon)'
47 if @style is STYLE_NORMAL
48 @el.setAttribute 'style', ''
51 @el.setAttribute 'class', "#{@css_class}"
53 @el.setAttribute 'class', "#{@css_class} selected"
55 @el.setAttribute 'class', "#{@css_class} hover"
57 @el.setAttribute 'class', "#{@css_class} dragging"
58 # FIXME when STYLE_EDITING
60 controls: -> # create controls, return them
64 class RectWidget extends Widget
65 constructor: (args) ->
68 @el = json_to_svg rect:
74 style: 'filter: url(#crayon)'
76 return new RectWidget @
79 @el.setAttribute 'x', @x + 1
80 @el.setAttribute 'y', @y + 1
81 proximity: (xy) -> # return the square of the distance to your visible bits
87 if x > @x - CLICK_FUZ and x < @x + @width + CLICK_FUZ
89 if y < @y + @height / 2
92 new_prox = @y + @height - y
96 if y > @y - CLICK_FUZ and y < @y + @height + CLICK_FUZ
98 if x < @x + @width / 2
101 new_prox = @x + @width - x
105 if in_x and in_y and prox > PROX_MAX
108 controls: -> # create controls, return them
112 # called automatically on domcontentloaded
115 $container = $ '.crayon_mockup'
116 svg = json_to_svg svg: width: width, height: height, viewBox: "0 0 #{width} #{height}"
118 $container.append $svg
119 svg.appendChild json_to_svg filter:
120 id: 'crayon', filterUnits: 'userSpaceOnUse'
121 x: '-5%', y: '-5%', height: '110%', width: '110%'
123 { feTurbulence: baseFrequency: '.3', numOctaves: '2', type: 'fractalNoise' }
124 { feDisplacementMap: scale: '6', xChannelSelector: 'R', in: 'SourceGraphic' }
127 # create canvas border
128 svg.appendChild json_to_svg rect:
132 height: height - 2 - supply_height
133 class: 'canvas_border'
137 new RectWidget width: 12, height: 50
138 new RectWidget width: 70, height: 12
140 for widget, i in supply
142 x: 30 + i * 90 + (70 - widget.width) / 2
143 y: (supply_height - widget.height) / 2
145 svg.appendChild widget.el
150 editing = [] # has controls
152 dragging_offset = x: 0, y: 0 # from mouse x,y -> widget x,y
155 closest_widget = (widgets, xy) ->
159 new_prox = w.proximity xy
164 return [prox, closest]
166 svg_event_to_xy = (e) ->
168 svg_offset = $svg.offset()
170 x: Math.round(e.pageX - svg_offset.left)
171 y: Math.round(e.pageY - svg_offset.top)
173 $svg.mousedown (e) ->
174 xy = svg_event_to_xy e
175 if xy.y < supply_height
176 closest = closest_widget supply, xy
178 closest[1] = closest[1].clone()
179 svg.appendChild closest[1].el
181 closest = closest_widget on_canvas, xy
183 selected = [closest[1]]
184 closest[1].set_style STYLE_DRAGGING
186 dragging_offset.x = closest[1].x - xy.x
187 dragging_offset.y = closest[1].y - xy.y
194 if selected[0].y > supply_height
195 on_canvas.push selected[0]
197 svg.removeChild selected[0].el
201 xy = svg_event_to_xy e
203 xy.x += dragging_offset.x
204 xy.y += dragging_offset.y
207 closest = closest_widget on_canvas, xy
214 w.set_style STYLE_HOVER
216 w.set_style STYLE_NORMAL
218 $svg.mousemove mousemove
219 #($ document).keydown (e) ->