mirror of
https://github.com/pipipi-pikachu/PPTist.git
synced 2025-04-15 02:20:00 +08:00
131 lines
2.9 KiB
Vue
131 lines
2.9 KiB
Vue
<template>
|
|
<div class="alpha">
|
|
<div class="alpha-checkboard-wrap">
|
|
<Checkboard />
|
|
</div>
|
|
<div class="alpha-gradient" :style="{ background: gradientColor }"></div>
|
|
<div
|
|
class="alpha-container"
|
|
ref="alphaRef"
|
|
@mousedown="$event => handleMouseDown($event)"
|
|
>
|
|
<div class="alpha-pointer" :style="{ left: color.a * 100 + '%' }">
|
|
<div class="alpha-picker"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script lang="ts">
|
|
import { computed, defineComponent, onUnmounted, PropType, ref } from 'vue'
|
|
|
|
import Checkboard from './Checkboard.vue'
|
|
import { ColorFormats } from 'tinycolor2'
|
|
|
|
export default defineComponent({
|
|
name: 'alpha',
|
|
components: {
|
|
Checkboard,
|
|
},
|
|
props: {
|
|
modelValue: {
|
|
type: Object as PropType<ColorFormats.RGBA>,
|
|
required: true,
|
|
},
|
|
},
|
|
setup(props, { emit }) {
|
|
const color = computed(() => props.modelValue)
|
|
const gradientColor = computed(() => {
|
|
const rgbaStr = [color.value.r, color.value.g, color.value.b].join(',')
|
|
return `linear-gradient(to right, rgba(${rgbaStr}, 0) 0%, rgba(${rgbaStr}, 1) 100%)`
|
|
})
|
|
|
|
const alphaRef = ref<HTMLElement | null>(null)
|
|
const handleChange = (e: MouseEvent) => {
|
|
e.preventDefault()
|
|
if(!alphaRef.value) return
|
|
const containerWidth = alphaRef.value.clientWidth
|
|
const xOffset = alphaRef.value.getBoundingClientRect().left + window.pageXOffset
|
|
const left = e.pageX - xOffset
|
|
let a
|
|
|
|
if(left < 0) a = 0
|
|
else if(left > containerWidth) a = 1
|
|
else a = Math.round(left * 100 / containerWidth) / 100
|
|
|
|
if(color.value.a !== a) {
|
|
emit('update:modelValue', {
|
|
r: color.value.r,
|
|
g: color.value.g,
|
|
b: color.value.b,
|
|
a: a,
|
|
})
|
|
}
|
|
}
|
|
|
|
const unbindEventListeners = () => {
|
|
window.removeEventListener('mousemove', handleChange)
|
|
window.removeEventListener('mouseup', unbindEventListeners)
|
|
}
|
|
const handleMouseDown = (e: MouseEvent) => {
|
|
handleChange(e)
|
|
window.addEventListener('mousemove', handleChange)
|
|
window.addEventListener('mouseup', unbindEventListeners)
|
|
}
|
|
|
|
onUnmounted(unbindEventListeners)
|
|
|
|
return {
|
|
alphaRef,
|
|
gradientColor,
|
|
handleMouseDown,
|
|
color,
|
|
}
|
|
},
|
|
})
|
|
</script>
|
|
|
|
<style>
|
|
.alpha {
|
|
position: absolute;
|
|
top: 0;
|
|
right: 0;
|
|
bottom: 0;
|
|
left: 0;
|
|
}
|
|
.alpha-checkboard-wrap {
|
|
position: absolute;
|
|
top: 0;
|
|
right: 0;
|
|
bottom: 0;
|
|
left: 0;
|
|
overflow: hidden;
|
|
}
|
|
.alpha-gradient {
|
|
position: absolute;
|
|
top: 0;
|
|
right: 0;
|
|
bottom: 0;
|
|
left: 0;
|
|
}
|
|
.alpha-container {
|
|
cursor: pointer;
|
|
position: relative;
|
|
z-index: 2;
|
|
height: 100%;
|
|
margin: 0 3px;
|
|
}
|
|
.alpha-pointer {
|
|
z-index: 2;
|
|
position: absolute;
|
|
}
|
|
.alpha-picker {
|
|
cursor: pointer;
|
|
width: 4px;
|
|
height: 8px;
|
|
box-shadow: 0 0 2px rgba(0, 0, 0, .6);
|
|
background: #fff;
|
|
margin-top: 1px;
|
|
transform: translateX(-2px);
|
|
}
|
|
</style> |