Skip to content

Instantly share code, notes, and snippets.

@smolinari
Last active September 4, 2019 07:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save smolinari/37367d96e800c940c289e86f752c2562 to your computer and use it in GitHub Desktop.
Save smolinari/37367d96e800c940c289e86f752c2562 to your computer and use it in GitHub Desktop.
<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
Copy link
Author

Yeah. I agree. It's not pretty. Seems like passing reactivity was easier with the this reference in the options API and we are losing that simplicity.

Scott

@smolinari
Copy link
Author

@trafium - Would this version work?

Scott

@smolinari
Copy link
Author

smolinari commented Sep 2, 2019

Not sure I like the "Ref" postfix. Seems unnecessary now in the setup() function. The "use" prefix on the functions should identify anything returned is a Ref. Right?

Scott

@smolinari
Copy link
Author

I'm taking the "Ref" postfix out.

Scott

@smolinari
Copy link
Author

Not too much different than what you had with just Refs. 😄

Scott

@voluntadpear
Copy link

Refs look more useful and less confusing than reactive and this final version doesn't look much different than the refs version. I don't see when you would prefer reactive over refs.

@doncatnip
Copy link

doncatnip commented Sep 2, 2019

I use it to group properties that really do belong together. A mouse position always has an x and y. A date range that has start, end. In the rare occasion you really only need/can pass the y axis along, i'd destructure it into refs.

I actually use it rather often. It might seem that reactive is superfluous, but at this point I would not want to miss it.

@trafium
Copy link

trafium commented Sep 3, 2019

@smolinari
Will check your solution soon.

I realised that in my use cases i never had to deal with actual mutable lists or other complex data. Took me long to realise, but seems like I can't really do those with refs only without much pain 😅

@trafium
Copy link

trafium commented Sep 3, 2019

@smolinari
Besides couple of typos there are still problems with lines #20 and #21 because primitive values are passed into functions instead of refs/reactive data.

@smolinari
Copy link
Author

@trafium - And if just the variable is passed in without value? Using value in the function?

Scott

@trafium
Copy link

trafium commented Sep 3, 2019

@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)

@smolinari
Copy link
Author

@trafium - edited. Will that work?

Scott

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment