Implementing User Defined Objects With LEADTOOLS Annotations

Summary

You can easily create your own annotation objects with the LEADTOOLS Annotations framework. This tutorial shows how to create two new annotations objects and how to write the required designer for them to plug these objects into the LEADTOOLS Annotations Automation framework.

  1. Start by creating a new HTML file with the following markup:

    <!DOCTYPE html>  
    <html xmlns="http://www.w3.org/1999/xhtml">  
    	<head>  
    		<title>Implementing User Defined Objects With LEADTOOLS Annotations</title>  
    		<meta http-equiv="X-UA-Compatible" content="IE=9" />  
    		<meta http-equiv="content-type" content="text/html; charset=utf-8" />  
    		<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=0, minimum-scale=1.0, maximum-scale=1.0" />  
    		<style> #imageViewerDiv { border: 1px solid #000000; width: 600px; height: 400px; background-color: #7F7F7F; } </style>  
    	</head>  
    	<body onload="pageLoad()">  
    		<div id="imageViewerDiv"></div>  
    	</body>  
    </html> 

  2. Add script tags, inside the page's head tag, for the LEADTOOLS JavaScript libraries. NOTE: In this example, the LEADTOOLS .js files are located in a lib subfolder:

    <script type="text/javascript" src="lib/Leadtools.js"></script>  
    <script type="text/javascript" src="lib/Leadtools.Controls.js"></script>  
    <script type="text/javascript" src="lib/Leadtools.Annotations.Engine.js"></script>  
    <script type="text/javascript" src="lib/Leadtools.Annotations.Rendering.JavaScript.js"></script>  
    <script type="text/javascript" src="lib/Leadtools.Annotations.Designers.js"></script>  
    <script type="text/javascript" src="lib/Leadtools.Annotations.Automation.js"></script>  
    <script type="text/javascript" src="lib/Leadtools.Demos.js"></script>  
    <script type="text/javascript" src="lib/Leadtools.Demos.Annotations.js"></script> 

  3. The object being created is a simple object, a triangle. This object will have three points for the end points of the triangle and it will use a stroke for the triangle edges and a fill for the interior.

    We need to create a custom annotation object type. Since a triangle is a polygon with only three points, we can derive one from the AnnPolylineObject class. Add the following to your script tag:

    JavaScript
    //////////////////////////////////////////////////////////////////////////////// 
    // AnnTriangleObject 
    AnnTriangleObject = function AnnTriangleObject() { 
    	AnnTriangleObject.initializeBase(this); 
    	this.isClosed = true; // Triangle is a closed figure 
    	this.setId(-99); // Set the object ID 
    } 
    AnnTriangleObject.prototype = { 
    	create: function AnnTriangleObject$create() { 
    		// Define the custom annotation object (the triangle is a polyline with only 3 points) 
    		return new AnnTriangleObject(); 
    	} 
    } 
    AnnTriangleObject.registerClass('AnnTriangleObject', lt.Annotations.Engine.AnnPolylineObject); 

  4. Since there are no existing draw and edit designers that can be used with our AnnTriangleObject class, we need to create our own. First, create the draw designer class, derived from AnnDrawDesigner. Add the following to your script tag, after the AnnTriangleObject code:

    JavaScript
    //////////////////////////////////////////////////////////////////////////////// 
    // AnnTriangleDrawDesigner 
    AnnTriangleDrawDesigner = function AnnTriangleDrawDesigner(automationControl, container, annPolyineObject) { 
    	AnnTriangleDrawDesigner.initializeBase(this, [automationControl, container, annPolyineObject]); 
    } 
    AnnTriangleDrawDesigner.prototype = { 
    	// Override the onPointerDown method and add 3 points for our triangle 
    	onPointerDown: function AnnTriangleDrawDesigner$onPointerDown(sender, e) { 
    		var handled = AnnTriangleDrawDesigner.callBaseMethod(this, 'onPointerDown', [sender, e]); 
    		if (this.targetObject.points.count < 3) 
    			if (e.button === lt.Annotations.Engine.AnnMouseButton.left) { 
    				if (this.startWorking()) 
    					this.targetObject.points.add(e.location); 
    				handled = true; 
    			} 
    		return handled; 
    	}, 
     
    	// Override the onPointerUp method and end the drawing when we have our 3 points 
    	onPointerUp: function AnnTriangleDrawDesigner$onPointerUp(sender, e) { 
    		var handled = AnnTriangleDrawDesigner.callBaseMethod(this, 'onPointerUp', [sender, e]); 
    		handled = true; 
    		if (this.targetObject.points.count >= 3) 
    			this.endWorking(); 
     
    		this.invalidate(lt.LeadRectD.empty); 
    		return handled; 
    	} 
    } 
    AnnTriangleDrawDesigner.registerClass('AnnTriangleDrawDesigner', lt.Annotations.Designers.AnnDrawDesigner); 

  5. Next, create the edit designer class, derived from the AnnPolylineEditDesigner class. Add the following code to your script, after the AnnTriangleDrawDesigner code:

    JavaScript
    //////////////////////////////////////////////////////////////////////////////// 
    // AnnTriangleEditDesigner 
    // We won't actually need to do any customization of this class. 
    AnnTriangleEditDesigner = function AnnTriangleEditDesigner(automationControl, container, annPolylineObject) { 
    	AnnTriangleEditDesigner.initializeBase(this, [automationControl, container, annPolylineObject]); 
    } 
    AnnTriangleEditDesigner.registerClass('AnnTriangleEditDesigner', lt.Annotations.Designers.AnnPolylineEditDesigner); 

  6. Now we can create a custom renderer for our AnnTriangleObject, derived from the AnnPolylineEditDesigner class. Add the following code to your script, after the AnnTriangleDrawDesigner code:

    JavaScript
    //////////////////////////////////////////////////////////////////////////////// 
    // AnnTriangleRenderer 
    AnnTriangleRenderer = function AnnTriangleRenderer() { 
    	AnnTriangleRenderer.initializeBase(this); 
    } 
    AnnTriangleRenderer.prototype = { 
    	// Override the Render method in order to draw the 3 points as the user creates them. 
    	render: function AnnTriangleRenderer$render(mapper, annObject) { 
    		AnnTriangleRenderer.callBaseMethod(this, 'render', [mapper, annObject]); 
    		// If we are finished drawing, allow the base class AnnPolylineObjectRenderer to handle the job 
    		if (annObject.points.count === 3) 
    			return; 
    		var engine = Type.safeCast(this.renderingEngine, lt.Annotations.Rendering.AnnHtml5RenderingEngine); 
    		if (engine != null) { 
    			var context = engine.context; 
    			if (context != null) { 
    				context.save(); 
    				var points = mapper.pointsFromContainerCoordinates(annObject.points.toArray(), annObject.fixedStateOperations); 
    				lt.Annotations.Rendering.AnnHtml5RenderingEngine.setStroke(context, lt.Annotations.Engine.AnnStroke.create(lt.Annotations.Engine.AnnSolidColorBrush.create('green'), lt.LeadLengthD.create(1))); 
    				context.beginPath(); 
    				for (var x = 0; x < points.length; x++) { 
    					var point = points[x]; 
    					if (!point.isEmpty) { 
    						var rect = lt.LeadRectD.create(point.x - 10, point.y - 10, 20, 20); 
    						lt.Annotations.Rendering.AnnHtml5RenderingEngine.drawEllipse(context, rect); 
    					} 
    				} 
    				context.closePath(); 
    				context.stroke(); 
    				context.restore(); 
    			} 
    		} 
    	} 
    } 
    AnnTriangleRenderer.registerClass('AnnTriangleRenderer', lt.Annotations.Rendering.AnnPolylineObjectRenderer); 

  7. The final step is to write the code that glues the LEADTOOLS ImageViewer and the automated annotation objects together.

    JavaScript
    // Shared variable 
    var automation; 
     
    // Create the custom automation object and hook the designers 
    function createTriangleAutomationObject(annObject) { 
    	// Create the automation object 
    	var automationObj = new lt.Annotations.Automation.AnnAutomationObject(); 
    	automationObj.id = annObject.id; 
    	automationObj.name = "Triangle"; 
    	automationObj.drawDesignerType = AnnTriangleDrawDesigner; // Hook the custom draw designer 
    	automationObj.editDesignerType = AnnTriangleEditDesigner; // Hook the custom edit designer 
    	automationObj.runDesignerType = lt.Annotations.Designers.AnnRunDesigner; 
    	 
    	// Get the current rendering engine 
    	var renderingEngine = annAutomation.manager.renderingEngine; 
     
    	// Set up the thumbs 
    	var annTriangleRenderer = new AnnTriangleRenderer(); 
    	var annPolylineRenderer = renderingEngine.renderers[lt.Annotations.Engine.AnnObject.polylineObjectId]; 
    	annTriangleRenderer.locationsThumbStyle = annPolylineRenderer.locationsThumbStyle; 
    	annTriangleRenderer.rotateCenterThumbStyle = annPolylineRenderer.rotateCenterThumbStyle; 
    	annTriangleRenderer.rotateGripperThumbStyle = annPolylineRenderer.rotateGripperThumbStyle; 
     
    	renderingEngine.renderers[annObject.id] = annTriangleRenderer; // Hook the custom renderer 
    	automationObj.objectTemplate = annObject; 
    	return automationObj; 
    } 
     
    function setupTriangleAnnotation() { 
    	// Create the triangle object 
    	var triangle = new AnnTriangleObject(); 
    	triangle.fill = lt.Annotations.Engine.AnnSolidColorBrush.create("blue"); 
    	// Create a user defined automation object 
    	var automationObj = createTriangleAutomationObject(triangle); 
    	annAutomation.manager.objects.add(automationObj); 
    } 
     
    function pageLoad() { 
    	// Create the viewer 
    	var createOptions = new lt.Controls.ImageViewerCreateOptions(document.getElementById('imageViewerDiv')); 
    	var imageViewer = new lt.Controls.ImageViewer(createOptions); 
     
    	// Watch item changed event to set container size and the current object id when the image get loaded 
    	imageViewer.itemChanged.add(imageViewer_ItemChanged); 
     
    	// Set the image URL - load using browser support 
    	imageViewer.imageUrl = "http://demo.leadtools.com/images/jpeg/cactus.jpg"; 
    	 
    	// Fit the image within the viewer 
    	imageViewer.zoom(lt.Controls.ControlSizeMode.fit, 1.0, imageViewer.defaultZoomOrigin); 
     
    	// Create the annotation automation control and attach image viewer to it 
    	var imageViewerAutomationControl = new lt.Demos.Annotations.ImageViewerAutomationControl(); 
    	imageViewerAutomationControl.imageViewer = imageViewer; 
     
    	// Create the automation manager, and default objects 
    	var manager = new lt.Annotations.Automation.AnnAutomationManager(); 
    	manager.createDefaultObjects(); 
     
    	// Create an HTML5 rendering engine and bind it to the automation manager 
    	var renderingEngine = new lt.Annotations.Rendering.AnnHtml5RenderingEngine(); 
    	manager.renderingEngine = renderingEngine; 
     
    	// Create an automation interactive mode instance and bind the automation control to it 
    	var automationInteractiveMode = new lt.Demos.Annotations.AutomationInteractiveMode(); 
    	automationInteractiveMode.automationControl = imageViewerAutomationControl; 
     
    	// Add the automation interactive mode to the viewer interactive modes list and enable it 
    	imageViewer.interactiveModes.beginUpdate(); 
    	imageViewer.interactiveModes.add(automationInteractiveMode); 
    	automationInteractiveMode.isEnabled = true; 
    	imageViewer.interactiveModes.endUpdate(); 
     
    	// Create the annotation automation object 
    	annAutomation = new lt.Annotations.Automation.AnnAutomation(manager, imageViewerAutomationControl); 
     
    	// Setup the triangle annotation 
    	setupTriangleAnnotation(); 
    	 
    	// Activate the annotation automation 
    	annAutomation.active = true; 
    } 
     
    function imageViewer_ItemChanged(sender, e) { 
    	if (e.reason == lt.Controls.ImageViewerItemChangedReason.url) { 
    		// Get loaded image size 
    		var imageSize = sender.activeItem.imageSize; 
     
    		// Set container size with loaded image size 
    		var container = annAutomation.container; 
    		container.size = container.mapper.sizeToContainerCoordinates(lt.LeadSizeD.create(imageSize.width, imageSize.height)); 
     
    		// Set the current object ID to our triangle 
    		annAutomation.manager.currentObjectId = -99; 
    	} 
    } 

  8. Save your .html file and load it in your favorite browser. Then, click/tap three separate points inside the viewer control to draw an AnnTriangleObject.

Help Version 20.0.2018.10.24
Products | Support | Contact Us | Copyright Notices
© 1991-2018 LEAD Technologies, Inc. All Rights Reserved.

LEADTOOLS HTML5 JavaScript