| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent ed41795 commit 68a6600
4 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,130 @@ | |||
| 1 | + /* | ||
| 2 | + JavaScript functions that are executed by running the corresponding methods of a Canvas object | ||
| 3 | + Donot use these functions by making a js file. Instead use the python Canvas class. | ||
| 4 | + See canvas.py for help on how to use the Canvas class to draw on the HTML Canvas | ||
| 5 | + */ | ||
| 6 | + | ||
| 7 | + //Manages the output of code executed in IPython kernel | ||
| 8 | + function output_callback(out, block){ | ||
| 9 | + console.log(out); | ||
| 10 | + script = out.content.data['text/html']; | ||
| 11 | + console.log(script); | ||
| 12 | + script = script.substr(8, script.length - 17); | ||
| 13 | + console.log(script); | ||
| 14 | + eval(script) | ||
| 15 | + } | ||
| 16 | + | ||
| 17 | + //Handles mouse click by calling mouse_click of Canvas object with the co-ordinates as arguments | ||
| 18 | + function click_callback(element, event, varname){ | ||
| 19 | + var rect = element.getBoundingClientRect(); | ||
| 20 | + var x = event.clientX - rect.left; | ||
| 21 | + var y = event.clientY - rect.top; | ||
| 22 | + var kernel = IPython.notebook.kernel; | ||
| 23 | + var exec_str = varname + ".mouse_click(" + String(x) + ", " + String(y) + ")"; | ||
| 24 | + console.log(exec_str); | ||
| 25 | + kernel.execute(exec_str,{'iopub': {'output': output_callback}}, {silent: false}); | ||
| 26 | + } | ||
| 27 | + | ||
| 28 | + function rgbToHex(r,g,b){ | ||
| 29 | + var hexValue=(r<<16) + (g<<8) + (b<<0); | ||
| 30 | + var hexString=hexValue.toString(16); | ||
| 31 | + hexString ='#' + Array(7-hexString.length).join('0') + hexString; //Add 0 padding | ||
| 32 | + return hexString; | ||
| 33 | + } | ||
| 34 | + | ||
| 35 | + function toRad(x){ | ||
| 36 | + return x*Math.PI/180; | ||
| 37 | + } | ||
| 38 | + | ||
| 39 | + //Canvas class to store variables | ||
| 40 | + function Canvas(id){ | ||
| 41 | + this.canvas = document.getElementById(id); | ||
| 42 | + this.ctx = this.canvas.getContext("2d"); | ||
| 43 | + this.WIDTH = this.canvas.width; | ||
| 44 | + this.HEIGHT = this.canvas.height; | ||
| 45 | + this.MOUSE = {x:0,y:0}; | ||
| 46 | + } | ||
| 47 | + | ||
| 48 | + //Sets the fill color with which shapes are filled | ||
| 49 | + Canvas.prototype.fill = function(r, g, b){ | ||
| 50 | + this.ctx.fillStyle = rgbToHex(r,g,b); | ||
| 51 | + } | ||
| 52 | + | ||
| 53 | + //Set the stroke color | ||
| 54 | + Canvas.prototype.stroke = function(r, g, b){ | ||
| 55 | + this.ctx.strokeStyle = rgbToHex(r,g,b); | ||
| 56 | + } | ||
| 57 | + | ||
| 58 | + //Set width of the lines/strokes | ||
| 59 | + Canvas.prototype.strokeWidth = function(w){ | ||
| 60 | + this.ctx.lineWidth = w; | ||
| 61 | + } | ||
| 62 | + | ||
| 63 | + //Draw a rectangle with top left at (x,y) with 'w' width and 'h' height | ||
| 64 | + Canvas.prototype.rect = function(x, y, w, h){ | ||
| 65 | + this.ctx.fillRect(x,y,w,h); | ||
| 66 | + } | ||
| 67 | + | ||
| 68 | + //Draw a line with (x1, y1) and (x2, y2) as end points | ||
| 69 | + Canvas.prototype.line = function(x1, y1, x2, y2){ | ||
| 70 | + this.ctx.beginPath(); | ||
| 71 | + this.ctx.moveTo(x1, y1); | ||
| 72 | + this.ctx.lineTo(x2, y2); | ||
| 73 | + this.ctx.stroke(); | ||
| 74 | + } | ||
| 75 | + | ||
| 76 | + //Draw an arc with (x, y) as centre, 'r' as radius from angles start to stop | ||
| 77 | + Canvas.prototype.arc = function(x, y, r, start, stop){ | ||
| 78 | + this.ctx.beginPath(); | ||
| 79 | + this.ctx.arc(x, y, r, toRad(start), toRad(stop)); | ||
| 80 | + this.ctx.stroke(); | ||
| 81 | + } | ||
| 82 | + | ||
| 83 | + //Clear the HTML canvas | ||
| 84 | + Canvas.prototype.clear = function(){ | ||
| 85 | + this.ctx.clearRect(0, 0, this.WIDTH, this.HEIGHT); | ||
| 86 | + } | ||
| 87 | + | ||
| 88 | + //Change font, size and style | ||
| 89 | + Canvas.prototype.font = function(font_str){ | ||
| 90 | + this.ctx.font = font_str; | ||
| 91 | + } | ||
| 92 | + | ||
| 93 | + //Draws "filled" text on the canvas | ||
| 94 | + Canvas.prototype.fill_text = function(text, x, y){ | ||
| 95 | + this.ctx.fillText(text, x, y); | ||
| 96 | + } | ||
| 97 | + | ||
| 98 | + //Write text on the canvas | ||
| 99 | + Canvas.prototype.stroke_text = function(text, x, y){ | ||
| 100 | + this.ctx.strokeText(text, x, y); | ||
| 101 | + } | ||
| 102 | + | ||
| 103 | + | ||
| 104 | + //Test if the canvas functions are working | ||
| 105 | + Canvas.prototype.test_run = function(){ | ||
| 106 | + var dbg = false; | ||
| 107 | + if(dbg) | ||
| 108 | + alert("1"); | ||
| 109 | + this.clear(); | ||
| 110 | + if(dbg) | ||
| 111 | + alert("2"); | ||
| 112 | + this.fill(0, 200, 0); | ||
| 113 | + if(dbg) | ||
| 114 | + alert("3"); | ||
| 115 | + this.rect(this.MOUSE.x, this.MOUSE.y, 100, 200); | ||
| 116 | + if(dbg) | ||
| 117 | + alert("4"); | ||
| 118 | + this.stroke(0, 0, 50); | ||
| 119 | + if(dbg) | ||
| 120 | + alert("5"); | ||
| 121 | + this.line(0, 0, 100, 100); | ||
| 122 | + if(dbg) | ||
| 123 | + alert("6"); | ||
| 124 | + this.stroke(200, 200, 200); | ||
| 125 | + if(dbg) | ||
| 126 | + alert("7"); | ||
| 127 | + this.arc(200, 100, 50, 0, 360); | ||
| 128 | + if(dbg) | ||
| 129 | + alert("8"); | ||
| 130 | + } | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,122 @@ | |||
| 1 | + from IPython.display import HTML, display, clear_output | ||
| 2 | + | ||
| 3 | + _canvas = """ | ||
| 4 | + <script type="text/javascript" src="./canvas.js"></script> | ||
| 5 | + <div> | ||
| 6 | + <canvas id="{0}" width="{1}" height="{2}" style="background:rgba(158, 167, 184, 0.2);" onclick='click_callback(this, event, "{3}")'></canvas> | ||
| 7 | + </div> | ||
| 8 | + | ||
| 9 | + <script> var {0}_canvas_object = new Canvas("{0}");</script> | ||
| 10 | + """ | ||
| 11 | + | ||
| 12 | + class Canvas: | ||
| 13 | + """Inherit from this class to manage the HTML canvas element in jupyter notebooks. | ||
| 14 | + To create an object of this class any_name_xyz = Canvas("any_name_xyz") | ||
| 15 | + The first argument given must be the name of the object being create | ||
| 16 | + IPython must be able to refernce the variable name that is being passed | ||
| 17 | + """ | ||
| 18 | + | ||
| 19 | + def __init__(self, varname, id=None, width=800, height=600): | ||
| 20 | + """""" | ||
| 21 | + self.name = varname | ||
| 22 | + self.id = id or varname | ||
| 23 | + self.width = width | ||
| 24 | + self.height = height | ||
| 25 | + self.html = _canvas.format(self.id, self.width, self.height, self.name) | ||
| 26 | + self.exec_list = [] | ||
| 27 | + display(HTML(self.html)) | ||
| 28 | + | ||
| 29 | + def mouse_click(self, x, y): | ||
| 30 | + "Override this method to handle mouse click at position (x, y)" | ||
| 31 | + raise NotImplementedError | ||
| 32 | + | ||
| 33 | + def mouse_move(self, x, y): | ||
| 34 | + raise NotImplementedError | ||
| 35 | + | ||
| 36 | + def exec(self, exec_str): | ||
| 37 | + "Stores the command to be exectued to a list which is used later during update()" | ||
| 38 | + if not isinstance(exec_str, str): | ||
| 39 | + print("Invalid execution argument:",exec_str) | ||
| 40 | + self.alert("Recieved invalid execution command format") | ||
| 41 | + prefix = "{0}_canvas_object.".format(self.id) | ||
| 42 | + self.exec_list.append(prefix + exec_str + ';') | ||
| 43 | + | ||
| 44 | + def fill(self, r, g, b): | ||
| 45 | + "Changes the fill color to a color in rgb format" | ||
| 46 | + self.exec("fill({0}, {1}, {2})".format(r, g, b)) | ||
| 47 | + | ||
| 48 | + def stroke(self, r, g, b): | ||
| 49 | + "Changes the colors of line/strokes to rgb" | ||
| 50 | + self.exec("stroke({0}, {1}, {2})".format(r, g, b)) | ||
| 51 | + | ||
| 52 | + def strokeWidth(self, w): | ||
| 53 | + "Changes the width of lines/strokes to 'w' pixels" | ||
| 54 | + self.exec("strokeWidth({0})".format(w)) | ||
| 55 | + | ||
| 56 | + def rect(self, x, y, w, h): | ||
| 57 | + "Draw a rectangle with 'w' width, 'h' height and (x, y) as the top-left corner" | ||
| 58 | + self.exec("rect({0}, {1}, {2}, {3})".format(x, y, w, h)) | ||
| 59 | + | ||
| 60 | + def rect_n(self, xn, yn, wn, hn): | ||
| 61 | + "Similar to rect(), but the dimensions are normalized to fall between 0 and 1" | ||
| 62 | + x = round(xn * self.width) | ||
| 63 | + y = round(yn * self.height) | ||
| 64 | + w = round(wn * self.width) | ||
| 65 | + h = round(hn * self.height) | ||
| 66 | + self.rect(x, y, w, h) | ||
| 67 | + | ||
| 68 | + def line(self, x1, y1, x2, y2): | ||
| 69 | + "Draw a line from (x1, y1) to (x, y2)" | ||
| 70 | + self.exec("line({0}, {1}, {2}, {3})".format(x1, y1, x2, y2)) | ||
| 71 | + | ||
| 72 | + def line_n(self, x1n, y1n, x2n, y2n): | ||
| 73 | + "Similar to line(), but the dimensions are normalized to fall between 0 and 1" | ||
| 74 | + x1 = round(x1n * self.width) | ||
| 75 | + y1 = round(y1n * self.height) | ||
| 76 | + x2 = round(x2n * self.width) | ||
| 77 | + y2 = round(y2n * self.height) | ||
| 78 | + self.line(x1, y1, x2, y2) | ||
| 79 | + | ||
| 80 | + def arc(self, x, y, r, start, stop): | ||
| 81 | + "Draw an arc with (x, y) as centre, 'r' as radius from angles 'start' to 'stop'" | ||
| 82 | + self.exec("arc({0}, {1}, {2}, {3}, {4})".format(x, y, r, start, stop)) | ||
| 83 | + | ||
| 84 | + def arc_n(self, xn ,yn, rn, start, stop): | ||
| 85 | + """Similar to arc(), but the dimensions are normalized to fall between 0 and 1 | ||
| 86 | + The normalizing factor for radius is selected between width and height by seeing which is smaller | ||
| 87 | + """ | ||
| 88 | + x = round(xn * self.width) | ||
| 89 | + y = round(yn * self.height) | ||
| 90 | + r = round(rn * min(self.width, self.height)) | ||
| 91 | + self.arc(x, y, r, start, stop) | ||
| 92 | + | ||
| 93 | + def clear(self): | ||
| 94 | + "Clear the HTML canvas" | ||
| 95 | + self.exec("clear()") | ||
| 96 | + | ||
| 97 | + def font(self, font): | ||
| 98 | + "Changes the font of text" | ||
| 99 | + self.exec('font("{0}")'.format(font)) | ||
| 100 | + | ||
| 101 | + def text(self, txt, x, y, fill = True): | ||
| 102 | + "Display a text at (x, y)" | ||
| 103 | + if fill: | ||
| 104 | + self.exec('fill_text("{0}", {1}, {2})'.format(txt, x, y)) | ||
| 105 | + else: | ||
| 106 | + self.exec('stroke_text("{0}", {1}, {2})'.format(txt, x, y)) | ||
| 107 | + | ||
| 108 | + def text_n(self, txt, xn, yn, fill = True): | ||
| 109 | + "Similar to text(), but with normalized coordinates" | ||
| 110 | + x = round(xn * self.width) | ||
| 111 | + y = round(yn * self.height) | ||
| 112 | + self.text(text, x, y, fill) | ||
| 113 | + | ||
| 114 | + def alert(self, message): | ||
| 115 | + "Immediately display an alert" | ||
| 116 | + display(HTML('<script>alert("{0}")</script>'.format(message))) | ||
| 117 | + | ||
| 118 | + def update(self): | ||
| 119 | + "Execute the JS code to execute the commands queued by exec()" | ||
| 120 | + exec_code = "<script>\n"+'\n'.join(self.exec_list)+"\n</script>" | ||
| 121 | + self.exec_list = [] | ||
| 122 | + display(HTML(exec_code)) | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments