Browse Source

Support for graphs

tentone 6 years ago
parent
commit
9b915f14df

+ 13 - 1
README.md

@@ -7,7 +7,7 @@
  - Built in viewport controls with drag, zoom and move functions.
  - Supports mobile web browsers.
 
-![graph](<https://tentone.github.io/trenette.js/examples/graph.png>)
+![graph](<https://tentone.github.io/trenette.js/readme/example.png>)
 
 
 
@@ -48,6 +48,18 @@ canvas.height = window.innerHeight;
 };
 ```
 
+- The coordinate system used, is the same as if using the canvas API directly -Y is down relative to the origin and +X is left relative to the origin. All objects are positioned using this coordinate system.
+
+![graph](<https://tentone.github.io/trenette.js/readme/grid.png>)
+
+
+
+### Viewport
+
+- The viewport is the object that indicates how the user will view the objects, the viewport can be used to change the position of the elements, zoom in and out, or even rotate the entire canvas.
+- Some object might ignore the viewport transformations by setting the `ignoreViewport` flag to false, this will indicate that renderer to reset the viewport transform just for that object.
+- Its possible to use viewport controller objects that define a default control behavior for the viewport object (mouse interaction).
+
 
 
 ### Custom Objects

+ 160 - 6
build/trenette.js

@@ -134,50 +134,75 @@
 		this.y += v.y;
 	};
 
+	/**
+	 * Add a scalar value to booth vector components.
+	 *
+	 * @param {number} s
+	 */
 	Vector2.prototype.addScalar = function(s)
 	{
 		this.x += s;
 		this.y += s;
 	};
 
+	/** 
+	 * Add two vectors and store the result in this vector.
+	 *
+	 * @param {Vector2} a
+	 * @param {Vector2} b
+	 */
 	Vector2.prototype.addVectors = function(a, b)
 	{
 		this.x = a.x + b.x;
 		this.y = a.y + b.y;
 	};
 
+	/**
+	 * Scale a vector components and add the result to this vector.
+	 *
+	 * @param {Vector2} v
+	 * @param {number} s
+	 */
 	Vector2.prototype.addScaledVector = function(v, s)
 	{
 		this.x += v.x * s;
 		this.y += v.y * s;
 	};
 
-
 	/**
 	 * Subtract the content of another vector to this one.
 	 *
 	 * @param {Vector2} v
 	 */
-
 	Vector2.prototype.sub = function(v)
 	{
 		this.x -= v.x;
 		this.y -= v.y;
 	};
 
+	/**
+	 * Subtract a scalar value to booth vector components.
+	 *
+	 * @param {number} s
+	 */
 	Vector2.prototype.subScalar = function(s)
 	{
 		this.x -= s;
 		this.y -= s;
 	};
 
+	/** 
+	 * Subtract two vectors and store the result in this vector.
+	 *
+	 * @param {Vector2} a
+	 * @param {Vector2} b
+	 */
 	Vector2.prototype.subVectors = function(a, b)
 	{
 		this.x = a.x - b.x;
 		this.y = a.y - b.y;
 	};
 
-
 	/**
 	 * Multiply the content of another vector to this one.
 	 *
@@ -189,6 +214,11 @@
 		this.y *= v.y;
 	};
 
+	/**
+	 * Multiply a scalar value by booth vector components.
+	 *
+	 * @param {number} s
+	 */
 	Vector2.prototype.multiplyScalar = function(scalar)
 	{
 		this.x *= scalar;
@@ -207,6 +237,11 @@
 		this.y /= v.y;
 	};
 
+	/**
+	 * Divide a scalar value by booth vector components.
+	 *
+	 * @param {number} s
+	 */
 	Vector2.prototype.divideScalar = function(scalar)
 	{
 		return this.multiplyScalar(1 / scalar);
@@ -379,6 +414,12 @@
 		return ((v.x === this.x) && (v.y === this.y));
 	};
 
+	/**
+	 * Set vector value from array with a offset.
+	 *
+	 * @param {array} array
+	 * @param {number} [offset]
+	 */
 	Vector2.prototype.fromArray = function(array, offset)
 	{
 		if(offset === undefined) offset = 0;
@@ -387,6 +428,12 @@
 		this.y = array[offset + 1];
 	};
 
+	/**
+	 * Convert this vector to an array.
+	 *
+	 * @param {array} array
+	 * @param {number} [offset]
+	 */
 	Vector2.prototype.toArray = function(array, offset)
 	{
 		if(array === undefined) array = [];
@@ -977,7 +1024,11 @@
 	/**
 	 * Callback method while the object is being dragged across the screen.
 	 *
-	 * Receives (pointer, viewport, delta) as arguments. Delta is the movement of the pointer already translated into local object coordinates.
+	 * By default is adds the delta value to the object position (making it follow the mouse movement).
+	 *
+	 * Delta is the movement of the pointer already translated into local object coordinates.
+	 *
+	 * Receives (pointer, viewport, delta) as arguments.
 	 */
 	Object2D.prototype.onPointerDrag = function(pointer, viewport, delta)
 	{
@@ -2214,6 +2265,11 @@
 		 */
 		this.strokeStyle = "#000000";
 
+		/**
+		 * Line width.
+		 */
+		this.lineWidth = 1;
+
 		/**
 		 * Background color of the circle.
 		 */
@@ -2245,7 +2301,7 @@
 		context.fillStyle = this.fillStyle;
 		context.fill();
 
-		context.lineWidth = 1;
+		context.lineWidth = this.lineWidth;
 		context.strokeStyle = this.strokeStyle;
 		context.stroke();
 	};
@@ -2377,6 +2433,11 @@
 		 */
 		this.strokeStyle = "#000000";
 
+		/**
+		 * Line width.
+		 */
+		this.lineWidth = 1;
+
 		/**
 		 * Background color of the box.
 		 */
@@ -2408,7 +2469,7 @@
 		context.fillStyle = this.fillStyle;
 		context.fillRect(this.box.min.x, this.box.min.y, width, height);
 
-		context.lineWidth = 1;
+		context.lineWidth = this.lineWidth;
 		context.strokeStyle = this.strokeStyle;
 		context.strokeRect(this.box.min.x, this.box.min.y, width, height);
 	};
@@ -2705,12 +2766,105 @@
 		}
 	};
 
+	/**
+	 * Graph object is used to draw simple graph data into the canvas.
+	 *
+	 * Graph data is composed of X, Y values.
+	 *
+	 * @class
+	 */
+	function Graph()
+	{
+		Object2D.call(this);
+
+		/**
+		 * Graph object containing the size of the object.
+		 */
+		this.box = new Box2(new Vector2(-50, -35), new Vector2(50, 35));
+
+		/**
+		 * Color of the box border line.
+		 */
+		this.strokeStyle = "rgb(0, 153, 255)";
+
+		/**
+		 * Line width.
+		 */
+		this.lineWidth = 1;
+
+		/**
+		 * Background color of the box.
+		 */
+		this.fillStyle = "rgba(0, 153, 255, 0.3)";
+
+		/**
+		 * Minimum value of the graph.
+		 */
+		this.min = 0;
+
+		/**
+		 * Maximum value of the graph.
+		 */
+		this.max = 10;
+
+		/**
+		 * Data to be presented in the graph.
+		 *
+		 * The array should store numeric values.
+		 */
+		this.data = [];
+	}
+
+	Graph.prototype = Object.create(Object2D.prototype);
+
+	Graph.prototype.isInside = function(point)
+	{
+		return this.box.containsPoint(point);
+	};
+
+	Graph.prototype.draw = function(context, viewport, canvas)
+	{
+		if(this.data.length === 0)
+		{
+			return;
+		}
+		
+		var width = this.box.max.x - this.box.min.x;
+		var height = this.box.max.y - this.box.min.y;
+
+		context.lineWidth = this.lineWidth;
+		context.strokeStyle = this.strokeStyle;
+		context.beginPath();
+			
+		var step = width / (this.data.length - 1);
+		var gamma = this.max - this.min;
+
+		context.moveTo(this.box.min.x, this.box.max.y - ((this.data[0] - this.min) / gamma) * height);
+		
+		for(var i = 1, s = step; i < this.data.length; s += step, i++)
+		{
+			context.lineTo(this.box.min.x + s, this.box.max.y - ((this.data[i] - this.min) / gamma) * height);
+		}
+
+		context.stroke();
+
+		if(this.fillStyle !== null)
+		{
+			context.fillStyle = this.fillStyle;
+
+			context.lineTo(this.box.max.x, this.box.max.y);
+			context.lineTo(this.box.min.x, this.box.max.y);
+			context.fill();
+		}
+	};
+
 	exports.Box = Box;
 	exports.Box2 = Box2;
 	exports.BoxMask = BoxMask;
 	exports.Circle = Circle;
 	exports.DOM = DOM;
 	exports.EventManager = EventManager;
+	exports.Graph = Graph;
 	exports.Helpers = Helpers;
 	exports.Image = Image;
 	exports.Key = Key;

File diff suppressed because it is too large
+ 0 - 0
build/trenette.min.js


+ 160 - 7
build/trenette.module.js

@@ -128,50 +128,75 @@ Vector2.prototype.add = function(v)
 	this.y += v.y;
 };
 
+/**
+ * Add a scalar value to booth vector components.
+ *
+ * @param {number} s
+ */
 Vector2.prototype.addScalar = function(s)
 {
 	this.x += s;
 	this.y += s;
 };
 
+/** 
+ * Add two vectors and store the result in this vector.
+ *
+ * @param {Vector2} a
+ * @param {Vector2} b
+ */
 Vector2.prototype.addVectors = function(a, b)
 {
 	this.x = a.x + b.x;
 	this.y = a.y + b.y;
 };
 
+/**
+ * Scale a vector components and add the result to this vector.
+ *
+ * @param {Vector2} v
+ * @param {number} s
+ */
 Vector2.prototype.addScaledVector = function(v, s)
 {
 	this.x += v.x * s;
 	this.y += v.y * s;
 };
 
-
 /**
  * Subtract the content of another vector to this one.
  *
  * @param {Vector2} v
  */
-
 Vector2.prototype.sub = function(v)
 {
 	this.x -= v.x;
 	this.y -= v.y;
 };
 
+/**
+ * Subtract a scalar value to booth vector components.
+ *
+ * @param {number} s
+ */
 Vector2.prototype.subScalar = function(s)
 {
 	this.x -= s;
 	this.y -= s;
 };
 
+/** 
+ * Subtract two vectors and store the result in this vector.
+ *
+ * @param {Vector2} a
+ * @param {Vector2} b
+ */
 Vector2.prototype.subVectors = function(a, b)
 {
 	this.x = a.x - b.x;
 	this.y = a.y - b.y;
 };
 
-
 /**
  * Multiply the content of another vector to this one.
  *
@@ -183,6 +208,11 @@ Vector2.prototype.multiply = function(v)
 	this.y *= v.y;
 };
 
+/**
+ * Multiply a scalar value by booth vector components.
+ *
+ * @param {number} s
+ */
 Vector2.prototype.multiplyScalar = function(scalar)
 {
 	this.x *= scalar;
@@ -201,6 +231,11 @@ Vector2.prototype.divide = function(v)
 	this.y /= v.y;
 };
 
+/**
+ * Divide a scalar value by booth vector components.
+ *
+ * @param {number} s
+ */
 Vector2.prototype.divideScalar = function(scalar)
 {
 	return this.multiplyScalar(1 / scalar);
@@ -373,6 +408,12 @@ Vector2.prototype.equals = function(v)
 	return ((v.x === this.x) && (v.y === this.y));
 };
 
+/**
+ * Set vector value from array with a offset.
+ *
+ * @param {array} array
+ * @param {number} [offset]
+ */
 Vector2.prototype.fromArray = function(array, offset)
 {
 	if(offset === undefined) offset = 0;
@@ -381,6 +422,12 @@ Vector2.prototype.fromArray = function(array, offset)
 	this.y = array[offset + 1];
 };
 
+/**
+ * Convert this vector to an array.
+ *
+ * @param {array} array
+ * @param {number} [offset]
+ */
 Vector2.prototype.toArray = function(array, offset)
 {
 	if(array === undefined) array = [];
@@ -971,7 +1018,11 @@ Object2D.prototype.onPointerOver = null;
 /**
  * Callback method while the object is being dragged across the screen.
  *
- * Receives (pointer, viewport, delta) as arguments. Delta is the movement of the pointer already translated into local object coordinates.
+ * By default is adds the delta value to the object position (making it follow the mouse movement).
+ *
+ * Delta is the movement of the pointer already translated into local object coordinates.
+ *
+ * Receives (pointer, viewport, delta) as arguments.
  */
 Object2D.prototype.onPointerDrag = function(pointer, viewport, delta)
 {
@@ -2208,6 +2259,11 @@ function Circle()
 	 */
 	this.strokeStyle = "#000000";
 
+	/**
+	 * Line width.
+	 */
+	this.lineWidth = 1;
+
 	/**
 	 * Background color of the circle.
 	 */
@@ -2239,7 +2295,7 @@ Circle.prototype.draw = function(context, viewport, canvas)
 	context.fillStyle = this.fillStyle;
 	context.fill();
 
-	context.lineWidth = 1;
+	context.lineWidth = this.lineWidth;
 	context.strokeStyle = this.strokeStyle;
 	context.stroke();
 };
@@ -2371,6 +2427,11 @@ function Box()
 	 */
 	this.strokeStyle = "#000000";
 
+	/**
+	 * Line width.
+	 */
+	this.lineWidth = 1;
+
 	/**
 	 * Background color of the box.
 	 */
@@ -2402,7 +2463,7 @@ Box.prototype.draw = function(context, viewport, canvas)
 	context.fillStyle = this.fillStyle;
 	context.fillRect(this.box.min.x, this.box.min.y, width, height);
 
-	context.lineWidth = 1;
+	context.lineWidth = this.lineWidth;
 	context.strokeStyle = this.strokeStyle;
 	context.strokeRect(this.box.min.x, this.box.min.y, width, height);
 };
@@ -2699,4 +2760,96 @@ Pattern.prototype.draw = function(context, viewport, canvas)
 	}
 };
 
-export { Box, Box2, BoxMask, Circle, DOM, EventManager, Helpers, Image, Key, Line, Mask, Matrix, Object2D, Pattern, Pointer, Renderer, Text, UUID, Vector2, Viewport };
+/**
+ * Graph object is used to draw simple graph data into the canvas.
+ *
+ * Graph data is composed of X, Y values.
+ *
+ * @class
+ */
+function Graph()
+{
+	Object2D.call(this);
+
+	/**
+	 * Graph object containing the size of the object.
+	 */
+	this.box = new Box2(new Vector2(-50, -35), new Vector2(50, 35));
+
+	/**
+	 * Color of the box border line.
+	 */
+	this.strokeStyle = "rgb(0, 153, 255)";
+
+	/**
+	 * Line width.
+	 */
+	this.lineWidth = 1;
+
+	/**
+	 * Background color of the box.
+	 */
+	this.fillStyle = "rgba(0, 153, 255, 0.3)";
+
+	/**
+	 * Minimum value of the graph.
+	 */
+	this.min = 0;
+
+	/**
+	 * Maximum value of the graph.
+	 */
+	this.max = 10;
+
+	/**
+	 * Data to be presented in the graph.
+	 *
+	 * The array should store numeric values.
+	 */
+	this.data = [];
+}
+
+Graph.prototype = Object.create(Object2D.prototype);
+
+Graph.prototype.isInside = function(point)
+{
+	return this.box.containsPoint(point);
+};
+
+Graph.prototype.draw = function(context, viewport, canvas)
+{
+	if(this.data.length === 0)
+	{
+		return;
+	}
+	
+	var width = this.box.max.x - this.box.min.x;
+	var height = this.box.max.y - this.box.min.y;
+
+	context.lineWidth = this.lineWidth;
+	context.strokeStyle = this.strokeStyle;
+	context.beginPath();
+		
+	var step = width / (this.data.length - 1);
+	var gamma = this.max - this.min;
+
+	context.moveTo(this.box.min.x, this.box.max.y - ((this.data[0] - this.min) / gamma) * height);
+	
+	for(var i = 1, s = step; i < this.data.length; s += step, i++)
+	{
+		context.lineTo(this.box.min.x + s, this.box.max.y - ((this.data[i] - this.min) / gamma) * height);
+	}
+
+	context.stroke();
+
+	if(this.fillStyle !== null)
+	{
+		context.fillStyle = this.fillStyle;
+
+		context.lineTo(this.box.max.x, this.box.max.y);
+		context.lineTo(this.box.min.x, this.box.max.y);
+		context.fill();
+	}
+};
+
+export { Box, Box2, BoxMask, Circle, DOM, EventManager, Graph, Helpers, Image, Key, Line, Mask, Matrix, Object2D, Pattern, Pointer, Renderer, Text, UUID, Vector2, Viewport };

+ 24 - 0
examples/diagram.html

@@ -120,6 +120,29 @@
 		image.draggable = true;
 		group.add(image);
 
+		var graph = new Trenette.Graph();
+		graph.box.min.set(-500, -50);
+		graph.box.max.set(500, 50);
+		graph.position.set(-300, -400);
+		graph.layer = 5;
+		graph.draggable = true;
+		group.add(graph);
+
+		Trenette.Helpers.boxResizeTool(graph);
+		for(var i = 0; i < 300; i++)
+		{
+			graph.data.push(Math.random() * 9 + 1);
+		}
+
+		function cycleGraph()
+		{
+			graph.data.push(graph.data.shift());
+			
+			requestAnimationFrame(cycleGraph);
+		}
+		cycleGraph();
+
+
 		// Image object
 		var background = new Trenette.Image("images/hexagon.jpg");
 		background.position.set(-300, -400);
@@ -130,6 +153,7 @@
 		// Box
 		var boxA = new Trenette.Box();
 		boxA.draggable = true;
+		boxA.position.set(-50, -100);
 		group.add(boxA);
 		Trenette.Helpers.boxResizeTool(boxA);
 

+ 0 - 0
examples/graph.png → readme/example.png


BIN
readme/graph.png


BIN
readme/grid.png


+ 1 - 0
source/Trenette.js

@@ -22,5 +22,6 @@ export {Text} from "./objects/Text.js";
 export {Image} from "./objects/Image.js";
 export {DOM} from "./objects/DOM.js";
 export {Pattern} from "./objects/Pattern.js";
+export {Graph} from "./objects/Graph.js";
 
 export {Helpers} from "./utils/Helpers.js";

+ 6 - 3
source/objects/Box.js

@@ -15,8 +15,6 @@ function Box()
 {
 	Object2D.call(this);
 
-	var self = this;
-
 	/**
 	 * Box object containing the size of the object.
 	 */
@@ -27,6 +25,11 @@ function Box()
 	 */
 	this.strokeStyle = "#000000";
 
+	/**
+	 * Line width.
+	 */
+	this.lineWidth = 1;
+
 	/**
 	 * Background color of the box.
 	 */
@@ -58,7 +61,7 @@ Box.prototype.draw = function(context, viewport, canvas)
 	context.fillStyle = this.fillStyle;
 	context.fillRect(this.box.min.x, this.box.min.y, width, height);
 
-	context.lineWidth = 1;
+	context.lineWidth = this.lineWidth;
 	context.strokeStyle = this.strokeStyle;
 	context.strokeRect(this.box.min.x, this.box.min.y, width, height);
 };

+ 6 - 1
source/objects/Circle.js

@@ -22,6 +22,11 @@ function Circle()
 	 */
 	this.strokeStyle = "#000000";
 
+	/**
+	 * Line width.
+	 */
+	this.lineWidth = 1;
+
 	/**
 	 * Background color of the circle.
 	 */
@@ -53,7 +58,7 @@ Circle.prototype.draw = function(context, viewport, canvas)
 	context.fillStyle = this.fillStyle;
 	context.fill();
 
-	context.lineWidth = 1;
+	context.lineWidth = this.lineWidth;
 	context.strokeStyle = this.strokeStyle;
 	context.stroke();
 };

+ 101 - 0
source/objects/Graph.js

@@ -0,0 +1,101 @@
+"use strict";
+
+import {Object2D} from "../Object2D.js";
+import {Vector2} from "../math/Vector2.js";
+import {Box2} from "../math/Box2.js";
+import {Helpers} from "../utils/Helpers.js";
+import {Circle} from "./Circle.js";
+
+/**
+ * Graph object is used to draw simple graph data into the canvas.
+ *
+ * Graph data is composed of X, Y values.
+ *
+ * @class
+ */
+function Graph()
+{
+	Object2D.call(this);
+
+	/**
+	 * Graph object containing the size of the object.
+	 */
+	this.box = new Box2(new Vector2(-50, -35), new Vector2(50, 35));
+
+	/**
+	 * Color of the box border line.
+	 */
+	this.strokeStyle = "rgb(0, 153, 255)";
+
+	/**
+	 * Line width.
+	 */
+	this.lineWidth = 1;
+
+	/**
+	 * Background color of the box.
+	 */
+	this.fillStyle = "rgba(0, 153, 255, 0.3)";
+
+	/**
+	 * Minimum value of the graph.
+	 */
+	this.min = 0;
+
+	/**
+	 * Maximum value of the graph.
+	 */
+	this.max = 10;
+
+	/**
+	 * Data to be presented in the graph.
+	 *
+	 * The array should store numeric values.
+	 */
+	this.data = [];
+}
+
+Graph.prototype = Object.create(Object2D.prototype);
+
+Graph.prototype.isInside = function(point)
+{
+	return this.box.containsPoint(point);
+};
+
+Graph.prototype.draw = function(context, viewport, canvas)
+{
+	if(this.data.length === 0)
+	{
+		return;
+	}
+	
+	var width = this.box.max.x - this.box.min.x;
+	var height = this.box.max.y - this.box.min.y;
+
+	context.lineWidth = this.lineWidth;
+	context.strokeStyle = this.strokeStyle;
+	context.beginPath();
+		
+	var step = width / (this.data.length - 1);
+	var gamma = this.max - this.min;
+
+	context.moveTo(this.box.min.x, this.box.max.y - ((this.data[0] - this.min) / gamma) * height);
+	
+	for(var i = 1, s = step; i < this.data.length; s += step, i++)
+	{
+		context.lineTo(this.box.min.x + s, this.box.max.y - ((this.data[i] - this.min) / gamma) * height);
+	}
+
+	context.stroke();
+
+	if(this.fillStyle !== null)
+	{
+		context.fillStyle = this.fillStyle;
+
+		context.lineTo(this.box.max.x, this.box.max.y);
+		context.lineTo(this.box.min.x, this.box.max.y);
+		context.fill();
+	}
+};
+
+export {Graph};

Some files were not shown because too many files changed in this diff