diff --git a/Gruntfile.js b/Gruntfile.js
index ac58660b..771b6f0b 100644
--- a/Gruntfile.js
+++ b/Gruntfile.js
@@ -34,6 +34,7 @@ module.exports = function(grunt) {
'src/plugins/RegularPolygon.js',
'src/plugins/Star.js',
'src/plugins/Label.js',
+ 'src/plugins/Crosshair.js',
// filters
'src/filters/FilterWrapper.js',
diff --git a/src/plugins/Crosshair.js b/src/plugins/Crosshair.js
new file mode 100644
index 00000000..78afbc1f
--- /dev/null
+++ b/src/plugins/Crosshair.js
@@ -0,0 +1,140 @@
+(function() {
+ /**
+ * Crosshair constructor
+ * @constructor
+ * @augments Kinetic.Shape
+ * @param {Object} config
+ * @param {Object} config.innerGap
+ * @param {Number} config.innerGapX
+ * @param {Number} config.innerGapY
+ * @param {Boolean} config.encircled
+ * @@shapeParams
+ * @@nodeParams
+ * @example
+ * var Crosshair = new Kinetic.Crosshair({
+ * width: 50,
+ * height: 70,
+ * fill: 'red',
+ * stroke: 'black',
+ * strokeWidth: 5,
+ * innerGap: {x: 5, y: 10},
+ * encircled: true
+ * });
+ */
+ Kinetic.Crosshair = function(config) {
+ this.___init(config);
+ };
+
+ Kinetic.Crosshair.prototype = {
+ ___init: function(config) {
+ // call super constructor
+ Kinetic.Shape.call(this, config);
+ this.className = 'Crosshair';
+ this.setDrawFunc(this._drawFunc);
+ },
+ _drawFunc: function(context) {
+ var width_over_2 = this.getWidth() / 2;
+ var height_over_2 = this.getHeight() / 2;
+
+ context.beginPath();
+ context.moveTo(this.getInnerGapX(), 0);
+ context.lineTo(width_over_2, 0);
+ context.moveTo(-this.getInnerGapX(), 0);
+ context.lineTo(-width_over_2, 0);
+ context.moveTo(0, this.getInnerGapY());
+ context.lineTo(0, height_over_2);
+ context.moveTo(0, -this.getInnerGapY());
+ context.lineTo(0, -height_over_2);
+
+ if (this.getEncircled()) {
+ var width_two_thirds = this.getWidth() * 2 / 3;
+ context.moveTo(0, -height_over_2);
+ context.bezierCurveTo(width_two_thirds, -height_over_2, width_two_thirds, height_over_2, 0, height_over_2);
+ context.bezierCurveTo(-width_two_thirds, height_over_2, -width_two_thirds, -height_over_2, 0, -height_over_2);
+ }
+
+ context.closePath();
+ context.fillStrokeShape(this);
+ }
+ };
+ Kinetic.Util.extend(Kinetic.Crosshair, Kinetic.Shape);
+
+ // add getters setters
+ Kinetic.Factory.addPointGetterSetter(Kinetic.Crosshair, 'innerGap', 0);
+
+ /**
+ * set innerGap. The innerGap is the distance between the center and the start of the crosshair line.
+ * @name setInnerGap
+ * @method
+ * @memberof Kinetic.Crosshair.prototype
+ * @param {Number} x
+ * @param {Number} y
+ * @returns {Kinetic.Crosshair}
+ * @example
+ * // set x and y
+ * shape.setInnerGap({
+ * x: 5
+ * y: 5
+ * });
+ */
+
+ /**
+ * get innerGap
+ * @name getInnerGap
+ * @method
+ * @memberof Kinetic.Crosshair.prototype
+ * @returns {Object}
+ */
+
+ /**
+ * set innerGap x
+ * @name setInnerGapX
+ * @method
+ * @memberof Kinetic.Crosshair.prototype
+ * @param {Number} x
+ * @returns {Kinetic.Crosshair}
+ */
+
+ /**
+ * get innerGap x
+ * @name getInnerGapX
+ * @method
+ * @memberof Kinetic.Crosshair.prototype
+ * @returns {Number}
+ */
+
+ /**
+ * set innerGap y
+ * @name setInnerGapY
+ * @method
+ * @memberof Kinetic.Crosshair.prototype
+ * @param {Number} y
+ * @returns {Kinetic.Crosshair}
+ */
+
+ /**
+ * get innerGap y
+ * @name getInnerGapY
+ * @method
+ * @memberof Kinetic.Crosshair.prototype
+ * @returns {Number}
+ */
+
+ Kinetic.Factory.addGetterSetter(Kinetic.Crosshair, 'encircled', false);
+
+ /**
+ * set encircled
+ * @name setEncircled
+ * @method
+ * @memberof Kinetic.Crosshair.prototype
+ * @param {Boolean}
+ */
+
+ /**
+ * get encircled
+ * @name getEncircled
+ * @method
+ * @memberof Kinetic.Crosshair.prototype
+ * @returns {Boolean}
+ */
+})();
diff --git a/test/runner.html b/test/runner.html
index 8ce6f4d6..80b42e3e 100644
--- a/test/runner.html
+++ b/test/runner.html
@@ -77,6 +77,7 @@