D3
OG
Old school D3 from simpler times
All examples
By author
By category
About
zeffii
Full window
Github gist
mediseen0.2
Built with
blockbuilder.org
<!DOCTYPE html> <head> <meta charset="utf-8"> <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js"></script> <style> body { margin:0;position:fixed;top:0;right:0;bottom:0;left:0; } svg { width:100%; height: 100% } </style> </head> <body> <svg></svg> <script> /* MIT license. Dealga McArdle. 2009-2015 Rewrite in Progress. Specifically written for people who have a difficult time figuring out their meds. It's easy for family or a healthcare professional to update and print when changes are made. It parses a medicine descriptor string used to describe most forms of medication. (Universal Medicine Descriptor Language). only caviat is some meds have weird shapes. A solution is to allow the medication descriptor to include a link to a bitmap. Milestones [x] parse csv [x] draw time, number, medication name, dose [x] parse UMDL as vector [ ] parse IMGUR 5 or 7 digit code when no UMDL is present [ ] write up formalized UMDL */ d3.select("body").style("background-color", d3.rgb(255,255,255)) var svg = d3.select("svg"); var defs = svg.append("defs"); var group1 = svg.append("g").classed("group1", true); var group2 = svg.append("g").classed("group2", true); var group3 = svg.append("g").classed("group2", true); var global_transform = "translate(" + [40, 63] + ")"; group1.attr("transform", global_transform) group2.attr("transform", global_transform) group3.attr("transform", global_transform) d3.csv("medilist.csv", generateList); var data = []; function generateList(data){ data = data; var line_height = 23, padding_y = 13, padding_x = 130, type_height = 19, time_height = 29, divider_height = 6, divider_width = 291, ty = 30, my = ty, vert_lines_x_offset = 259, outline_width = {"stroke-width": 0.7 + "px"}, div_style = {"fill": "#424242", "stroke": "none"}, med_style = {"fill": "#837979", "stroke": "none", "font-family": "sans-serif"}, dose_style = {"fill": "#77A2CA", "stroke": "none", "font-family": "sans-serif"}, text_styles = [med_style, dose_style]; function assemble_med_list(data, med_list, time_list){ data.forEach(function(d){ if (d.time in med_list) med_list[d.time].push(d) else { med_list[d.time] = [d] time_list.push(d.time) } }) return [med_list, time_list] } var med_and_time_list = assemble_med_list(data, {}, []); var med_list = med_and_time_list[0]; var time_list = med_and_time_list[1]; function draw_text(text, size, pos, style){ group1.append('text') .text(text) .attr(pos) .style(style) .style({"font-size": size}) } function draw_text2(text, size, pos){ group1.append('text') .text(text.med) .attr(pos) .style(med_style) .style({"font-size": size}) .append('tspan') .text(" " + text.dose) .style(dose_style) } function draw_divider(pos){ group1.append("rect") .attr(pos) .attr({height: divider_height, width: divider_width}) .style(div_style) } function _adjust(ty){ return ty-35 } function buffer_space(n){ return (2 * padding_y) + (n * line_height) } function parse_umdl(d){ var descr_array, descr_object, descr = d.descriptor, descr_length = descr.length; // maybe enforcing this leads to unnecessary complexity // but i like the way it helps keep the description together // optically at least in the csv if ((descr[0] != "(") || (descr[descr_length-1] != ")")){ console.error(descr) console.error("descriptor must be enclosed in parentheses") return } // strip parentheses descr = descr.slice(1, descr_length-1) // split into color(s)|shape|[groovetype|]inscription object descr_array = descr.split("|") if (descr_array.length === 3){ descr_object = { color: descr_array[0].split("/"), shape: descr_array[1], inscription: descr_array[2], numparams: 3 } } else if (descr_array.length === 4){ descr_object = { color: descr_array[0].split("/"), shape: descr_array[1], groovetype: descr_array[2], inscription: descr_array[3], numparams: 4 } } else { var error_message = "descriptor must take form: \n"; error_message += "color(s)|shape|groovetype|inscription\n" error_message += "or\n" error_message += "color|shape|inscription" console.error(error_message) return } return descr_object } function console_debug(d, medicine_object){ console.log("______") console.log(d.descriptor) console.log("color(s):", medicine_object.color) console.log("shape:", medicine_object.shape) if (medicine_object.numparams === 4) console.log("groove type:", medicine_object.groovetype) if (medicine_object.inscription != "_") console.log("inscription:", medicine_object.inscription) } function draw_from_umdl(d, pos){ var medicine_object = parse_umdl(d); // check if this parsed a valid umdl if (!medicine_object){ console.error(d, "didn't parse correctly") // draw questionmark? return } var show_debug = [false, true][0]; if (show_debug) console_debug(d, medicine_object) draw_medicine(medicine_object, pos) } c_list = { "D-pink": "#F171E7" // add custom colors }; function color_list_check(c_in){ if (c_in in c_list) return c_list[c_in] else { console.error(c_in, "not in color list (c_list), add it!") return "#fff" } } function draw_liteline(pos){ // function draw_text(text, size, pos, style){ var y_tweak = 4; var line_start_x = 239; var line_width_x = 630; var line_height_y = type_height+4; group1.append("line") .attr(pos) .attr({x1: line_start_x, y1:0+y_tweak, x2: line_start_x + line_width_x, y2: 0+y_tweak}) .style({"stroke-width": "1px", "stroke": "#eee"}) group1.append("line") .attr(pos) .attr({x1: line_start_x, y1: -line_height_y + y_tweak, x2: line_start_x + line_width_x, y2: -line_height_y + y_tweak}) .style({"stroke-width": "1px", "stroke": "#eee"}) } function draw_vertline(x, total_height){ var line_start_y = -4; group1.append("line") .attr({"transform": "translate(" + [x, 0] + ")"}) .attr({x1: x, y1:line_start_y, x2: x, y2: line_start_y + total_height}) .style({"stroke-width": "1px", "stroke": "#aaa"}) } function draw_medicine(mo, pos){ var med = group2.append("g") var med_r = type_height/2; var shape = mo.shape.toLowerCase(); var size = shape.indexOf("small") >= 0 ? "small" : "normal"; if (size==="small") med_r *= 0.8 // round & round-small if (shape.indexOf("round") >= 0){ med.append("circle") .attr({"cx": pos.x, "cy": pos.y-med_r/2, "r": med_r}) .style({stroke: "#121212", "fill": mo.color[0]}) .style(outline_width) } // oval if (shape.indexOf("oval") >= 0){ var oval_color = color_list_check(mo.color[0]); med.append("ellipse") .attr({"cx": pos.x, "cy": pos.y-med_r/2, "rx": med_r*1.5, "ry": med_r}) .style({stroke: "#121212", "fill": oval_color}) .style(outline_width) } if (mo.groovetype){ var groove = mo.groovetype.toLowerCase(); var g_width = 1; if (groove === "brkthin") g_width = 1 if (groove === "brkwide") g_width = 4 var groove_style = { "stroke": "#000", "stroke-width": g_width +"px", "stroke-opacity": 0.6 }; med.append('line') .attr({x1: pos.x, y1: pos.y, x2: pos.x, y2: pos.y-(med_r*2)}) .style(groove_style) .attr("transform", "translate("+ [0, med_r/2] + ")") if (groove === "brkx"){ med.append('line') .attr({x1: pos.x-med_r, y1: pos.y-(med_r), x2: pos.x+med_r, y2: pos.y-(med_r)}) .style(groove_style) .attr("transform", "translate("+ [0, med_r/2] + ")") } } function side_(dir, med_r){ var th = med_r, two_th = med_r*2, straight_1 = "M" + [0,0,-th*dir,0].join(" "), curve = "C" + [-two_th*dir, 0, -two_th*dir, -two_th, -th*dir, -two_th].join(" "), straight_2 = "L" + [0,-two_th].join(" "); return straight_1 + curve + straight_2; } // capsule if (shape==="capsule"){ var cap = {x: pos.x, y: pos.y+(med_r/2)}; med.append("path") .attr("d", side_(1, med_r)) .style({stroke: "#121212", "fill": mo.color[0]}) .style(outline_width) med.append("path") .attr("d", side_(-1, med_r)) .style({stroke: "#121212", "fill": mo.color[1]}) .style(outline_width) med.attr("transform", "translate(" + [cap.x, cap.y] + ")") } // inscriptions if (mo.inscription != "_"){ group3.append('text') .attr({x: pos.x + 30, y: pos.y}) .text(mo.inscription) .style(med_style) } } var end_height = 0; time_list.forEach(function(d){ my = ty; draw_divider({x: padding_x, y: _adjust(ty)}) var num_items = med_list[d].length; var extra_space = buffer_space(num_items); var text_y = ty + (extra_space / 2) - (padding_y * 1.4); // draw time draw_text(d, time_height, {x: 37, y: text_y-5}, med_style) ty += extra_space // draw details for each med_list[d].forEach(function(m){ draw_text(m.num, type_height, {x: 152, y: my}, med_style) draw_text2(m, type_height, {x: 172, y: my}) draw_liteline({"transform": "translate(" + [172, my] + ")"}) draw_from_umdl(m, {x: 389, y: my}) my += line_height }) end_height = my; }) draw_divider({x: padding_x, y: _adjust(ty)}) // draw vertical markings 'Za Zo Ma Di Wo Do Vr'.split(' ').forEach(function(d, i){ // draw_vertline(x, total_height) var twinky = 35; var line_x = vert_lines_x_offset + 36*i; draw_vertline(line_x, end_height); draw_text(d, 14, {x: line_x+287+(twinky*i), y: 0}) console.log(d) }) console.log("______\nscript finished") /* EOF */ } </script> </body>
https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js