| 
					
				 | 
			
			
				@@ -29,10 +29,18 @@ function newElement(type, x, y, width = 0, height = 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   return element; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-function exportAsPNG({ background, visibleOnly, padding = 10 }) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+function exportAsPNG({ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  exportBackground, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  exportVisibleOnly, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  exportPadding = 10 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+}) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  // deselect & rerender 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   clearSelection(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   drawScene(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  // calculate visible-area coords 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   let subCanvasX1 = Infinity; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   let subCanvasX2 = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   let subCanvasY1 = Infinity; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -45,40 +53,54 @@ function exportAsPNG({ background, visibleOnly, padding = 10 }) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     subCanvasY2 = Math.max(subCanvasY2, getElementAbsoluteY2(element)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  let targetCanvas = canvas; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  if ( visibleOnly ) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    targetCanvas = document.createElement('canvas'); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    targetCanvas.style.display = 'none'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    document.body.appendChild(targetCanvas); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    targetCanvas.width = subCanvasX2 - subCanvasX1 + padding * 2; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    targetCanvas.height = subCanvasY2 - subCanvasY1 + padding * 2; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    const targetCanvas_ctx = targetCanvas.getContext('2d'); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if ( background ) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      targetCanvas_ctx.fillStyle = "#FFF"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      targetCanvas_ctx.fillRect(0, 0, canvas.width, canvas.height); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    targetCanvas_ctx.drawImage( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      canvas, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      subCanvasX1 - padding, // x 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      subCanvasY1 - padding, // y 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      subCanvasX2 - subCanvasX1 + padding * 2, // width 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      subCanvasY2 - subCanvasY1 + padding * 2, // height 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      0, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      0, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      targetCanvas.width, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      targetCanvas.height 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  // create temporary canvas from which we'll export 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  const tempCanvas = document.createElement("canvas"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  const tempCanvasCtx = tempCanvas.getContext("2d"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  tempCanvas.style.display = "none"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  document.body.appendChild(tempCanvas); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  tempCanvas.width = exportVisibleOnly 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    ? subCanvasX2 - subCanvasX1 + exportPadding * 2 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    : canvas.width; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  tempCanvas.height = exportVisibleOnly 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    ? subCanvasY2 - subCanvasY1 + exportPadding * 2 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    : canvas.height; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if (exportBackground) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    tempCanvasCtx.fillStyle = "#FFF"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    tempCanvasCtx.fillRect(0, 0, canvas.width, canvas.height); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  const link = document.createElement('a'); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  link.setAttribute('download', 'excalibur.png'); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  link.setAttribute('href', targetCanvas.toDataURL("image/png")); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  // copy our original canvas onto the temp canvas 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  tempCanvasCtx.drawImage( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    canvas, // source 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    exportVisibleOnly // sx 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      ? subCanvasX1 - exportPadding 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      : 0, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    exportVisibleOnly // sy 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      ? subCanvasY1 - exportPadding 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      : 0, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    exportVisibleOnly // sWidth 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      ? subCanvasX2 - subCanvasX1 + exportPadding * 2 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      : canvas.width, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    exportVisibleOnly // sHeight 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      ? subCanvasY2 - subCanvasY1 + exportPadding * 2 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      : canvas.height, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    0, // dx 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    0, // dy 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    exportVisibleOnly ? tempCanvas.width : canvas.width, // dWidth 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    exportVisibleOnly ? tempCanvas.height : canvas.height // dHeight 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  // create a temporary <a> elem which we'll use to download the image 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  const link = document.createElement("a"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  link.setAttribute("download", "excalibur.png"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  link.setAttribute("href", tempCanvas.toDataURL("image/png")); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   link.click(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  // clean up the DOM 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   link.remove(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  if ( targetCanvas !== canvas ) targetCanvas.remove(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if (tempCanvas !== canvas) tempCanvas.remove(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 function rotate(x1, y1, x2, y2, angle) { 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -280,9 +302,9 @@ class App extends React.Component { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       <div className="exportWrapper"> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         <button onClick={() => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           exportAsPNG({ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            background: this.state.exportBackground, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            visibleOnly: this.state.exportVisibleOnly, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            padding: this.state.exportPadding 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            exportBackground: this.state.exportBackground, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            exportVisibleOnly: this.state.exportVisibleOnly, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            exportPadding: this.state.exportPadding 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           }) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         }}>Export to png</button> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         <label> 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -337,7 +359,7 @@ class App extends React.Component { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                   element.isSelected = true 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 return isSelected 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-              })  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+              }) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				               if (selectedElement) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 this.setState({ draggingElement: selectedElement }); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -350,7 +372,7 @@ class App extends React.Component { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				               if (isDraggingElements) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 document.documentElement.style.cursor = "move"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				               } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            }  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             if (this.state.elementType === "text") { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				               const text = prompt("What text do you want?"); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -441,7 +463,7 @@ class App extends React.Component { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				               if (elementType === "selection") { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 if (isDraggingElements) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                   isDraggingElements = false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                }  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 elements.pop() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				               } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 draggingElement.isSelected = true; 
			 |