Last active
September 4, 2019 07:40
-
-
Save smolinari/37367d96e800c940c289e86f752c2562 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<template lang="pug"> | |
div.component(ref="el" :style="{ filter: `saturate(${saturation}) brightness(${brightness})` }") | |
div | |
div Brightness: {{brightness}} | |
div Saturation: {{saturation}} | |
div Width: {{width}} | |
div Height: {{height}} | |
div X: {{x}} | |
div Y: {{y}} | |
</template> | |
<script> | |
import { onBeforeUnmount, onMounted, reactive, ref, toRefs, watch } from '@vue/composition-api' | |
export default { | |
setup () { | |
let el = ref(null) | |
const { x, y } = useRelativeMousePosition(el) | |
const { width, height } = useSizeObserver(el) | |
const { brightness } = useBrightness(x, width) | |
const { saturation } = useSaturation(y, height) | |
return { | |
el, | |
width, | |
height, | |
x, | |
y, | |
brightness, | |
saturation | |
} | |
} | |
} | |
function useRelativeMousePosition (el) { | |
let mousePosition = reactive({ | |
x: 0, | |
y: 0 | |
}) | |
function update (event) { | |
const rect = el.getBoundingClientRect() | |
mousePosition.x = event.clientX - rect.left | |
mousePosition.y = event.clientY - rect.top | |
} | |
onMounted(() => window.addEventListener('mousemove', update)) | |
onBeforeUnmount(() => window.removeEventListener('mousemove', update)) | |
return toRefs(mousePosition) | |
function useSizeObserver (el) { | |
let attrs = reactive({ | |
width: 0, | |
height: 0 | |
}) | |
const resizeObserver = new ResizeObserver(entries => { | |
for (let entry of entries) { | |
attrs.width = entry.contentRect.width | |
attrs.height = entry.contentRect.height | |
} | |
}) | |
onMounted(() => resizeObserver.observe(el)) | |
onBeforeUnmount(() => resizeObserver.unobserve(el)) | |
return toRefs(attrs) | |
} | |
function useBrightness (value, maxValue) { | |
let brightnessRef = ref(0) | |
watch([value, maxValue], ([value, max]) => { | |
brightnessRef = cappedValue(value, { max, min: 0 }) | |
}, { lazy: true }) | |
return { brightnessRef } | |
} | |
function useSaturation (value, maxValue) { | |
let saturationRef = ref(0) | |
watch([value, maxValue], ([value, max]) => { | |
saturationRef = cappedValue(value, { max, min: 0 }) | |
}, { lazy: true }) | |
return { saturationRef } | |
} | |
function cappedValue (value, { max, min }) { | |
return Math.max(min, Math.min(value, max)) / max | |
} | |
</script> | |
<style | |
lang="scss" | |
scoped | |
> | |
.component { | |
max-width: 700px; | |
min-height: 300px; | |
background: royalblue; | |
color: white; | |
display: flex; | |
align-items: center; | |
justify-content: center; | |
flex-direction: column; | |
} | |
</style> |
@smolinari
Yes, in fact we don't need to use .value
at all since we would pass ref into watch
and receive plain values in callback function ([value, max]
part)
@trafium - edited. Will that work?
Scott
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@trafium - And if just the variable is passed in without value? Using value in the function?
Scott