You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
185 lines
5.0 KiB
185 lines
5.0 KiB
|
7 years ago
|
//从quasar处搬运 https://quasar.dev/vue-directives/material-ripple
|
||
|
6 years ago
|
import './style.scss'
|
||
|
7 years ago
|
|
||
|
|
let lastKeyCompositionStatus = false
|
||
|
|
|
||
|
|
function isKeyCode(evt, keyCodes) {
|
||
|
|
return (
|
||
|
|
lastKeyCompositionStatus === true ||
|
||
|
|
evt !== Object(evt) ||
|
||
|
|
evt.isComposing === true ||
|
||
|
|
evt.qKeyEvent === true
|
||
|
|
)
|
||
|
|
? false
|
||
|
|
: [].concat(keyCodes).includes(evt.keyCode)
|
||
|
|
}
|
||
|
|
|
||
|
|
function css(element, css) {
|
||
|
|
let style = element.style
|
||
|
|
|
||
|
|
Object.keys(css).forEach(prop => {
|
||
|
|
style[prop] = css[prop]
|
||
|
|
})
|
||
|
|
}
|
||
|
|
|
||
|
|
function position(e) {
|
||
|
|
if (e.touches && e.touches[0]) {
|
||
|
|
e = e.touches[0]
|
||
|
|
}
|
||
|
|
else if (e.changedTouches && e.changedTouches[0]) {
|
||
|
|
e = e.changedTouches[0]
|
||
|
|
}
|
||
|
|
else if (e.targetTouches && e.targetTouches[0]) {
|
||
|
|
e = e.targetTouches[0]
|
||
|
|
}
|
||
|
|
|
||
|
|
return {
|
||
|
|
top: e.clientY,
|
||
|
|
left: e.clientX
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
function stop(e) {
|
||
|
|
e.stopPropagation()
|
||
|
|
}
|
||
|
|
|
||
|
|
const listenOpts = {
|
||
|
|
hasPassive: false,
|
||
|
|
passiveCapture: true,
|
||
|
|
notPassiveCapture: true
|
||
|
|
}
|
||
|
|
|
||
|
|
function showRipple(evt, el, ctx, forceCenter) {
|
||
|
|
ctx.modifiers.stop === true && stop(evt)
|
||
|
|
|
||
|
|
let {center, color} = ctx.modifiers
|
||
|
|
center = center === true || forceCenter === true
|
||
|
|
|
||
|
|
const
|
||
|
|
node = document.createElement('span'),
|
||
|
|
innerNode = document.createElement('span'),
|
||
|
|
pos = position(evt),
|
||
|
|
{left, top, width, height} = el.getBoundingClientRect(),
|
||
|
|
diameter = Math.sqrt(width * width + height * height),
|
||
|
|
radius = diameter / 2,
|
||
|
|
centerX = `${(width - diameter) / 2}px`,
|
||
|
|
x = center ? centerX : `${pos.left - left - radius}px`,
|
||
|
|
centerY = `${(height - diameter) / 2}px`,
|
||
|
|
y = center ? centerY : `${pos.top - top - radius}px`
|
||
|
|
|
||
|
|
innerNode.className = 'q-ripple__inner'
|
||
|
|
css(innerNode, {
|
||
|
|
height: `${diameter}px`,
|
||
|
|
width: `${diameter}px`,
|
||
|
|
transform: `translate3d(${x},${y},0) scale3d(.2,.2,1)`,
|
||
|
|
opacity: 0
|
||
|
|
})
|
||
|
|
|
||
|
|
node.className = `q-ripple${color ? ' text-' + color : ''}`
|
||
|
|
node.setAttribute('dir', 'ltr')
|
||
|
|
node.appendChild(innerNode)
|
||
|
|
el.appendChild(node)
|
||
|
|
|
||
|
|
const abort = () => {
|
||
|
|
node.remove()
|
||
|
6 years ago
|
window.clearTimeout(timer)
|
||
|
7 years ago
|
}
|
||
|
|
ctx.abort.push(abort)
|
||
|
|
|
||
|
|
let timer = setTimeout(() => {
|
||
|
|
innerNode.classList.add('q-ripple__inner--enter')
|
||
|
|
innerNode.style.transform = `translate3d(${centerX},${centerY},0) scale3d(1,1,1)`
|
||
|
|
innerNode.style.opacity = 0.2
|
||
|
|
|
||
|
|
timer = setTimeout(() => {
|
||
|
|
innerNode.classList.remove('q-ripple__inner--enter')
|
||
|
|
innerNode.classList.add('q-ripple__inner--leave')
|
||
|
|
innerNode.style.opacity = 0
|
||
|
|
|
||
|
|
timer = setTimeout(() => {
|
||
|
|
node.remove()
|
||
|
|
ctx.abort.splice(ctx.abort.indexOf(abort), 1)
|
||
|
|
}, 275)
|
||
|
|
}, 250)
|
||
|
|
}, 50)
|
||
|
|
}
|
||
|
|
|
||
|
|
function updateCtx(ctx, {value, modifiers, arg}) {
|
||
|
|
ctx.enabled = value !== false
|
||
|
|
|
||
|
|
if (ctx.enabled === true) {
|
||
|
|
ctx.modifiers = Object(value) === value
|
||
|
|
? {
|
||
|
|
stop: value.stop === true || modifiers.stop === true,
|
||
|
|
center: value.center === true || modifiers.center === true,
|
||
|
|
color: value.color || arg,
|
||
|
|
keyCodes: [].concat(value.keyCodes || 13)
|
||
|
|
}
|
||
|
|
: {
|
||
|
|
stop: modifiers.stop,
|
||
|
|
center: modifiers.center,
|
||
|
|
color: arg,
|
||
|
|
keyCodes: [13]
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
export default {
|
||
|
|
name: 'ripple',
|
||
|
|
|
||
|
|
inserted(el, binding) {
|
||
|
|
const ctx = {
|
||
|
|
modifiers: {},
|
||
|
|
abort: [],
|
||
|
|
|
||
|
|
click(evt) {
|
||
|
|
if (ctx.enabled === true && evt.qSkipRipple !== true && evt.clientX >= 0) {
|
||
|
|
showRipple(evt, el, ctx, evt.qKeyEvent === true)
|
||
|
|
}
|
||
|
|
},
|
||
|
|
|
||
|
|
keyup(evt) {
|
||
|
|
if (
|
||
|
|
ctx.enabled === true &&
|
||
|
|
evt.qSkipRipple !== true &&
|
||
|
|
isKeyCode(evt, ctx.modifiers.keyCodes) === true
|
||
|
|
) {
|
||
|
|
showRipple(evt, el, ctx, true)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
updateCtx(ctx, binding)
|
||
|
|
|
||
|
|
if (el.__qripple) {
|
||
|
|
el.__qripple_old = el.__qripple
|
||
|
|
}
|
||
|
|
|
||
|
|
const computed = window.getComputedStyle(el)
|
||
|
|
if (computed && computed.position === 'static') {
|
||
|
|
el.style.position = 'relative'
|
||
|
|
el.dataset.previousPosition = 'static'
|
||
|
|
}
|
||
|
|
|
||
|
|
el.__qripple = ctx
|
||
|
|
el.addEventListener('click', ctx.click, listenOpts.passive)
|
||
|
|
el.addEventListener('keyup', ctx.keyup, listenOpts.passive)
|
||
|
|
},
|
||
|
|
|
||
|
|
update(el, binding) {
|
||
|
|
el.__qripple !== void 0 && updateCtx(el.__qripple, binding)
|
||
|
|
},
|
||
|
|
|
||
|
|
unbind(el) {
|
||
|
|
const ctx = el.__qripple_old || el.__qripple
|
||
|
|
if (ctx !== void 0) {
|
||
|
|
ctx.abort.forEach(fn => {
|
||
|
|
fn()
|
||
|
|
})
|
||
|
|
el.removeEventListener('click', ctx.click, listenOpts.passive)
|
||
|
|
el.removeEventListener('keyup', ctx.keyup, listenOpts.passive)
|
||
|
|
delete el[el.__qripple_old ? '__qripple_old' : '__qripple']
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|