summaryrefslogtreecommitdiffstats
path: root/src/gradient.js
blob: 13256f458fd14fa1bf248ec50e83a5394766fc87 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
SVG.Gradient = SVG.invent({
  // Initialize node
  create: function (type) {
    this.constructor.call(this, typeof type === 'object' ? type : SVG.create(type + 'Gradient'))
  },

  // Inherit from
  inherit: SVG.Container,

  // Add class methods
  extend: {
    // Add a color stop
    stop: function (offset, color, opacity) {
      return this.put(new SVG.Stop()).update(offset, color, opacity)
    },
    // Update gradient
    update: function (block) {
      // remove all stops
      this.clear()

      // invoke passed block
      if (typeof block === 'function') {
        block.call(this, this)
      }

      return this
    },
    // Return the fill id
    url: function () {
      return 'url(#' + this.id() + ')'
    },
    // Alias string convertion to fill
    toString: function () {
      return this.url()
    },
    // custom attr to handle transform
    attr: function (a, b, c) {
      if (a === 'transform') a = 'gradientTransform'
      return SVG.Container.prototype.attr.call(this, a, b, c)
    }
  },

  // Add parent method
  construct: {
    // Create gradient element in defs
    gradient: function (type, block) {
      return this.defs().gradient(type, block)
    }
  }
})

// Add animatable methods to both gradient and fx module
SVG.extend([SVG.Gradient, SVG.FX], {
  // From position
  from: function (x, y) {
    return (this._target || this).type === 'radialGradient'
      ? this.attr({ fx: new SVG.Number(x), fy: new SVG.Number(y) })
      : this.attr({ x1: new SVG.Number(x), y1: new SVG.Number(y) })
  },
  // To position
  to: function (x, y) {
    return (this._target || this).type === 'radialGradient'
      ? this.attr({ cx: new SVG.Number(x), cy: new SVG.Number(y) })
      : this.attr({ x2: new SVG.Number(x), y2: new SVG.Number(y) })
  }
})

// Base gradient generation
SVG.extend(SVG.Defs, {
  // define gradient
  gradient: function (type, block) {
    return this.put(new SVG.Gradient(type)).update(block)
  }

})

SVG.Stop = SVG.invent({
  // Initialize node
  create: 'stop',

  // Inherit from
  inherit: SVG.Element,

  // Add class methods
  extend: {
    // add color stops
    update: function (o) {
      if (typeof o === 'number' || o instanceof SVG.Number) {
        o = {
          offset: arguments[0],
          color: arguments[1],
          opacity: arguments[2]
        }
      }

      // set attributes
      if (o.opacity != null) this.attr('stop-opacity', o.opacity)
      if (o.color != null) this.attr('stop-color', o.color)
      if (o.offset != null) this.attr('offset', new SVG.Number(o.offset))

      return this
    }
  }

})