implemented dashed and dotted line styling for Kinetic.Line based on method written by Phrogz

This commit is contained in:
Eric Rowell 2012-05-08 19:11:19 -07:00
parent f2976e7dd1
commit 40ebb21033
4 changed files with 212 additions and 7 deletions

74
dist/kinetic-core.js vendored
View File

@ -3,7 +3,7 @@
* http://www.kineticjs.com/
* Copyright 2012, Eric Rowell
* Licensed under the MIT or GPL Version 2 licenses.
* Date: May 03 2012
* Date: May 08 2012
*
* Copyright (C) 2011 - 2012 by Eric Rowell
*
@ -3496,17 +3496,32 @@ Kinetic.GlobalObject.extend(Kinetic.Text, Kinetic.Shape);
Kinetic.Line = function(config) {
this.setDefaultAttrs({
points: {},
lineCap: 'butt'
lineCap: 'butt',
dashArray: []
});
this.shapeType = "Line";
config.drawFunc = function() {
var context = this.getContext();
var lastPos = {};
context.beginPath();
this.applyLineJoin();
context.moveTo(this.attrs.points[0].x, this.attrs.points[0].y);
for(var n = 1; n < this.attrs.points.length; n++) {
context.lineTo(this.attrs.points[n].x, this.attrs.points[n].y);
var x = this.attrs.points[n].x;
var y = this.attrs.points[n].y;
if(this.attrs.dashArray.length > 0) {
// draw dashed line
var lastX = this.attrs.points[n - 1].x;
var lastY = this.attrs.points[n - 1].y;
this._dashedLine(lastX, lastY, x, y, this.attrs.dashArray);
}
else {
// draw normal line
context.lineTo(x, y);
}
}
if(!!this.attrs.lineCap) {
@ -3546,6 +3561,59 @@ Kinetic.Line.prototype = {
*/
getLineCap: function() {
return this.attrs.lineCap;
},
/**
* set dash array.
* @param {Array} dashArray
* examples:<br>
* [10, 5] dashes are 10px long and 5 pixels apart
* [10, 20, 0, 20] if using a round lineCap, the line will
* be made up of alternating dashed lines that are 10px long
* and 20px apart, and dots that have a radius of 5 and are 20px
* apart
*/
setDashArray: function(dashArray) {
this.attrs.dashArray = dashArray;
},
/**
* get dash array
*/
getDashArray: function() {
return this.attrs.dashArray;
},
/**
* draw dashed line. Written by Phrogz
*/
_dashedLine: function(x, y, x2, y2, dashArray) {
var context = this.getContext();
var dashCount = dashArray.length;
var dx = (x2 - x), dy = (y2 - y);
var xSlope = (Math.abs(dx) > Math.abs(dy));
var slope = (xSlope) ? dy / dx : dx / dy;
var distRemaining = Math.sqrt(dx * dx + dy * dy);
var dashIndex = 0, draw = true;
while(distRemaining >= 0.1 && dashIndex < 10000) {
var dashLength = dashArray[dashIndex++ % dashCount];
if(dashLength === 0) {
dashLength = 0.001;
}
if(dashLength > distRemaining) {
dashLength = distRemaining;
}
var step = Math.sqrt(dashLength * dashLength / (1 + slope * slope));
if(xSlope) {
x += step;
y += slope * step;
}
else {
x += slope * step;
y += step;
}
context[draw ? 'lineTo' : 'moveTo'](x, y);
distRemaining -= dashLength;
draw = !draw;
}
}
};

File diff suppressed because one or more lines are too long

View File

@ -10,17 +10,32 @@
Kinetic.Line = function(config) {
this.setDefaultAttrs({
points: {},
lineCap: 'butt'
lineCap: 'butt',
dashArray: []
});
this.shapeType = "Line";
config.drawFunc = function() {
var context = this.getContext();
var lastPos = {};
context.beginPath();
this.applyLineJoin();
context.moveTo(this.attrs.points[0].x, this.attrs.points[0].y);
for(var n = 1; n < this.attrs.points.length; n++) {
context.lineTo(this.attrs.points[n].x, this.attrs.points[n].y);
var x = this.attrs.points[n].x;
var y = this.attrs.points[n].y;
if(this.attrs.dashArray.length > 0) {
// draw dashed line
var lastX = this.attrs.points[n - 1].x;
var lastY = this.attrs.points[n - 1].y;
this._dashedLine(lastX, lastY, x, y, this.attrs.dashArray);
}
else {
// draw normal line
context.lineTo(x, y);
}
}
if(!!this.attrs.lineCap) {
@ -60,6 +75,59 @@ Kinetic.Line.prototype = {
*/
getLineCap: function() {
return this.attrs.lineCap;
},
/**
* set dash array.
* @param {Array} dashArray
* examples:<br>
* [10, 5] dashes are 10px long and 5 pixels apart
* [10, 20, 0, 20] if using a round lineCap, the line will
* be made up of alternating dashed lines that are 10px long
* and 20px apart, and dots that have a radius of 5 and are 20px
* apart
*/
setDashArray: function(dashArray) {
this.attrs.dashArray = dashArray;
},
/**
* get dash array
*/
getDashArray: function() {
return this.attrs.dashArray;
},
/**
* draw dashed line. Written by Phrogz
*/
_dashedLine: function(x, y, x2, y2, dashArray) {
var context = this.getContext();
var dashCount = dashArray.length;
var dx = (x2 - x), dy = (y2 - y);
var xSlope = (Math.abs(dx) > Math.abs(dy));
var slope = (xSlope) ? dy / dx : dx / dy;
var distRemaining = Math.sqrt(dx * dx + dy * dy);
var dashIndex = 0, draw = true;
while(distRemaining >= 0.1 && dashIndex < 10000) {
var dashLength = dashArray[dashIndex++ % dashCount];
if(dashLength === 0) {
dashLength = 0.001;
}
if(dashLength > distRemaining) {
dashLength = distRemaining;
}
var step = Math.sqrt(dashLength * dashLength / (1 + slope * slope));
if(xSlope) {
x += step;
y += slope * step;
}
else {
x += slope * step;
y += step;
}
context[draw ? 'lineTo' : 'moveTo'](x, y);
distRemaining -= dashLength;
draw = !draw;
}
}
};

View File

@ -103,8 +103,8 @@ Test.prototype.tests = {
name: 'myCircle',
draggable: true,
scale: {
x: 0.5,
y: 0.5
x: 0.5,
y: 0.5
}
});
@ -1212,6 +1212,46 @@ Test.prototype.tests = {
layer.add(line);
stage.add(layer);
},
'SHAPES - add dashed line': function(containerId) {
var stage = new Kinetic.Stage({
container: containerId,
width: 578,
height: 200
});
var layer = new Kinetic.Layer();
var points = [{
x: 73,
y: 160
}, {
x: 340,
y: 23
}, {
x: 500,
y: 109
}, {
x: 500,
y: 180
}];
var line = new Kinetic.Line({
points: points,
stroke: 'blue',
strokeWidth: 5,
lineCap: 'round',
lineJoin: 'round',
draggable: true,
dashArray: [30, 10, 0, 10, 10, 20]
});
layer.add(line);
stage.add(layer);
test(line.getDashArray().length === 6, 'dashArray should have 6 elements');
line.setDashArray([10, 10]);
test(line.getDashArray().length === 2, 'dashArray should have 2 elements');
},
'SHAPES - add regular polygon triangle': function(containerId) {
var stage = new Kinetic.Stage({