Permalink
Browse files

Merge pull request #563 from koenbok/feature/stroke-api

Feature/stroke api
  • Loading branch information...
nvh committed Jan 31, 2018
2 parents 8b1c6f3 + 11cf534 commit 0ff94eee02ae9e93b8ff858efe803adcef55035c
Showing with 229 additions and 5 deletions.
  1. +50 −5 framer/SVGPath.coffee
  2. +179 −0 test/tests/SVGPathTest.coffee
View
@@ -38,6 +38,30 @@ class exports.SVGPath extends SVGBaseLayer
@_path = @_svg.querySelector(link)
@_length = @_path.getTotalLength()
updateStroke: ->
startLength = @strokeStart ? 0
endLength = @strokeEnd ? @length
dasharray = []
if endLength < startLength
gap = startLength - endLength
remaining = @length - startLength
dasharray.push(endLength)
dasharray.push(gap)
if remaining isnt 0
dasharray.push(remaining)
dasharray.push(0)
else
length = endLength - startLength
remaining = @length - endLength
if startLength isnt 0
dasharray.push(0)
dasharray.push(startLength)
if length isnt @length and (length isnt 0 or startLength is 0)
dasharray.push(length)
if length isnt remaining and remaining isnt 0
dasharray.push(remaining)
@strokeDasharray = dasharray
# Custom properties
@define "fill", layerProperty(@, "fill", "fill", null, SVG.validFill, SVG.toFill)
@define "stroke", layerProperty(@, "stroke", "stroke", null, SVG.validFill, SVG.toFill)
@@ -48,14 +72,35 @@ class exports.SVGPath extends SVGBaseLayer
@define "strokeOpacity", layerProperty(@, "strokeOpacity", "strokeOpacity", null, _.isNumber, parseFloat)
@define "strokeDasharray", layerProperty(@, "strokeDasharray", "strokeDasharray", [], _.isArray, dasharrayTransform)
@define "strokeDashoffset", layerProperty(@, "strokeDashoffset", "strokeDashoffset", null, _.isNumber, dashoffsetTransform)
@define "strokeLength", layerProperty @, "strokeLength", null, undefined, _.isNumber, null, {}, (path, value) ->
@define "strokeLength", layerProperty @, "strokeLength", null, undefined, _.isNumber, ((value, path) -> Math.max(0, Math.min(value, path.length))), {}, (path, value) ->
strokeStart = path.strokeStart ? 0
strokeEnd = strokeStart + value
if strokeEnd > path.length
strokeEnd -= path.length
path._properties.strokeStart = strokeStart
path._properties.strokeEnd = strokeEnd
path._properties.strokeFraction = value / path.length
if _.isEmpty path.strokeDasharray
path.strokeDasharray = [path.length]
path.strokeDashoffset = path.length - value
@define "strokeFraction", layerProperty @, "strokeFraction", null, undefined, _.isNumber, null, {}, (path, value) ->
path.updateStroke()
@define "strokeFraction", layerProperty @, "strokeFraction", null, undefined, _.isNumber, ((value, path) -> Math.max(0, Math.min(value, 1))), {}, (path, value) ->
path.strokeLength = path.length * value
@define "strokeStart", layerProperty @, "strokeStart", null, undefined, _.isNumber, ((value, path) -> Math.max(0, Math.min(value, path.length))), {}, (path, value) ->
strokeStart = value
strokeEnd = path.strokeEnd ? path.strokeLength ? path.length
if strokeEnd >= strokeStart
path.strokeLength = strokeEnd - strokeStart
else
path.strokeLength = (path.length - strokeStart) + strokeEnd
@define "strokeEnd", layerProperty @, "strokeEnd", null, undefined, _.isNumber, ((value, path) -> Math.max(0, Math.min(value, path.length))), {}, (path, value) ->
strokeStart = path.strokeStart ? 0
strokeEnd = value
if strokeEnd >= strokeStart
path.strokeLength = strokeEnd - strokeStart
else
path.strokeLength = (path.length - strokeStart) + strokeEnd
@define "length", get: -> @_length
@define "start", get: -> @pointAtFraction(0)
@define "end", get: -> @pointAtFraction(1)
@@ -41,6 +41,185 @@ describe "SVGPath", ->
layer.elements.test.strokeDasharray.should.eql []
expect(layer.elements.test.strokeDashoffset).to.be.null
describe "strokeLength", ->
it "0", ->
path.strokeLength = 0
path.strokeStart.should.equal 0
path.strokeEnd.should.equal 0
path.strokeDasharray.should.eql [0, path.length]
path.strokeFraction.should.equal 0
expect(path.strokeDashoffset).to.be.null
it "length", ->
path.strokeLength = path.length
path.strokeStart.should.equal 0
path.strokeEnd.should.equal path.length
path.strokeDasharray.should.eql []
path.strokeFraction.should.equal 1
expect(path.strokeDashoffset).to.be.null
it "100", ->
path.strokeLength = 100
path.strokeStart.should.equal 0
path.strokeEnd.should.equal 100
path.strokeFraction.should.equal 100/path.length
path.strokeDasharray.should.eql [100, path.length - 100]
expect(path.strokeDashoffset).to.be.null
it "-1", ->
path.strokeLength = -1
path.strokeLength.should.equal 0
path.strokeStart.should.equal 0
path.strokeEnd.should.equal 0
path.strokeDasharray.should.eql [0, path.length]
path.strokeFraction.should.equal 0
expect(path.strokeDashoffset).to.be.null
it "1000", ->
path.strokeLength = 1000
path.strokeLength.should.equal path.length
path.strokeStart.should.equal 0
path.strokeEnd.should.equal path.length
path.strokeDasharray.should.eql []
path.strokeFraction.should.equal 1
expect(path.strokeDashoffset).to.be.null
describe "strokeFraction", ->
it "0", ->
path.strokeFraction = 0
path.strokeStart.should.equal 0
path.strokeEnd.should.equal 0
path.strokeLength.should.equal 0
path.strokeDasharray.should.eql [0, path.length]
expect(path.strokeDashoffset).to.be.null
it "1", ->
path.strokeFraction = 1
path.strokeStart.should.equal 0
path.strokeEnd.should.equal path.length
path.strokeLength.should.equal path.length
path.strokeDasharray.should.eql []
expect(path.strokeDashoffset).to.be.null
it "0.5", ->
path.strokeFraction = 0.5
path.strokeStart.should.equal 0
path.strokeEnd.should.equal path.length / 2
path.strokeLength.should.equal path.length / 2
path.strokeDasharray.should.eql [path.length/2]
expect(path.strokeDashoffset).to.be.null
it "-1", ->
path.strokeFraction = -1
path.strokeFraction.should.equal 0
path.strokeStart.should.equal 0
path.strokeEnd.should.equal 0
path.strokeLength.should.equal 0
path.strokeDasharray.should.eql [0, path.length]
expect(path.strokeDashoffset).to.be.null
it "1000", ->
path.strokeFraction = 1000
path.strokeFraction.should.equal 1
path.strokeStart.should.equal 0
path.strokeEnd.should.equal path.length
path.strokeLength.should.equal path.length
path.strokeDasharray.should.eql []
expect(path.strokeDashoffset).to.be.null
describe "strokeStart", ->
it "0", ->
path.strokeStart = 0
path.strokeEnd.should.equal path.length
path.strokeLength.should.equal path.length
path.strokeDasharray.should.eql []
expect(path.strokeDashoffset).to.be.null
it "length", ->
path.strokeStart = path.length
path.strokeEnd.should.equal path.length
path.strokeLength.should.equal 0
path.strokeDasharray.should.eql [0, path.length]
expect(path.strokeDashoffset).to.be.null
it "0.5", ->
path.strokeStart = path.length / 2
path.strokeEnd.should.equal path.length
path.strokeLength.should.equal path.length / 2
path.strokeDasharray.should.eql [0, path.length/2, path.length/2]
expect(path.strokeDashoffset).to.be.null
it "with end", ->
path.strokeStart = 50
path.strokeEnd = 200
path.strokeLength.should.equal 150
path.strokeDasharray.should.eql [0, 50, 150, path.length - 200]
expect(path.strokeDashoffset).to.be.null
it "with end before start", ->
path.strokeStart = 200
path.strokeEnd = 50
path.strokeLength.should.equal path.length - 200 + 50
path.strokeDasharray.should.eql [50, 150, path.length - 200, 0]
expect(path.strokeDashoffset).to.be.null
it "with reversed end before start", ->
path.strokeEnd = 50
path.strokeStart = 200
path.strokeLength.should.equal path.length - 200 + 50
path.strokeDasharray.should.eql [50, 150, path.length - 200, 0]
expect(path.strokeDashoffset).to.be.null
it "-1", ->
path.strokeStart = -1
path.strokeStart.should.equal 0
path.strokeEnd.should.equal path.length
path.strokeLength.should.equal path.length
path.strokeDasharray.should.eql []
expect(path.strokeDashoffset).to.be.null
it "1000", ->
path.strokeStart = 1000
path.strokeStart.should.equal path.length
path.strokeEnd.should.equal path.length
path.strokeLength.should.equal 0
path.strokeDasharray.should.eql [0, path.length]
expect(path.strokeDashoffset).to.be.null
describe "strokeEnd", ->
it "0", ->
path.strokeEnd = 0
path.strokeLength.should.equal 0
path.strokeDasharray.should.eql [0, path.length]
expect(path.strokeDashoffset).to.be.null
it "1", ->
path.strokeEnd = path.length
path.strokeLength.should.equal path.length
path.strokeDasharray.should.eql []
expect(path.strokeDashoffset).to.be.null
it "0.5", ->
path.strokeEnd = path.length / 2
path.strokeLength.should.equal path.length / 2
path.strokeDasharray.should.eql [path.length/2]
expect(path.strokeDashoffset).to.be.null
it "-1", ->
path.strokeEnd = -1
path.strokeEnd.should.equal 0
path.strokeLength.should.equal 0
path.strokeDasharray.should.eql [0, path.length]
expect(path.strokeDashoffset).to.be.null
it "1000", ->
path.strokeEnd = 1000
path.strokeEnd.should.equal path.length
path.strokeLength.should.equal path.length
path.strokeDasharray.should.eql []
expect(path.strokeDashoffset).to.be.null
describe "positioning", ->
it "should proxy the transform property to the SVGLayer if that is it's direct parent", ->
path.x.should.equal 123

0 comments on commit 0ff94ee

Please sign in to comment.