5 CLICK_FUZ = 10 # this far away from things is close enough to be "clicked on"
6 PROX_MAX = CLICK_FUZ * CLICK_FUZ
23 set_style_class = (args) ->
24 args.el.setAttribute 'class', "#{args.class} #{STYLE_TO_CLASS[args.style]}"
26 # json (compiled to javascript and minified) is ~8% smaller than the resulting xml
27 json_to_svg = (json) ->
28 for tag, attrs of json
29 el = document.createElementNS 'http://www.w3.org/2000/svg', tag
33 el.appendChild json_to_svg child
34 else if k is 'contents'
35 el.appendChild document.createTextNode v
41 # public vars: x, y, width, height, el
44 constructor: (args) ->
50 @width = args.width ? 50
51 @height = args.height ? 34
52 @style = args.style ? STYLE_NORMAL
57 proximity: (xy) -> # return the square of the distance to your visible bits
62 class Control extends Visible
64 class Widget extends Visible
65 #sub-classes are expected to implement all of these:
68 controls: -> # create controls, return them
72 class RectWidget extends Widget
73 constructor: (args) ->
76 @el = json_to_svg rect:
88 return new RectWidget @
91 set_style_class el: @el, class: 'box', style: style
94 @el.setAttribute 'x', @x + 1
95 @el.setAttribute 'y', @y + 1
96 proximity: (xy) -> # return the square of the distance to your visible bits
102 if x > @x - CLICK_FUZ and x < @x + @width + CLICK_FUZ
104 if y < @y + @height / 2
107 new_prox = @y + @height - y
111 if y > @y - CLICK_FUZ and y < @y + @height + CLICK_FUZ
113 if x < @x + @width / 2
116 new_prox = @x + @width - x
120 if in_x and in_y and prox > PROX_MAX
123 controls: -> # create controls, return them
127 # called automatically on domcontentloaded
130 $container = $ '.crayon_mockup'
131 svg = json_to_svg svg: width: width, height: height, viewBox: "0 0 #{width} #{height}"
133 $container.append $svg
134 svg.appendChild json_to_svg filter:
135 id: 'crayon', filterUnits: 'userSpaceOnUse'
136 x: '-5%', y: '-5%', height: '110%', width: '110%'
138 { feTurbulence: baseFrequency: '.3', numOctaves: '2', type: 'fractalNoise' }
139 { feDisplacementMap: scale: '6', xChannelSelector: 'R', in: 'SourceGraphic' }
141 svg.appendChild json_to_svg style:
143 contents: '.box.normal,.box.hover,.box.selected{filter: url(#crayon)}'
145 # create canvas border
146 svg.appendChild json_to_svg rect:
150 height: height - 2 - supply_height
151 class: 'canvas_border'
155 { width: 40, height: 40 }
156 { width: 12, height: 50 }
157 { width: 70, height: 12 }
159 widget = new RectWidget {
162 x: 30 + i * 90 + (70 - args.width) / 2
163 y: (supply_height - args.height) / 2
166 supply[widget.id] = widget
171 editing = {} # has controls
173 drag_from = x: 0, y: 0 # mouse was here at last frame of drag
174 shift_key_down = false
176 deselect_all = (args) ->
177 except = args?.except ? null
178 for id, w of selected
179 w.set_style STYLE_NORMAL
181 closest_widget = (widgets, xy) ->
185 new_prox = w.proximity xy
192 svg_event_to_xy = (e) ->
194 svg_offset = $svg.offset()
196 x: Math.round(e.pageX - svg_offset.left)
197 y: Math.round(e.pageY - svg_offset.top)
201 if dragging # two mousedowns in a row?! it happens
203 xy = svg_event_to_xy e
204 if xy.y < supply_height
205 closest = closest_widget supply, xy
207 closest = closest.clone()
208 on_canvas[closest.id] = closest
210 closest = closest_widget on_canvas, xy
212 unless (shift_key_down or selected[closest.id]?)
213 deselect_all except: closest
214 selected[closest.id] = closest
215 closest.set_style STYLE_DRAGGING
224 for id, w of selected
225 if w.y < supply_height
229 w.set_style STYLE_SELECTED
234 xy = svg_event_to_xy e
236 return if drag_from.x is xy.x and drag_from.y is xy.y
237 rel_x = xy.x - drag_from.x
238 rel_y = xy.y - drag_from.y
240 for id, w of selected
241 w.move x: w.x + rel_x, y: w.y + rel_y
243 hover = closest_widget on_canvas, xy
245 hover = closest_widget supply, xy
246 if hover != prev_hover
249 if selected[prev_hover.id]?
250 prev_hover.set_style STYLE_SELECTED
252 prev_hover.set_style STYLE_NORMAL
254 hover.set_style STYLE_HOVER
257 $svg.mousedown mousedown
259 $svg.mousemove mousemove
260 $(document).on 'keyup keydown', (e) ->
261 shift_key_down = e.shiftKey
263 #($ document).keydown (e) ->