Start the creation of ink ripple

This commit is contained in:
Marcos Moura 2016-06-21 22:45:49 -03:00
parent 3fed7ddf33
commit c36ee6005f
12 changed files with 275 additions and 8 deletions

View file

@ -1,4 +1,3 @@
{
"plugins": ["transform-runtime"],
"presets": ["es2015", "stage-0"]
}

View file

@ -22,7 +22,7 @@
<body>
<div class="container" id="app" v-cloak>
<md-button class="md-primary" @click="clickAction">My first component</md-button>
<md-link-button class="md-primary md-raised" href="/" target="_blank">My second component</md-link-button>
<md-link-button class="md-primary md-raised" href="/">My second component</md-link-button>
</div>
<script src="components/main.js"></script>

View file

@ -49,6 +49,7 @@
"xtend": "^4.0.1"
},
"dependencies": {
"vue": "^1.0.25"
"vue": "^1.0.25",
"vue-ripple": "^1.0.2"
}
}

View file

@ -1,7 +1,9 @@
import Vue from 'vue/dist/vue.min';
import MdButton from './mdButton';
import MdInkRipple from './mdInkRipple';
Vue.use(MdButton);
Vue.use(MdInkRipple);
new Vue({
el: '#app',

View file

@ -4,3 +4,4 @@ export default {
disabled: Boolean
}
};

View file

@ -1,6 +1,134 @@
@import '../../stylesheets/variables.scss';
$button-width: 88px;
$button-height: 36px;
$button-icon-size: 40px;
.md-button {
height: 36px;
padding: 0 8px;
border: none;
border-radius: 2px;
min-width: $button-width;
min-height: $button-height;
margin: 6px 8px;
padding: 0 6px;
display: inline-block;
position: relative;
align-items: center;
overflow: hidden;
user-select: none;
cursor: pointer;
outline: none;
background: none;
border: 0;
border-radius: 3px;
transition: box-shadow $swift-ease-out-duration $swift-ease-out-timing-function,
background-color $swift-ease-out-duration $swift-ease-out-timing-function;
color: currentColor;
font-family: inherit;
font-size: 14px;
font-style: inherit;
font-variant: inherit;
font-weight: 500;
line-height: $button-height;
text-align: center;
text-transform: uppercase;
text-decoration: none;
vertical-align: top;
white-space: nowrap;
&:focus {
outline: none;
}
&:hover,
&:focus {
text-decoration: none;
}
&.ng-hide,
&.ng-leave {
transition: none;
}
&.md-raised:not([disabled]) {
box-shadow: $material-shadow-z1;
}
&.md-icon-button {
width: $button-icon-size;
min-width: 0;
height: $button-icon-size;
margin: 0 6px;
padding: 8px;
border-radius: 50%;
line-height: 24px;
}
/*
&.md-cornered {
border-radius: 0;
}
&.md-icon {
padding: 0;
background: none;
}
&.md-fab {
// Include the top/left/bottom/right fab positions
@include fab-all-positions();
z-index: $z-index-fab;
line-height: $button-fab-line-height;
min-width: 0;
width: $button-fab-width;
height: $button-fab-height;
vertical-align: middle;
@include md-shadow-bottom-z-1();
border-radius: $button-fab-border-radius;
background-clip: padding-box;
overflow: hidden;
transition: $swift-ease-in;
transition-property: background-color, box-shadow, transform;
.md-ripple-container {
border-radius: $button-fab-border-radius;
background-clip: padding-box;
overflow: hidden;
// The following hack causes Safari/Chrome to respect overflow hidden for ripples
-webkit-mask-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAA5JREFUeNpiYGBgAAgwAAAEAAGbA+oJAAAAAElFTkSuQmCC');
}
&.md-mini {
line-height: $button-fab-mini-line-height;
width: $button-fab-mini-width;
height: $button-fab-mini-height;
}
&.ng-hide, &.ng-leave {
transition: none;
}
}
&:not([disabled]) {
&.md-raised,
&.md-fab {
&.md-focused {
@include md-shadow-bottom-z-1();
}
&:active {
@include md-shadow-bottom-z-2();
}
}
} */
.md-ripple-container {
border-radius: 3px;
background-clip: padding-box;
overflow: hidden;
-webkit-mask-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAA5JREFUeNpiYGBgAAgwAAAEAAGbA+oJAAAAAElFTkSuQmCC');
}
}

View file

@ -1,5 +1,5 @@
<template>
<button :type="type || 'button'" :disabled="disabled" class="md-button">
<button :type="type || 'button'" :disabled="disabled" class="md-button" v-md-ink-ripple>
<slot></slot>
</button>
</template>

View file

@ -0,0 +1,59 @@
import './mdInkRipple.vue';
export default function install(Vue) {
let rippleParentClass = 'md-ink-ripple';
let rippleClass = 'md-ripple';
let rippleActiveClass = 'md-active';
let registerMouseEvent = (element) => {
Vue.nextTick(() => {
let rect = element.getBoundingClientRect();
let ripple = element.querySelector('.' + rippleClass);
element.addEventListener('mousedown', function(event) {
ripple.classList.remove(rippleActiveClass);
let top = event.pageY - rect.top - ripple.offsetHeight / 2 - document.body.scrollTop;
let left = event.pageX - rect.left - ripple.offsetWidth / 2 - document.body.scrollLeft;
ripple.style.top = top + 'px';
ripple.style.left = left + 'px';
ripple.classList.add(rippleActiveClass);
});
});
};
let createElement = (ripple, className, size) => {
ripple = document.createElement('div');
ripple.className = className;
if (size) {
ripple.style.width = size;
ripple.style.height = size;
}
return ripple;
};
let createRipple = (element) => {
let ripple = element.querySelector('.' + rippleClass);
if (!ripple) {
Vue.nextTick(() => {
let elementSize = Math.round(Math.max(element.offsetWidth, element.offsetHeight)) + 'px';
let rippleParent = createElement(ripple, rippleParentClass);
let rippleElement = createElement(ripple, rippleClass, elementSize);
rippleParent.appendChild(rippleElement);
element.appendChild(rippleParent);
registerMouseEvent(element);
});
}
};
Vue.directive('mdInkRipple', function() {
createRipple(this.el);
});
}

View file

@ -0,0 +1,28 @@
@import '../../stylesheets/variables.scss';
.md-ink-ripple {
pointer-events: none;
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
}
.md-ripple {
position: absolute;
transform: scale(0);
background: rgba(0, 0, 0, .26);
border-radius: 50%;
&.md-active {
animation: ripple 1.2s $swift-ease-out-timing-function;
}
}
@keyframes ripple {
to {
transform: scale(1.5);
opacity: 0;
}
}

View file

@ -0,0 +1 @@
<style lang="scss" src="mdInkRipple.scss"></style>

View file

@ -0,0 +1,12 @@
body {
min-height: 100%;
position: relative;
-webkit-tap-highlight-color: transparent;
-webkit-touch-callout: none;
-webkit-text-size-adjust: 100%;
-ms-text-size-adjust: 100%;
-moz-osx-font-smoothing: grayscale;
-webkit-font-smoothing: antialiased;
font-size: 14px;
font-family: $font-roboto;
}

View file

@ -0,0 +1,36 @@
/* Transitions
========================================================================== */
$swift-ease-out-duration: .4s !default;
$swift-ease-out-timing-function: cubic-bezier(.25, .8, .25, 1) !default;
$swift-ease-out: all $swift-ease-out-duration $swift-ease-out-timing-function !default;
$swift-ease-in-duration: .3s !default;
$swift-ease-in-timing-function: cubic-bezier(.55, 0, .55, .2) !default;
$swift-ease-in: all $swift-ease-in-duration $swift-ease-in-timing-function !default;
$swift-ease-in-out-duration: .5s !default;
$swift-ease-in-out-timing-function: cubic-bezier(.35, 0, .25, 1) !default;
$swift-ease-in-out: all $swift-ease-in-out-duration $swift-ease-in-out-timing-function !default;
$swift-linear-duration: .08s !default;
$swift-linear-timing-function: linear !default;
$swift-linear: all $swift-linear-duration $swift-linear-timing-function !default;
$material-enter-duration: .3s;
$material-enter-timing-function: cubic-bezier(.0, .0, .2, 1);
$material-enter: all $material-enter-duration $material-enter-timing-function;
$material-leave-duration: .3s;
$material-leave-timing-function: cubic-bezier(.4, .0, 1, 1);
$material-leave: all $material-leave-duration $material-leave-timing-function;
/* Common
========================================================================== */
$material-shadow-z1: 0 2px 5px rgba(0, 0, 0, .26);
$material-shadow-z2: 0 4px 8px rgba(0, 0, 0, .4);
$font-roboto: Roboto, "Helvetica Neue", sans-serif;