diff --git a/articles/circle_script/circle_setter.html b/articles/circle_script/circle_setter.html index 06e3926..6726894 100644 --- a/articles/circle_script/circle_setter.html +++ b/articles/circle_script/circle_setter.html @@ -10,48 +10,30 @@
- - - - - - - - - - - @@ -138,55 +122,46 @@ @@ -194,14 +169,12 @@ @@ -246,44 +219,42 @@ @@ -291,14 +262,12 @@ @@ -336,8 +305,7 @@ @@ -346,23 +314,23 @@
- - + - + - - + + - + - + +
@@ -394,9 +362,6 @@ - diff --git a/articles/circle_script/circle_setter.js b/articles/circle_script/circle_setter.js index 2504632..68b0b1e 100644 --- a/articles/circle_script/circle_setter.js +++ b/articles/circle_script/circle_setter.js @@ -4,8 +4,12 @@ const glyphs = []; const vowels = []; const consonants = []; +var svg; +var connections_container; + $(document).ready(function() { svg = $('svg#arena')[0]; + connections_container = $('svg#arena #connections'); major_radius = parseFloat($('circle').attr('r')); $(document).on("mouseup", on_mouse_up); @@ -17,9 +21,8 @@ $(document).ready(function() { const mouse_position = svg_from_dom({x:event.clientX, y:event.clientY}, svg); - var g = make_new_glyph_from($("#consonant_copy_from_here")); - g.position = mouse_position; - set_transform(g.element, mouse_position, appropriate_angle(mouse_position)); + var g = make_new_consonant(); + set_location(g, mouse_position); currently_dragging = g; }) @@ -28,11 +31,10 @@ $(document).ready(function() { let selected = $(this); receptacle.html(selected.html()); + var g = make_new_vowel(); + const mouse_position = svg_from_dom({x:event.clientX, y:event.clientY}, svg); - - var g = make_new_glyph_from($("#vowel_copy_from_here")); - g.position = mouse_position; - set_transform(g.element, mouse_position, appropriate_angle(mouse_position)); + set_location(g, mouse_position); currently_dragging = g; }); @@ -103,52 +105,53 @@ function populate_vowels() { }); } -function on_mouse_down(event) { - // this is called on an element when the mouse is clicked down on it. event.data will contain the glyph object - - currently_dragging = event.data; -} - function make_new_consonant(source) { // create a new glyph object by copying the elements pointed to by source // this will add it to the svg and to the glyphs list var x = {}; x.angle = 0; - x.element = source.clone().attr("id","").attr("onclick", "").attr("onmousedown", ""); + x.element = $("#consonant_copy_from_here").clone().attr("id","").attr("onclick", "").attr("onmousedown", ""); x.element.find("#consonant_put_it_in_here").attr("id",""); x.position = {x:0, y:0}; - set_transform(x.element, x.position, 0); - x.element.on("mousedown", x, on_mouse_down); + x.element.on("mousedown", x, (event) => { currently_dragging = event.data }); $(svg).append(x.element); x.handles = []; - x.handles.push($(ns_elem("circle", svg_ns)).attr("r",2)) - x.handles.push($(ns_elem("circle", svg_ns)).attr("r",2)) - $.each(x.handles, () => $(svg).append(this)); + x.handles.push($(ns_elem("circle", svg_ns))) + x.handles.push($(ns_elem("circle", svg_ns))) + $.each(x.handles, function() { + $(svg).append(this) + this.attr("r", 2); + add_class(this, "handle"); + }); update_handles(x); glyphs.push(x); + x.vowel = false; return x; } -function make_new_glyph_from(source) { +function make_new_vowel(source) { // create a new glyph object by copying the elements pointed to by source // this will add it to the svg and to the glyphs list var x = {}; x.angle = 0; - x.element = source.clone().attr("id","").attr("onclick", "").attr("onmousedown", ""); - x.element.find("#consonant_put_it_in_here").attr("id",""); + x.element = $("#vowel_copy_from_here").clone().attr("id","").attr("onclick", "").attr("onmousedown", ""); x.element.find("#vowel_put_it_in_here").attr("id",""); x.position = {x:0, y:0}; - set_transform(x.element, x.position, 0); - x.element.on("mousedown", x, on_mouse_down); + x.element.on("mousedown", x, (event) => { currently_dragging = event.data }); $(svg).append(x.element); x.handles = []; - x.handles.push($(ns_elem("circle", svg_ns)).attr("r",2)) - x.handles.push($(ns_elem("circle", svg_ns)).attr("r",2)) - $(svg).append(x.handles[0]).append(x.handles[1]); + x.handles.push($(ns_elem("circle", svg_ns))); + x.handles.push($(ns_elem("circle", svg_ns))); + $.each(x.handles, function() { + $(svg).append(this) + this.attr("r", 2); + add_class(this, "handle"); + }); update_handles(x); glyphs.push(x); + x.vowel = true; return x; } @@ -159,12 +162,11 @@ function on_mouse_up(event) { $.each(currently_dragging.handles, function() { $(this).remove(); }); currently_dragging.element.remove(); currently_dragging = null; + connect_vowels(); } if (currently_dragging != null) { - currently_dragging.position = mul(norm(currently_dragging.position), major_radius); - set_transform(currently_dragging.element, currently_dragging.position, appropriate_angle(currently_dragging.position)); - update_handles(currently_dragging); + set_location(currently_dragging, mul(norm(currently_dragging.position), major_radius)); } currently_dragging = null; @@ -190,15 +192,99 @@ $(document).mousemove(function(event) { // get the position inside the svg tag for the mouse if (currently_dragging != null) { + set_location(currently_dragging, add(currently_dragging.position, mouse_move)); update_handles(currently_dragging); - - currently_dragging.position = add(currently_dragging.position, mouse_move); - set_transform(currently_dragging.element, currently_dragging.position, appropriate_angle(currently_dragging.position)); - } }); function update_handles(g) { - set_loc(g.handles[0], get_global_point_at_length(svg, g.element.find('path.glyph,path.vowel-base')[0], 0)) - set_loc(g.handles[1], get_global_point_at_length(svg, g.element.find('path.glyph,path.vowel-base')[0], 1000)) + if (g.element.find('path.glyph,path.vowel-base').length != 0) { + set_loc(g.handles[0], get_global_point_at_length(svg, g.element.find('path.glyph,path.vowel-base')[0], 0)); + set_loc(g.handles[1], get_global_point_at_length(svg, g.element.find('path.glyph,path.vowel-base')[0], 1000)); + } + connect_vowels(); +} + +function set_location(glyph, point) { + glyph.position = point; + glyph.angle = Math.atan2(point.y, point.x); + set_transform(glyph.element, glyph.position, appropriate_angle(point)); + update_handles(glyph); +} + +function connect_vowels() { + let vowels = $.grep(glyphs, (v) => v.vowel); + vowels.sort((a, b) => b.angle - a.angle); + console.log($.map(vowels, (a)=>a.angle)); + + + // clear oout the old connections + + connections_container.html(""); + + if (vowels.length == 0) { + // if there's no vowels, we should have just a bare circle + /*} else if (vowels.length == 1) { + // make a fake point on the other side to connect + let connection = ns_elem("path", svg_ns); + add_class(connection, "intervowel"); + + let path = `M ${start_x} ${start_y} `; + path += `A ${}` + + $(connection).attr("d", `M ${start_x} ${start_y} A ${major_radius} ${major_radius} 0 ${sweep} ${large} ${end_x} ${end_y}`); + + connections_container.append(connection);*/ + } else { + // otherwise iterate over them and connect one to the next + for (let i=0; i < vowels.length; i++) { + //connections_container.append($(ns_elem("circle", svg_ns)).attr("r",1).attr("cx",Math.cos(vowels[i].angle)*major_radius).attr("cy",major_radius*Math.sin(vowels[i].angle))); + let connection = ns_elem("path", svg_ns); + add_class(connection, "intervowel"); + + let first = vowels[i]; + let second = vowels[(i+1)%vowels.length]; + + let start_x = parseFloat(first.handles[1].attr("cx")); + let start_y = parseFloat(first.handles[1].attr("cy")); + + /* abandoned quadratic approach + let roundness = 0.2*Math.abs(first.angle - second.angle); + roundness = first.angle > second.angle ? 1 : 0; + + let s_dx = start_x + (Math.sin(first.angle) * major_radius * roundness); + let s_dy = start_y - (Math.cos(first.angle) * major_radius * roundness); + */ + let end_x = parseFloat(second.handles[0].attr("cx")); + let end_y = parseFloat(second.handles[0].attr("cy")); + /* + let e_dx = end_x - (Math.sin(second.angle) * major_radius * roundness); + let e_dy = end_y + (Math.cos(second.angle) * major_radius * roundness); + + // $(connection).attr("d", `M ${start_x} ${start_y} C ${s_dx} ${s_dy} ${e_dx} ${e_dy} ${end_x} ${end_y}`); + */ + + let distance = -(second.angle - first.angle); + if (vowels.length == 1) { + distance = 1.5*Math.PI; + } + let midpoint; + let sweep = "0"; + let large = "0"; + if (distance < 0) { + distance += 2*Math.PI; + } + if (distance < Math.PI) { + sweep = "0" + large = "0" + } else if (distance < 2*Math.PI) { + sweep = "1" + large = "0" + } + + $(connection).attr("d", `M ${start_x} ${start_y} A ${major_radius} ${major_radius} 0 ${sweep} ${large} ${end_x} ${end_y}`); + + connections_container.append(connection); + } + } } \ No newline at end of file diff --git a/articles/circle_script/circle_setter_utils.js b/articles/circle_script/circle_setter_utils.js index a6fc05f..f7659ac 100644 --- a/articles/circle_script/circle_setter_utils.js +++ b/articles/circle_script/circle_setter_utils.js @@ -6,7 +6,6 @@ SVGElement.prototype.getTransformToElement = SVGElement.prototype.getTransformTo function ns_elem () { if (typeof arguments[0] === "undefined") { console.log('There was an error in the element assist function. Called with no valid tag name!');} var elem; if (typeof arguments[1] === "string") { elem = document.createElementNS(arguments[1], arguments[0]); for (var i=2; i
- - - - - - - - - - - - - - -
- - + [m] [n][ŋ] - - +
- - + [p], [b] [t], [d][k], [g] [q], [ɢ] - - +
- - + [f], [v] [s], [z] [ʔ], [ʡ] - - +
- - + + + [θ], [ð] [ts][x~χ], [ʁ] - - +
- - + [w] [ɹ], [l][j] [h] - - +