polymer-paper-rails 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/README.md +69 -0
- data/Rakefile +1 -0
- data/app/assets/components/core/animation/web-animations.html.erb +1 -0
- data/app/assets/components/core/animation/web-animations.js +5666 -0
- data/app/assets/components/core/icon/core-icon.css +25 -0
- data/app/assets/components/core/icon/core-icon.html.erb +126 -0
- data/app/assets/components/core/iconset/core-iconset.html.erb +236 -0
- data/app/assets/components/core/input/core-input.css +35 -0
- data/app/assets/components/core/input/core-input.html.erb +385 -0
- data/app/assets/components/core/list/core-list.css +20 -0
- data/app/assets/components/core/list/core-list.html.erb +403 -0
- data/app/assets/components/core/media-query/core-media-query.html +86 -0
- data/app/assets/components/core/menu/core-menu.css +18 -0
- data/app/assets/components/core/menu/core-menu.html.erb +62 -0
- data/app/assets/components/core/menu/core-submenu.css +29 -0
- data/app/assets/components/core/menu/core-submenu.html.erb +106 -0
- data/app/assets/components/core/meta/core-meta.html +143 -0
- data/app/assets/components/core/overlay/core-key-helper.html +17 -0
- data/app/assets/components/core/overlay/core-overlay-layer.html +112 -0
- data/app/assets/components/core/overlay/core-overlay.html.erb +661 -0
- data/app/assets/components/core/range/core-range.html +106 -0
- data/app/assets/components/core/selection/core-selection.html +148 -0
- data/app/assets/components/core/selector/core-selector.html.erb +423 -0
- data/app/assets/components/core/style/core-style.html +386 -0
- data/app/assets/components/core/transition/core-transition-css.html.erb +76 -0
- data/app/assets/components/core/transition/core-transition-overlay.css +46 -0
- data/app/assets/components/core/transition/core-transition.html.erb +44 -0
- data/app/assets/components/paper-button/paper-button.css +115 -0
- data/app/assets/components/paper-button/paper-button.html.erb +210 -0
- data/app/assets/components/paper-checkbox/paper-checkbox.css +262 -0
- data/app/assets/components/paper-checkbox/paper-checkbox.html.erb +104 -0
- data/app/assets/components/paper-dialog/paper-dialog-transition.css +59 -0
- data/app/assets/components/paper-dialog/paper-dialog-transition.html.erb +27 -0
- data/app/assets/components/paper-dialog/paper-dialog.css +0 -0
- data/app/assets/components/paper-dialog/paper-dialog.html.erb +176 -0
- data/app/assets/components/paper-fab/paper-fab.css +27 -0
- data/app/assets/components/paper-fab/paper-fab.html.erb +55 -0
- data/app/assets/components/paper-focusable/paper-focusable.html +144 -0
- data/app/assets/components/paper-icon-button/paper-icon-button.css +17 -0
- data/app/assets/components/paper-icon-button/paper-icon-button.html.erb +87 -0
- data/app/assets/components/paper-input/error-100.png +0 -0
- data/app/assets/components/paper-input/error-200.png +0 -0
- data/app/assets/components/paper-input/paper-input.html.erb +398 -0
- data/app/assets/components/paper-input/paper-input.scss +203 -0
- data/app/assets/components/paper-item/paper-item.css +30 -0
- data/app/assets/components/paper-item/paper-item.html.erb +103 -0
- data/app/assets/components/paper-menu-button/paper-menu-button-overlay.html.erb +86 -0
- data/app/assets/components/paper-menu-button/paper-menu-button-transition.css +19 -0
- data/app/assets/components/paper-menu-button/paper-menu-button-transition.html.erb +118 -0
- data/app/assets/components/paper-menu-button/paper-menu-button.css +86 -0
- data/app/assets/components/paper-menu-button/paper-menu-button.html.erb +128 -0
- data/app/assets/components/paper-progress/paper-progress.css +35 -0
- data/app/assets/components/paper-progress/paper-progress.html.erb +98 -0
- data/app/assets/components/paper-radio-button/paper-radio-button.css +98 -0
- data/app/assets/components/paper-radio-button/paper-radio-button.html.erb +148 -0
- data/app/assets/components/paper-radio-group/paper-radio-group.html.erb +68 -0
- data/app/assets/components/paper-ripple/paper-ripple.html +426 -0
- data/app/assets/components/paper-shadow/paper-shadow.css +81 -0
- data/app/assets/components/paper-shadow/paper-shadow.html.erb +212 -0
- data/app/assets/components/paper-slider/paper-slider.css +193 -0
- data/app/assets/components/paper-slider/paper-slider.html.erb +310 -0
- data/app/assets/components/paper-tabs/paper-tab.css +49 -0
- data/app/assets/components/paper-tabs/paper-tab.html.erb +66 -0
- data/app/assets/components/paper-tabs/paper-tabs.css +57 -0
- data/app/assets/components/paper-tabs/paper-tabs.html.erb +127 -0
- data/app/assets/components/paper-toast/paper-toast.css +0 -0
- data/app/assets/components/paper-toast/paper-toast.html.erb +258 -0
- data/app/assets/components/paper-toggle-button/paper-toggle-button.css +61 -0
- data/app/assets/components/paper-toggle-button/paper-toggle-button.html.erb +125 -0
- data/lib/polymer-paper-rails/engine.rb +4 -0
- data/lib/polymer-paper-rails/version.rb +3 -0
- data/lib/polymer-paper-rails.rb +2 -0
- metadata +158 -0
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
|
|
3
|
+
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
|
|
4
|
+
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
|
|
5
|
+
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
|
|
6
|
+
Code distributed by Google as part of the polymer project is also
|
|
7
|
+
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
|
|
8
|
+
-->
|
|
9
|
+
|
|
10
|
+
<!--
|
|
11
|
+
`paper-radio-button` is a button that can be either checked or unchecked.
|
|
12
|
+
User can tap the radio button to check it. But it cannot be unchecked by
|
|
13
|
+
tapping once checked.
|
|
14
|
+
|
|
15
|
+
Use `paper-radio-group` to group a set of radio buttons. When radio buttons
|
|
16
|
+
are inside a radio group, only one radio button in the group can be checked.
|
|
17
|
+
|
|
18
|
+
Example:
|
|
19
|
+
|
|
20
|
+
<paper-radio-button></paper-radio-button>
|
|
21
|
+
|
|
22
|
+
Styling radio button:
|
|
23
|
+
|
|
24
|
+
To change the ink color for checked state:
|
|
25
|
+
|
|
26
|
+
paper-radio-button::shadow #ink[checked] {
|
|
27
|
+
color: #4285f4;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
To change the radio checked color:
|
|
31
|
+
|
|
32
|
+
paper-radio-button::shadow #onRadio {
|
|
33
|
+
background-color: #4285f4;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
To change the ink color for unchecked state:
|
|
37
|
+
|
|
38
|
+
paper-radio-button::shadow #ink {
|
|
39
|
+
color: #b5b5b5;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
To change the radio unchecked color:
|
|
43
|
+
|
|
44
|
+
paper-radio-button::shadow #offRadio {
|
|
45
|
+
border-color: #b5b5b5;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
@group Paper Elements
|
|
49
|
+
@element paper-radio-button
|
|
50
|
+
@homepage github.io
|
|
51
|
+
-->
|
|
52
|
+
|
|
53
|
+
<%= html_import_tag "paper-ripple/paper-ripple" %>
|
|
54
|
+
|
|
55
|
+
<polymer-element name="paper-radio-button" role="radio" tabindex="0" aria-checked="false">
|
|
56
|
+
<template>
|
|
57
|
+
|
|
58
|
+
<%= stylesheet_link_tag "paper-radio-button/paper-radio-button" %>
|
|
59
|
+
|
|
60
|
+
<div id="radioContainer" class="{{ {labeled: label} | tokenList }}">
|
|
61
|
+
|
|
62
|
+
<div id="offRadio"></div>
|
|
63
|
+
<div id="onRadio"></div>
|
|
64
|
+
|
|
65
|
+
<paper-ripple id="ink" class="circle recenteringTouch" checked?="{{!checked}}"></paper-ripple>
|
|
66
|
+
|
|
67
|
+
</div>
|
|
68
|
+
|
|
69
|
+
<div id="radioLabel" aria-hidden="true" hidden?="{{!label}}">{{label}}<content></content></div>
|
|
70
|
+
|
|
71
|
+
</template>
|
|
72
|
+
<script>
|
|
73
|
+
|
|
74
|
+
Polymer('paper-radio-button', {
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Fired when the checked state changes.
|
|
78
|
+
*
|
|
79
|
+
* @event change
|
|
80
|
+
*/
|
|
81
|
+
|
|
82
|
+
publish: {
|
|
83
|
+
/**
|
|
84
|
+
* Gets or sets the state, `true` is checked and `false` is unchecked.
|
|
85
|
+
*
|
|
86
|
+
* @attribute checked
|
|
87
|
+
* @type boolean
|
|
88
|
+
* @default false
|
|
89
|
+
*/
|
|
90
|
+
checked: {value: false, reflect: true},
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* The label for the radio button.
|
|
94
|
+
*
|
|
95
|
+
* @attribute label
|
|
96
|
+
* @type string
|
|
97
|
+
* @default ''
|
|
98
|
+
*/
|
|
99
|
+
label: '',
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Normally the user cannot uncheck the radio button by tapping once
|
|
103
|
+
* checked. Setting this property to `true` makes the radio button
|
|
104
|
+
* toggleable from checked to unchecked.
|
|
105
|
+
*
|
|
106
|
+
* @attribute toggles
|
|
107
|
+
* @type boolean
|
|
108
|
+
* @default false
|
|
109
|
+
*/
|
|
110
|
+
toggles: false,
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* If true, the user cannot interact with this element.
|
|
114
|
+
*
|
|
115
|
+
* @attribute disabled
|
|
116
|
+
* @type boolean
|
|
117
|
+
* @default false
|
|
118
|
+
*/
|
|
119
|
+
disabled: {value: false, reflect: true}
|
|
120
|
+
},
|
|
121
|
+
|
|
122
|
+
eventDelegates: {
|
|
123
|
+
tap: 'tap'
|
|
124
|
+
},
|
|
125
|
+
|
|
126
|
+
tap: function() {
|
|
127
|
+
this.toggle();
|
|
128
|
+
this.fire('paper-radio-button-activate');
|
|
129
|
+
},
|
|
130
|
+
|
|
131
|
+
toggle: function() {
|
|
132
|
+
this.checked = !this.toggles || !this.checked;
|
|
133
|
+
},
|
|
134
|
+
|
|
135
|
+
checkedChanged: function() {
|
|
136
|
+
this.$.onRadio.classList.toggle('fill', this.checked);
|
|
137
|
+
this.setAttribute('aria-checked', this.checked ? 'true': 'false');
|
|
138
|
+
this.fire('change');
|
|
139
|
+
},
|
|
140
|
+
|
|
141
|
+
labelChanged: function() {
|
|
142
|
+
this.setAttribute('aria-label', this.label);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
</script>
|
|
148
|
+
</polymer-element>
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
|
|
3
|
+
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
|
|
4
|
+
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
|
|
5
|
+
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
|
|
6
|
+
Code distributed by Google as part of the polymer project is also
|
|
7
|
+
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
|
|
8
|
+
-->
|
|
9
|
+
|
|
10
|
+
<!--
|
|
11
|
+
`paper-radio-group` allows user to select only one radio button from a set.
|
|
12
|
+
Checking one radio button that belongs to a radio group unchecks any
|
|
13
|
+
previously checked radio button within the same group. Use
|
|
14
|
+
`selected` to get or set the selected radio button.
|
|
15
|
+
|
|
16
|
+
Example:
|
|
17
|
+
|
|
18
|
+
<paper-radio-group selected="small">
|
|
19
|
+
<paper-radio-button name="small" label="Small"></paper-radio-button>
|
|
20
|
+
<paper-radio-button name="medium" label="Medium"></paper-radio-button>
|
|
21
|
+
<paper-radio-button name="large" label="Large"></paper-radio-button>
|
|
22
|
+
</paper-radio-group>
|
|
23
|
+
|
|
24
|
+
See <a href="../paper-radio-button/">paper-radio-button</a> for more
|
|
25
|
+
information about `paper-radio-button`.
|
|
26
|
+
|
|
27
|
+
@group Paper Elements
|
|
28
|
+
@element paper-radio-group
|
|
29
|
+
@extends core-selector
|
|
30
|
+
@homepage github.io
|
|
31
|
+
-->
|
|
32
|
+
|
|
33
|
+
<%= html_import_tag 'core/selector/core-selector'%>
|
|
34
|
+
<%= html_import_tag 'paper-radio-button/paper-radio-button'%>
|
|
35
|
+
|
|
36
|
+
<polymer-element name="paper-radio-group" extends="core-selector" role="radiogroup">
|
|
37
|
+
|
|
38
|
+
<template>
|
|
39
|
+
|
|
40
|
+
<style>
|
|
41
|
+
|
|
42
|
+
:host {
|
|
43
|
+
display: inline-block;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
polyfill-next-selector { content: ':host > *'; }
|
|
47
|
+
::content > * {
|
|
48
|
+
padding: 12px;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
</style>
|
|
52
|
+
|
|
53
|
+
<shadow></shadow>
|
|
54
|
+
|
|
55
|
+
</template>
|
|
56
|
+
|
|
57
|
+
<script>
|
|
58
|
+
|
|
59
|
+
Polymer('paper-radio-group', {
|
|
60
|
+
|
|
61
|
+
selectedAttribute: 'checked',
|
|
62
|
+
activateEvent: 'paper-radio-button-activate'
|
|
63
|
+
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
</script>
|
|
67
|
+
|
|
68
|
+
</polymer-element>
|
|
@@ -0,0 +1,426 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
|
|
3
|
+
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
|
|
4
|
+
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
|
|
5
|
+
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
|
|
6
|
+
Code distributed by Google as part of the polymer project is also
|
|
7
|
+
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
|
|
8
|
+
-->
|
|
9
|
+
|
|
10
|
+
<!--
|
|
11
|
+
`paper-ripple` provides a visual effect that other paper elements can
|
|
12
|
+
use to simulate a rippling effect emanating from the point of contact. The
|
|
13
|
+
effect can be visualized as a concentric circle with motion.
|
|
14
|
+
|
|
15
|
+
Example:
|
|
16
|
+
|
|
17
|
+
<paper-ripple></paper-ripple>
|
|
18
|
+
|
|
19
|
+
`paper-ripple` listens to "down" and "up" events so it would display ripple
|
|
20
|
+
effect when touches on it. You can also defeat the default behavior and
|
|
21
|
+
manually route the down and up actions to the ripple element. Note that it is
|
|
22
|
+
important if you call downAction() you will have to make sure to call upAction()
|
|
23
|
+
so that `paper-ripple` would end the animation loop.
|
|
24
|
+
|
|
25
|
+
Example:
|
|
26
|
+
|
|
27
|
+
<paper-ripple id="ripple" style="pointer-events: none;"></paper-ripple>
|
|
28
|
+
...
|
|
29
|
+
downAction: function(e) {
|
|
30
|
+
this.$.ripple.downAction({x: e.x, y: e.y});
|
|
31
|
+
},
|
|
32
|
+
upAction: function(e) {
|
|
33
|
+
this.$.ripple.upAction();
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
Styling ripple effect:
|
|
37
|
+
|
|
38
|
+
Use CSS color property to style the ripple:
|
|
39
|
+
|
|
40
|
+
paper-ripple {
|
|
41
|
+
color: #4285f4;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
Note that CSS color property is inherited so it is not required to set it on
|
|
45
|
+
the `paper-ripple` element directly.
|
|
46
|
+
|
|
47
|
+
Apply `recenteringTouch` class to make the recentering rippling effect.
|
|
48
|
+
|
|
49
|
+
<paper-ripple class="recenteringTouch"></paper-ripple>
|
|
50
|
+
|
|
51
|
+
Apply `circle` class to make the rippling effect within a circle.
|
|
52
|
+
|
|
53
|
+
<paper-ripple class="circle"></paper-ripple>
|
|
54
|
+
|
|
55
|
+
@group Paper Elements
|
|
56
|
+
@element paper-ripple
|
|
57
|
+
@homepage github.io
|
|
58
|
+
-->
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
<polymer-element name="paper-ripple" attributes="initialOpacity opacityDecayVelocity">
|
|
62
|
+
<template>
|
|
63
|
+
|
|
64
|
+
<style>
|
|
65
|
+
|
|
66
|
+
:host {
|
|
67
|
+
display: block;
|
|
68
|
+
position: relative;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
#canvas {
|
|
72
|
+
pointer-events: none;
|
|
73
|
+
position: absolute;
|
|
74
|
+
top: 0;
|
|
75
|
+
left: 0;
|
|
76
|
+
width: 100%;
|
|
77
|
+
height: 100%;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
:host(.circle) #canvas {
|
|
81
|
+
border-radius: 50%;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
</style>
|
|
85
|
+
|
|
86
|
+
</template>
|
|
87
|
+
<script>
|
|
88
|
+
|
|
89
|
+
(function() {
|
|
90
|
+
|
|
91
|
+
var waveMaxRadius = 150;
|
|
92
|
+
//
|
|
93
|
+
// INK EQUATIONS
|
|
94
|
+
//
|
|
95
|
+
function waveRadiusFn(touchDownMs, touchUpMs, anim) {
|
|
96
|
+
// Convert from ms to s.
|
|
97
|
+
var touchDown = touchDownMs / 1000;
|
|
98
|
+
var touchUp = touchUpMs / 1000;
|
|
99
|
+
var totalElapsed = touchDown + touchUp;
|
|
100
|
+
var ww = anim.width, hh = anim.height;
|
|
101
|
+
// use diagonal size of container to avoid floating point math sadness
|
|
102
|
+
var waveRadius = Math.min(Math.sqrt(ww * ww + hh * hh), waveMaxRadius) * 1.1 + 5;
|
|
103
|
+
var duration = 1.1 - .2 * (waveRadius / waveMaxRadius);
|
|
104
|
+
var tt = (totalElapsed / duration);
|
|
105
|
+
|
|
106
|
+
var size = waveRadius * (1 - Math.pow(80, -tt));
|
|
107
|
+
return Math.abs(size);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function waveOpacityFn(td, tu, anim) {
|
|
111
|
+
// Convert from ms to s.
|
|
112
|
+
var touchDown = td / 1000;
|
|
113
|
+
var touchUp = tu / 1000;
|
|
114
|
+
var totalElapsed = touchDown + touchUp;
|
|
115
|
+
|
|
116
|
+
if (tu <= 0) { // before touch up
|
|
117
|
+
return anim.initialOpacity;
|
|
118
|
+
}
|
|
119
|
+
return Math.max(0, anim.initialOpacity - touchUp * anim.opacityDecayVelocity);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function waveOuterOpacityFn(td, tu, anim) {
|
|
123
|
+
// Convert from ms to s.
|
|
124
|
+
var touchDown = td / 1000;
|
|
125
|
+
var touchUp = tu / 1000;
|
|
126
|
+
|
|
127
|
+
// Linear increase in background opacity, capped at the opacity
|
|
128
|
+
// of the wavefront (waveOpacity).
|
|
129
|
+
var outerOpacity = touchDown * 0.3;
|
|
130
|
+
var waveOpacity = waveOpacityFn(td, tu, anim);
|
|
131
|
+
return Math.max(0, Math.min(outerOpacity, waveOpacity));
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// Determines whether the wave should be completely removed.
|
|
135
|
+
function waveDidFinish(wave, radius, anim) {
|
|
136
|
+
var waveOpacity = waveOpacityFn(wave.tDown, wave.tUp, anim);
|
|
137
|
+
// If the wave opacity is 0 and the radius exceeds the bounds
|
|
138
|
+
// of the element, then this is finished.
|
|
139
|
+
if (waveOpacity < 0.01 && radius >= Math.min(wave.maxRadius, waveMaxRadius)) {
|
|
140
|
+
return true;
|
|
141
|
+
}
|
|
142
|
+
return false;
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
function waveAtMaximum(wave, radius, anim) {
|
|
146
|
+
var waveOpacity = waveOpacityFn(wave.tDown, wave.tUp, anim);
|
|
147
|
+
if (waveOpacity >= anim.initialOpacity && radius >= Math.min(wave.maxRadius, waveMaxRadius)) {
|
|
148
|
+
return true;
|
|
149
|
+
}
|
|
150
|
+
return false;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
//
|
|
154
|
+
// DRAWING
|
|
155
|
+
//
|
|
156
|
+
function drawRipple(ctx, x, y, radius, innerColor, outerColor) {
|
|
157
|
+
if (outerColor) {
|
|
158
|
+
ctx.fillStyle = outerColor;
|
|
159
|
+
ctx.fillRect(0,0,ctx.canvas.width, ctx.canvas.height);
|
|
160
|
+
}
|
|
161
|
+
ctx.beginPath();
|
|
162
|
+
ctx.arc(x, y, radius, 0, 2 * Math.PI, false);
|
|
163
|
+
ctx.fillStyle = innerColor;
|
|
164
|
+
ctx.fill();
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
//
|
|
168
|
+
// SETUP
|
|
169
|
+
//
|
|
170
|
+
function createWave(elem) {
|
|
171
|
+
var elementStyle = window.getComputedStyle(elem);
|
|
172
|
+
var fgColor = elementStyle.color;
|
|
173
|
+
|
|
174
|
+
var wave = {
|
|
175
|
+
waveColor: fgColor,
|
|
176
|
+
maxRadius: 0,
|
|
177
|
+
isMouseDown: false,
|
|
178
|
+
mouseDownStart: 0.0,
|
|
179
|
+
mouseUpStart: 0.0,
|
|
180
|
+
tDown: 0,
|
|
181
|
+
tUp: 0
|
|
182
|
+
};
|
|
183
|
+
return wave;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
function removeWaveFromScope(scope, wave) {
|
|
187
|
+
if (scope.waves) {
|
|
188
|
+
var pos = scope.waves.indexOf(wave);
|
|
189
|
+
scope.waves.splice(pos, 1);
|
|
190
|
+
}
|
|
191
|
+
};
|
|
192
|
+
|
|
193
|
+
// Shortcuts.
|
|
194
|
+
var pow = Math.pow;
|
|
195
|
+
var now = Date.now;
|
|
196
|
+
if (window.performance && performance.now) {
|
|
197
|
+
now = performance.now.bind(performance);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
function cssColorWithAlpha(cssColor, alpha) {
|
|
201
|
+
var parts = cssColor.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/);
|
|
202
|
+
if (typeof alpha == 'undefined') {
|
|
203
|
+
alpha = 1;
|
|
204
|
+
}
|
|
205
|
+
if (!parts) {
|
|
206
|
+
return 'rgba(255, 255, 255, ' + alpha + ')';
|
|
207
|
+
}
|
|
208
|
+
return 'rgba(' + parts[1] + ', ' + parts[2] + ', ' + parts[3] + ', ' + alpha + ')';
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
function dist(p1, p2) {
|
|
212
|
+
return Math.sqrt(pow(p1.x - p2.x, 2) + pow(p1.y - p2.y, 2));
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
function distanceFromPointToFurthestCorner(point, size) {
|
|
216
|
+
var tl_d = dist(point, {x: 0, y: 0});
|
|
217
|
+
var tr_d = dist(point, {x: size.w, y: 0});
|
|
218
|
+
var bl_d = dist(point, {x: 0, y: size.h});
|
|
219
|
+
var br_d = dist(point, {x: size.w, y: size.h});
|
|
220
|
+
return Math.max(tl_d, tr_d, bl_d, br_d);
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
Polymer('paper-ripple', {
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* The initial opacity set on the wave.
|
|
227
|
+
*
|
|
228
|
+
* @attribute initialOpacity
|
|
229
|
+
* @type number
|
|
230
|
+
* @default 0.25
|
|
231
|
+
*/
|
|
232
|
+
initialOpacity: 0.25,
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* How fast (opacity per second) the wave fades out.
|
|
236
|
+
*
|
|
237
|
+
* @attribute opacityDecayVelocity
|
|
238
|
+
* @type number
|
|
239
|
+
* @default 0.8
|
|
240
|
+
*/
|
|
241
|
+
opacityDecayVelocity: 0.8,
|
|
242
|
+
|
|
243
|
+
backgroundFill: true,
|
|
244
|
+
pixelDensity: 2,
|
|
245
|
+
|
|
246
|
+
eventDelegates: {
|
|
247
|
+
down: 'downAction',
|
|
248
|
+
up: 'upAction'
|
|
249
|
+
},
|
|
250
|
+
|
|
251
|
+
attached: function() {
|
|
252
|
+
// create the canvas element manually becase ios
|
|
253
|
+
// does not render the canvas element if it is not created in the
|
|
254
|
+
// main document (component templates are created in a
|
|
255
|
+
// different document). See:
|
|
256
|
+
// https://bugs.webkit.org/show_bug.cgi?id=109073.
|
|
257
|
+
if (!this.$.canvas) {
|
|
258
|
+
var canvas = document.createElement('canvas');
|
|
259
|
+
canvas.id = 'canvas';
|
|
260
|
+
this.shadowRoot.appendChild(canvas);
|
|
261
|
+
this.$.canvas = canvas;
|
|
262
|
+
}
|
|
263
|
+
},
|
|
264
|
+
|
|
265
|
+
ready: function() {
|
|
266
|
+
this.waves = [];
|
|
267
|
+
},
|
|
268
|
+
|
|
269
|
+
setupCanvas: function() {
|
|
270
|
+
this.$.canvas.setAttribute('width', this.$.canvas.clientWidth * this.pixelDensity + "px");
|
|
271
|
+
this.$.canvas.setAttribute('height', this.$.canvas.clientHeight * this.pixelDensity + "px");
|
|
272
|
+
var ctx = this.$.canvas.getContext('2d');
|
|
273
|
+
ctx.scale(this.pixelDensity, this.pixelDensity);
|
|
274
|
+
if (!this._loop) {
|
|
275
|
+
this._loop = this.animate.bind(this, ctx);
|
|
276
|
+
}
|
|
277
|
+
},
|
|
278
|
+
|
|
279
|
+
downAction: function(e) {
|
|
280
|
+
this.setupCanvas();
|
|
281
|
+
var wave = createWave(this.$.canvas);
|
|
282
|
+
|
|
283
|
+
this.cancelled = false;
|
|
284
|
+
wave.isMouseDown = true;
|
|
285
|
+
wave.tDown = 0.0;
|
|
286
|
+
wave.tUp = 0.0;
|
|
287
|
+
wave.mouseUpStart = 0.0;
|
|
288
|
+
wave.mouseDownStart = now();
|
|
289
|
+
|
|
290
|
+
var width = this.$.canvas.width / 2; // Retina canvas
|
|
291
|
+
var height = this.$.canvas.height / 2;
|
|
292
|
+
var rect = this.getBoundingClientRect();
|
|
293
|
+
var touchX = e.x - rect.left;
|
|
294
|
+
var touchY = e.y - rect.top;
|
|
295
|
+
|
|
296
|
+
wave.startPosition = {x:touchX, y:touchY};
|
|
297
|
+
|
|
298
|
+
if (this.classList.contains("recenteringTouch")) {
|
|
299
|
+
wave.endPosition = {x: width / 2, y: height / 2};
|
|
300
|
+
wave.slideDistance = dist(wave.startPosition, wave.endPosition);
|
|
301
|
+
}
|
|
302
|
+
wave.containerSize = Math.max(width, height);
|
|
303
|
+
wave.maxRadius = distanceFromPointToFurthestCorner(wave.startPosition, {w: width, h: height});
|
|
304
|
+
this.waves.push(wave);
|
|
305
|
+
requestAnimationFrame(this._loop);
|
|
306
|
+
},
|
|
307
|
+
|
|
308
|
+
upAction: function() {
|
|
309
|
+
for (var i = 0; i < this.waves.length; i++) {
|
|
310
|
+
// Declare the next wave that has mouse down to be mouse'ed up.
|
|
311
|
+
var wave = this.waves[i];
|
|
312
|
+
if (wave.isMouseDown) {
|
|
313
|
+
wave.isMouseDown = false
|
|
314
|
+
wave.mouseUpStart = now();
|
|
315
|
+
wave.mouseDownStart = 0;
|
|
316
|
+
wave.tUp = 0.0;
|
|
317
|
+
break;
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
this._loop && requestAnimationFrame(this._loop);
|
|
321
|
+
},
|
|
322
|
+
|
|
323
|
+
cancel: function() {
|
|
324
|
+
this.cancelled = true;
|
|
325
|
+
},
|
|
326
|
+
|
|
327
|
+
animate: function(ctx) {
|
|
328
|
+
var shouldRenderNextFrame = false;
|
|
329
|
+
|
|
330
|
+
// Clear the canvas
|
|
331
|
+
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
|
|
332
|
+
|
|
333
|
+
var deleteTheseWaves = [];
|
|
334
|
+
// The oldest wave's touch down duration
|
|
335
|
+
var longestTouchDownDuration = 0;
|
|
336
|
+
var longestTouchUpDuration = 0;
|
|
337
|
+
// Save the last known wave color
|
|
338
|
+
var lastWaveColor = null;
|
|
339
|
+
// wave animation values
|
|
340
|
+
var anim = {
|
|
341
|
+
initialOpacity: this.initialOpacity,
|
|
342
|
+
opacityDecayVelocity: this.opacityDecayVelocity,
|
|
343
|
+
height: ctx.canvas.height,
|
|
344
|
+
width: ctx.canvas.width
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
for (var i = 0; i < this.waves.length; i++) {
|
|
348
|
+
var wave = this.waves[i];
|
|
349
|
+
|
|
350
|
+
if (wave.mouseDownStart > 0) {
|
|
351
|
+
wave.tDown = now() - wave.mouseDownStart;
|
|
352
|
+
}
|
|
353
|
+
if (wave.mouseUpStart > 0) {
|
|
354
|
+
wave.tUp = now() - wave.mouseUpStart;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
// Determine how long the touch has been up or down.
|
|
358
|
+
var tUp = wave.tUp;
|
|
359
|
+
var tDown = wave.tDown;
|
|
360
|
+
longestTouchDownDuration = Math.max(longestTouchDownDuration, tDown);
|
|
361
|
+
longestTouchUpDuration = Math.max(longestTouchUpDuration, tUp);
|
|
362
|
+
|
|
363
|
+
// Obtain the instantenous size and alpha of the ripple.
|
|
364
|
+
var radius = waveRadiusFn(tDown, tUp, anim);
|
|
365
|
+
var waveAlpha = waveOpacityFn(tDown, tUp, anim);
|
|
366
|
+
var waveColor = cssColorWithAlpha(wave.waveColor, waveAlpha);
|
|
367
|
+
lastWaveColor = wave.waveColor;
|
|
368
|
+
|
|
369
|
+
// Position of the ripple.
|
|
370
|
+
var x = wave.startPosition.x;
|
|
371
|
+
var y = wave.startPosition.y;
|
|
372
|
+
|
|
373
|
+
// Ripple gravitational pull to the center of the canvas.
|
|
374
|
+
if (wave.endPosition) {
|
|
375
|
+
|
|
376
|
+
// This translates from the origin to the center of the view based on the max dimension of
|
|
377
|
+
var translateFraction = Math.min(1, radius / wave.containerSize * 2 / Math.sqrt(2) );
|
|
378
|
+
|
|
379
|
+
x += translateFraction * (wave.endPosition.x - wave.startPosition.x);
|
|
380
|
+
y += translateFraction * (wave.endPosition.y - wave.startPosition.y);
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
// If we do a background fill fade too, work out the correct color.
|
|
384
|
+
var bgFillColor = null;
|
|
385
|
+
if (this.backgroundFill) {
|
|
386
|
+
var bgFillAlpha = waveOuterOpacityFn(tDown, tUp, anim);
|
|
387
|
+
bgFillColor = cssColorWithAlpha(wave.waveColor, bgFillAlpha);
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
// Draw the ripple.
|
|
391
|
+
drawRipple(ctx, x, y, radius, waveColor, bgFillColor);
|
|
392
|
+
|
|
393
|
+
// Determine whether there is any more rendering to be done.
|
|
394
|
+
var maximumWave = waveAtMaximum(wave, radius, anim);
|
|
395
|
+
var waveDissipated = waveDidFinish(wave, radius, anim);
|
|
396
|
+
var shouldKeepWave = !waveDissipated || maximumWave;
|
|
397
|
+
var shouldRenderWaveAgain = !waveDissipated && !maximumWave;
|
|
398
|
+
shouldRenderNextFrame = shouldRenderNextFrame || shouldRenderWaveAgain;
|
|
399
|
+
if (!shouldKeepWave || this.cancelled) {
|
|
400
|
+
deleteTheseWaves.push(wave);
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
if (shouldRenderNextFrame) {
|
|
405
|
+
requestAnimationFrame(this._loop);
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
for (var i = 0; i < deleteTheseWaves.length; ++i) {
|
|
409
|
+
var wave = deleteTheseWaves[i];
|
|
410
|
+
removeWaveFromScope(this, wave);
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
if (!this.waves.length) {
|
|
414
|
+
// If there is nothing to draw, clear any drawn waves now because
|
|
415
|
+
// we're not going to get another requestAnimationFrame any more.
|
|
416
|
+
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
|
|
417
|
+
this._loop = null;
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
});
|
|
422
|
+
|
|
423
|
+
})();
|
|
424
|
+
|
|
425
|
+
</script>
|
|
426
|
+
</polymer-element>
|