diff options
Diffstat (limited to 'src/patharray.js')
-rw-r--r-- | src/patharray.js | 188 |
1 files changed, 88 insertions, 100 deletions
diff --git a/src/patharray.js b/src/patharray.js index 697bc68..d9ffecd 100644 --- a/src/patharray.js +++ b/src/patharray.js @@ -1,49 +1,51 @@ +/* globals arrayToString, pathRegReplace */ + var pathHandlers = { - M: function(c, p, p0) { + M: function (c, p, p0) { p.x = p0.x = c[0] p.y = p0.y = c[1] return ['M', p.x, p.y] }, - L: function(c, p) { + L: function (c, p) { p.x = c[0] p.y = c[1] return ['L', c[0], c[1]] }, - H: function(c, p) { + H: function (c, p) { p.x = c[0] return ['H', c[0]] }, - V: function(c, p) { + V: function (c, p) { p.y = c[0] return ['V', c[0]] }, - C: function(c, p) { + C: function (c, p) { p.x = c[4] p.y = c[5] return ['C', c[0], c[1], c[2], c[3], c[4], c[5]] }, - S: function(c, p) { + S: function (c, p) { p.x = c[2] p.y = c[3] return ['S', c[0], c[1], c[2], c[3]] }, - Q: function(c, p) { + Q: function (c, p) { p.x = c[2] p.y = c[3] return ['Q', c[0], c[1], c[2], c[3]] }, - T: function(c, p) { + T: function (c, p) { p.x = c[0] p.y = c[1] return ['T', c[0], c[1]] }, - Z: function(c, p, p0) { + Z: function (c, p, p0) { p.x = p0.x p.y = p0.y return ['Z'] }, - A: function(c, p) { + A: function (c, p) { p.x = c[5] p.y = c[6] return ['A', c[0], c[1], c[2], c[3], c[4], c[5], c[6]] @@ -52,19 +54,19 @@ var pathHandlers = { var mlhvqtcsaz = 'mlhvqtcsaz'.split('') -for(var i = 0, il = mlhvqtcsaz.length; i < il; ++i){ - pathHandlers[mlhvqtcsaz[i]] = (function(i){ - return function(c, p, p0) { - if(i == 'H') c[0] = c[0] + p.x - else if(i == 'V') c[0] = c[0] + p.y - else if(i == 'A'){ - c[5] = c[5] + p.x, +for (var i = 0, il = mlhvqtcsaz.length; i < il; ++i) { + pathHandlers[mlhvqtcsaz[i]] = (function (i) { + return function (c, p, p0) { + if (i === 'H') c[0] = c[0] + p.x + else if (i === 'V') c[0] = c[0] + p.y + else if (i === 'A') { + c[5] = c[5] + p.x c[6] = c[6] + p.y - } - else - for(var j = 0, jl = c.length; j < jl; ++j) { - c[j] = c[j] + (j%2 ? p.y : p.x) + } else { + for (var j = 0, jl = c.length; j < jl; ++j) { + c[j] = c[j] + (j % 2 ? p.y : p.x) } + } return pathHandlers[i](c, p, p0) } @@ -72,21 +74,21 @@ for(var i = 0, il = mlhvqtcsaz.length; i < il; ++i){ } // Path points array -SVG.PathArray = function(array, fallback) { +SVG.PathArray = function (array, fallback) { SVG.Array.call(this, array, fallback || [['M', 0, 0]]) } // Inherit from SVG.Array -SVG.PathArray.prototype = new SVG.Array +SVG.PathArray.prototype = new SVG.Array() SVG.PathArray.prototype.constructor = SVG.PathArray SVG.extend(SVG.PathArray, { // Convert array to string - toString: function() { + toString: function () { return arrayToString(this.value) - } + }, // Move path string -, move: function(x, y) { + move: function (x, y) { // get bounding box of current situation var box = this.bbox() @@ -99,121 +101,113 @@ SVG.extend(SVG.PathArray, { for (var l, i = this.value.length - 1; i >= 0; i--) { l = this.value[i][0] - if (l == 'M' || l == 'L' || l == 'T') { + if (l === 'M' || l === 'L' || l === 'T') { this.value[i][1] += x this.value[i][2] += y - - } else if (l == 'H') { + } else if (l === 'H') { this.value[i][1] += x - - } else if (l == 'V') { + } else if (l === 'V') { this.value[i][1] += y - - } else if (l == 'C' || l == 'S' || l == 'Q') { + } else if (l === 'C' || l === 'S' || l === 'Q') { this.value[i][1] += x this.value[i][2] += y this.value[i][3] += x this.value[i][4] += y - if (l == 'C') { + if (l === 'C') { this.value[i][5] += x this.value[i][6] += y } - - } else if (l == 'A') { + } else if (l === 'A') { this.value[i][6] += x this.value[i][7] += y } - } } return this - } + }, // Resize path string -, size: function(width, height) { + size: function (width, height) { // get bounding box of current situation - var i, l, box = this.bbox() + var box = this.bbox() + var i, l // recalculate position of all points according to new size for (i = this.value.length - 1; i >= 0; i--) { l = this.value[i][0] - if (l == 'M' || l == 'L' || l == 'T') { - this.value[i][1] = ((this.value[i][1] - box.x) * width) / box.width + box.x + if (l === 'M' || l === 'L' || l === 'T') { + this.value[i][1] = ((this.value[i][1] - box.x) * width) / box.width + box.x this.value[i][2] = ((this.value[i][2] - box.y) * height) / box.height + box.y - - } else if (l == 'H') { - this.value[i][1] = ((this.value[i][1] - box.x) * width) / box.width + box.x - - } else if (l == 'V') { + } else if (l === 'H') { + this.value[i][1] = ((this.value[i][1] - box.x) * width) / box.width + box.x + } else if (l === 'V') { this.value[i][1] = ((this.value[i][1] - box.y) * height) / box.height + box.y - - } else if (l == 'C' || l == 'S' || l == 'Q') { - this.value[i][1] = ((this.value[i][1] - box.x) * width) / box.width + box.x + } else if (l === 'C' || l === 'S' || l === 'Q') { + this.value[i][1] = ((this.value[i][1] - box.x) * width) / box.width + box.x this.value[i][2] = ((this.value[i][2] - box.y) * height) / box.height + box.y - this.value[i][3] = ((this.value[i][3] - box.x) * width) / box.width + box.x + this.value[i][3] = ((this.value[i][3] - box.x) * width) / box.width + box.x this.value[i][4] = ((this.value[i][4] - box.y) * height) / box.height + box.y - if (l == 'C') { - this.value[i][5] = ((this.value[i][5] - box.x) * width) / box.width + box.x + if (l === 'C') { + this.value[i][5] = ((this.value[i][5] - box.x) * width) / box.width + box.x this.value[i][6] = ((this.value[i][6] - box.y) * height) / box.height + box.y } - - } else if (l == 'A') { + } else if (l === 'A') { // resize radii - this.value[i][1] = (this.value[i][1] * width) / box.width + this.value[i][1] = (this.value[i][1] * width) / box.width this.value[i][2] = (this.value[i][2] * height) / box.height // move position values - this.value[i][6] = ((this.value[i][6] - box.x) * width) / box.width + box.x + this.value[i][6] = ((this.value[i][6] - box.x) * width) / box.width + box.x this.value[i][7] = ((this.value[i][7] - box.y) * height) / box.height + box.y } - } return this - } + }, // Test if the passed path array use the same path data commands as this path array -, equalCommands: function(pathArray) { + equalCommands: function (pathArray) { var i, il, equalCommands pathArray = new SVG.PathArray(pathArray) equalCommands = this.value.length === pathArray.value.length - for(i = 0, il = this.value.length; equalCommands && i < il; i++) { + for (i = 0, il = this.value.length; equalCommands && i < il; i++) { equalCommands = this.value[i][0] === pathArray.value[i][0] } return equalCommands - } + }, // Make path array morphable -, morph: function(pathArray) { + morph: function (pathArray) { pathArray = new SVG.PathArray(pathArray) - if(this.equalCommands(pathArray)) { + if (this.equalCommands(pathArray)) { this.destination = pathArray } else { this.destination = null } return this - } + }, // Get morphed path array at given position -, at: function(pos) { + at: function (pos) { // make sure a destination is defined if (!this.destination) return this var sourceArray = this.value - , destinationArray = this.destination.value - , array = [], pathArray = new SVG.PathArray() - , i, il, j, jl + var destinationArray = this.destination.value + var array = [] + var pathArray = new SVG.PathArray() + var i, il, j, jl // Animate has specified in the SVG spec // See: https://www.w3.org/TR/SVG11/paths.html#PathElement for (i = 0, il = sourceArray.length; i < il; i++) { array[i] = [sourceArray[i][0]] - for(j = 1, jl = sourceArray[i].length; j < jl; j++) { + for (j = 1, jl = sourceArray[i].length; j < jl; j++) { array[i][j] = sourceArray[i][j] + (destinationArray[i][j] - sourceArray[i][j]) * pos } // For the two flags of the elliptical arc command, the SVG spec say: @@ -221,74 +215,68 @@ SVG.extend(SVG.PathArray, { // Elliptical arc command as an array followed by corresponding indexes: // ['A', rx, ry, x-axis-rotation, large-arc-flag, sweep-flag, x, y] // 0 1 2 3 4 5 6 7 - if(array[i][0] === 'A') { - array[i][4] = +(array[i][4] != 0) - array[i][5] = +(array[i][5] != 0) + if (array[i][0] === 'A') { + array[i][4] = +(array[i][4] !== 0) + array[i][5] = +(array[i][5] !== 0) } } // Directly modify the value of a path array, this is done this way for performance pathArray.value = array return pathArray - } + }, // Absolutize and parse path to array -, parse: function(array) { + parse: function (array) { // if it's already a patharray, no need to parse it if (array instanceof SVG.PathArray) return array.valueOf() // prepare for parsing - var i, x0, y0, s, seg, arr - , x = 0 - , y = 0 - , paramCnt = { 'M':2, 'L':2, 'H':1, 'V':1, 'C':6, 'S':4, 'Q':4, 'T':2, 'A':7, 'Z':0 } - - if(typeof array == 'string'){ + var s + var paramCnt = { 'M': 2, 'L': 2, 'H': 1, 'V': 1, 'C': 6, 'S': 4, 'Q': 4, 'T': 2, 'A': 7, 'Z': 0 } + if (typeof array === 'string') { array = array .replace(SVG.regex.numbersWithDots, pathRegReplace) // convert 45.123.123 to 45.123 .123 .replace(SVG.regex.pathLetters, ' $& ') // put some room between letters and numbers .replace(SVG.regex.hyphen, '$1 -') // add space before hyphen .trim() // trim .split(SVG.regex.delimiter) // split into array - - }else{ - array = array.reduce(function(prev, curr){ + } else { + array = array.reduce(function (prev, curr) { return [].concat.call(prev, curr) }, []) } // array now is an array containing all parts of a path e.g. ['M', '0', '0', 'L', '30', '30' ...] - var arr = [] - , p = new SVG.Point() - , p0 = new SVG.Point() - , index = 0 - , len = array.length + var result = [] + var p = new SVG.Point() + var p0 = new SVG.Point() + var index = 0 + var len = array.length - do{ + do { // Test if we have a path letter - if(SVG.regex.isPathLetter.test(array[index])){ + if (SVG.regex.isPathLetter.test(array[index])) { s = array[index] ++index // If last letter was a move command and we got no new, it defaults to [L]ine - }else if(s == 'M'){ + } else if (s === 'M') { s = 'L' - }else if(s == 'm'){ + } else if (s === 'm') { s = 'l' } - arr.push(pathHandlers[s].call(null, + result.push(pathHandlers[s].call(null, array.slice(index, (index = index + paramCnt[s.toUpperCase()])).map(parseFloat), p, p0 ) ) + } while (len > index) - }while(len > index) - - return arr - - } + return result + }, // Get bounding box of path -, bbox: function() { + bbox: function () { SVG.parser().path.setAttribute('d', this.toString()) return SVG.parser.nodes.path.getBBox() } |