Programmatically generate SVG (vector) images, animations, and interactive Jupyter widgets
1javascript = ''' 2require.undef('drawingview'); 3 4define('drawingview', ['@jupyter-widgets/base'], function(widgets) { 5 var DrawingView = widgets.DOMWidgetView.extend({ 6 render: function() { 7 this.container = document.createElement('a'); 8 this.image_changed(); 9 this.container.appendChild(this.svg_view); 10 this.el.appendChild(this.container); 11 this.model.on('change:_image', this.image_changed, this); 12 this.model.on('change:_mousemove_blocked', this.block_changed, 13 this); 14 this.model.on('change:frame_delay', this.delay_changed, 15 this); 16 this.model.on('change:_frame_blocked', this.delay_changed, 17 this); 18 this.model.on('change:disable', this.delay_changed, 19 this); 20 this.delay_changed(); 21 }, 22 image_changed: function() { 23 this.container.innerHTML = this.model.get('_image'); 24 this.svg_view = this.container.getElementsByTagName('svg')[0]; 25 this.cursor_point = this.svg_view.createSVGPoint(); 26 this.register_events(); 27 }, 28 last_move: null, 29 last_mousemove_blocked: null, 30 last_timer: null, 31 block_changed: function() { 32 var widget = this; 33 window.setTimeout(function() { 34 if (widget.model.get('_mousemove_blocked') 35 != widget.last_mousemove_blocked && widget.last_move) { 36 widget.send_mouse_event('mousemove', widget.last_move); 37 } 38 }, 0); 39 }, 40 send_mouse_event: function(name, e) { 41 this.last_move = null; 42 if (this.model.get('disable')) { 43 return; 44 } 45 46 this.cursor_point.x = e.clientX; 47 this.cursor_point.y = e.clientY; 48 var svg_pt = this.cursor_point.matrixTransform( 49 this.svg_view.getScreenCTM().inverse()); 50 51 this.send({ 52 name: name, 53 x: svg_pt.x, 54 y: -svg_pt.y, 55 type: e.type, 56 button: e.button, 57 buttons: e.buttons, 58 shiftKey: e.shiftKey, 59 altKey: e.altKey, 60 ctrlKey: e.ctrlKey, 61 metaKey: e.metaKey, 62 clientX: e.clientX, 63 clientY: e.clientY, 64 movementX: e.movementX, 65 movementY: e.movementY, 66 timeStamp: e.timeStamp, 67 targetId: e.target ? e.target.id : null, 68 currentTargetId: e.currentTarget ? e.currentTarget.id : null, 69 relatedTargetId: e.relatedTarget ? e.relatedTarget.id : null, 70 }); 71 }, 72 delay_changed: function() { 73 var widget = this; 74 window.clearTimeout(widget.last_timer); 75 if (widget.model.get('disable')) { 76 return; 77 } 78 var delay = widget.model.get('frame_delay'); 79 if (delay > 0) { 80 widget.last_timer = window.setTimeout(function() { 81 widget.send_timed_event('timed'); 82 }, delay); 83 } 84 }, 85 send_timed_event: function(name) { 86 if (this.model.get('disable')) { 87 return; 88 } 89 90 this.send({ 91 name: name, 92 }); 93 }, 94 register_events: function() { 95 var widget = this; 96 this.svg_view.addEventListener('mousedown', function(e) { 97 e.preventDefault(); 98 widget.send_mouse_event('mousedown', e); 99 }); 100 this.svg_view.addEventListener('mousemove', function(e) { 101 e.preventDefault(); 102 if (widget.model.get('_mousemove_blocked') 103 == widget.last_mousemove_blocked) { 104 widget.last_move = e; 105 } else { 106 widget.send_mouse_event('mousemove', e); 107 } 108 }); 109 this.svg_view.addEventListener('mouseup', function(e) { 110 e.preventDefault(); 111 widget.send_mouse_event('mouseup', e); 112 }); 113 } 114 }); 115 116 return { 117 DrawingView: DrawingView 118 }; 119}); 120'''