From 0334684c7b92ea68acf4bd53b2e5d7378d3f3862 Mon Sep 17 00:00:00 2001 From: Jason Woofenden Date: Sat, 19 Sep 2015 18:52:15 -0400 Subject: [PATCH] drag offset, proper box proximity, hover --- auto.coffee | 128 +++++++++++++++++++++++++++++++++++++++++++++++++---------- styl.styl | 45 +++++++++++++-------- 2 files changed, 134 insertions(+), 39 deletions(-) diff --git a/auto.coffee b/auto.coffee index fcde726..c415d0b 100644 --- a/auto.coffee +++ b/auto.coffee @@ -2,6 +2,15 @@ width = 800 height = 600 supply_height = 96 +CLICK_FUZ = 10 # this far away from things is close enough to be "clicked on" +PROX_MAX = CLICK_FUZ * CLICK_FUZ + +# constants +STYLE_NORMAL = 0 +STYLE_SELECTED = 1 +STYLE_HOVER = 2 +STYLE_EDITING = 3 +STYLE_DRAGGING = 4 # json (compiled to javascript and minified) is ~8% smaller than the resulting xml json_to_svg = (json) -> @@ -18,16 +27,44 @@ json_to_svg = (json) -> # public vars: x, y, width, height, el class Widget constructor: (args) -> + @style = STYLE_NORMAL @x = args?.x ? 1 @y = args?.y ? 1 @width = args?.width ? 50 @height = args?.height ? 34 + clone: -> + return new Widget @ move: (args) -> @x = args.x @y = args.y + proximity: (xy) -> # return the square of the distance to your visible bits + return PROX_MAX + 1 + set_style: (style) -> + return if @style is style + if style is STYLE_NORMAL + @el.setAttribute 'style', 'filter: url(#crayon)' + else + if @style is STYLE_NORMAL + @el.setAttribute 'style', '' + switch style + when STYLE_NORMAL + @el.setAttribute 'class', "#{@css_class}" + when STYLE_SELECTED + @el.setAttribute 'class', "#{@css_class} selected" + when STYLE_HOVER + @el.setAttribute 'class', "#{@css_class} hover" + when STYLE_DRAGGING + @el.setAttribute 'class', "#{@css_class} dragging" + # FIXME when STYLE_EDITING + @style = style + controls: -> # create controls, return them + return [] + hide_controls: -> + class RectWidget extends Widget constructor: (args) -> super args + @css_class = 'box' @el = json_to_svg rect: x: @x + 1 y: @x + 1 @@ -35,19 +72,46 @@ class RectWidget extends Widget height: @height - 2 class: 'box' style: 'filter: url(#crayon)' + clone: -> + return new RectWidget @ move: (args) -> super args @el.setAttribute 'x', @x + 1 @el.setAttribute 'y', @y + 1 - clone: -> - return new RectWidget @ + proximity: (xy) -> # return the square of the distance to your visible bits + x = xy.x + y = xy.y + prox = PROX_MAX + 1 + in_x = false + in_y = false + if x > @x - CLICK_FUZ and x < @x + @width + CLICK_FUZ + in_x = true + if y < @y + @height / 2 + new_prox = @y - y + else + new_prox = @y + @height - y + new_prox *= new_prox + if new_prox < prox + prox = new_prox + if y > @y - CLICK_FUZ and y < @y + @height + CLICK_FUZ + in_y = true + if x < @x + @width / 2 + new_prox = @x - x + else + new_prox = @x + @width - x + new_prox *= new_prox + if new_prox < prox + prox = new_prox + if in_x and in_y and prox > PROX_MAX + prox = PROX_MAX - 1 + return prox + controls: -> # create controls, return them + return [] + hide_controls: -> # called automatically on domcontentloaded init = -> - offset = null - selected = [] - on_canvas = [] - dragging = false + svg_offset = null $container = $ '.crayon_mockup' svg = json_to_svg svg: width: width, height: height, viewBox: "0 0 #{width} #{height}" $svg = $ svg @@ -80,30 +144,36 @@ init = -> } svg.appendChild widget.el + # editor state + on_canvas = [] + selected = [] + editing = [] # has controls + dragging = false + dragging_offset = x: 0, y: 0 # from mouse x,y -> widget x,y + # todo ask widgets closest_widget = (widgets, xy) -> - closest = [10000, null] + prox = PROX_MAX + 1 + closest = null for w in widgets - x = w.x + w.width / 2 - xy.x - y = w.y + w.height / 2 - xy.y - dist2 = x * x + y * y - if dist2 < closest[0] - closest = [dist2, w] - if closest[1]? - return closest + new_prox = w.proximity xy + if new_prox < prox + prox = new_prox + closest = w + if prox < PROX_MAX + return [prox, closest] return null svg_event_to_xy = (e) -> - unless offset? - offset = $svg.offset() + unless svg_offset? + svg_offset = $svg.offset() return { - x: Math.round(e.pageX - offset.left) - y: Math.round(e.pageY - offset.top) + x: Math.round(e.pageX - svg_offset.left) + y: Math.round(e.pageY - svg_offset.top) } $svg.mousedown (e) -> xy = svg_event_to_xy e if xy.y < supply_height closest = closest_widget supply, xy - console.log closest if closest? closest[1] = closest[1].clone() svg.appendChild closest[1].el @@ -111,7 +181,10 @@ init = -> closest = closest_widget on_canvas, xy if closest? selected = [closest[1]] + closest[1].set_style STYLE_DRAGGING dragging = true + dragging_offset.x = closest[1].x - xy.x + dragging_offset.y = closest[1].y - xy.y mousemove e return false $svg.mouseup (e) -> @@ -125,11 +198,22 @@ init = -> selected = [] return false mousemove = (e) -> + xy = svg_event_to_xy e if dragging - xy = svg_event_to_xy e - xy.x -= selected[0].width / 2 - xy.y -= selected[0].height / 2 + xy.x += dragging_offset.x + xy.y += dragging_offset.y selected[0].move xy + else + closest = closest_widget on_canvas, xy + if closest? + hover = closest[1] + else + hover = null + for w in on_canvas + if w is hover + w.set_style STYLE_HOVER + else + w.set_style STYLE_NORMAL return false $svg.mousemove mousemove #($ document).keydown (e) -> diff --git a/styl.styl b/styl.styl index ef85724..5d41158 100644 --- a/styl.styl +++ b/styl.styl @@ -9,34 +9,45 @@ p margin: 0 * p margin-top: 10px - + +color_crayon = #8c8c8c +color_selected = #544c4c +color_hover = #000 +color_dragging = #9e9373 +color_controls = #000 .crayon_mockup - svg - path + path.polyline fill: none - stroke: #8c8c8c stroke-width: 5 stroke-linecap: butt stroke-linejoin: round stroke-miterlimit: 4 stroke-opacity: 1 stroke-dasharray: none - filter: url(#crayon) + // fails in firefox (must be inline) filter: url(#crayon) rect fill: none rect.canvas_border - overflow: hidden; - stroke: #ccc; - stroke-width: 2; - stroke-linecap: butt; - stroke-linejoin:miter; - stroke-dasharray:2 4; - stroke-dashoffset:1; + overflow: hidden + stroke: #ccc + stroke-width: 2 + stroke-linecap: butt + stroke-linejoin:miter + stroke-dasharray:2 4 + stroke-dashoffset:1 //stroke-opacity:1;marker:none;enable-background:accumulate rect.box - stroke: #8c8c8c; - stroke-width: 4; - stroke-linecap: butt; - stroke-linejoin:miter; - // this doesn't work in firefox: filter: url(#crayon); + stroke: color_crayon + stroke-width: 4 + stroke-linecap: butt + stroke-linejoin:miter + // this doesn't work in firefox: filter: url(#crayon) + rect.box, path.polyline + stroke: color_crayon + rect.box.hover, path.polyline.hover + stroke: color_hover + rect.box.dragging, path.polyline.dragging + stroke: color_dragging + rect.box.selected, path.polyline.selected + stroke: color_selected -- 1.7.10.4