[-] Split color picker
This commit is contained in:
+1
-2
@@ -18,8 +18,7 @@
|
|||||||
"tg-blog": "^1.1.0",
|
"tg-blog": "^1.1.0",
|
||||||
"vue": "^3.2.47",
|
"vue": "^3.2.47",
|
||||||
"vue-i18n": "^9.2.2",
|
"vue-i18n": "^9.2.2",
|
||||||
"vue-router": "^4.1.6",
|
"vue-router": "^4.1.6"
|
||||||
"vue3-colorpicker": "^2.1.2"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/jquery": "^3.5.16",
|
"@types/jquery": "^3.5.16",
|
||||||
|
|||||||
@@ -1,285 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div id="ColorPicker" ref="el" @keydown.esc="close">
|
|
||||||
<div id="title-colors" class="fbox-h">
|
|
||||||
<div class="text" @mousedown="windowDrag" @click.right.alt="close">Colors</div>
|
|
||||||
<div class="close fbox-vcenter" @click="close" v-if="showClose"><i class="fas fa-times"></i></div>
|
|
||||||
<input v-model="colorInput" spellcheck="false" @change="colorModel = colorInput">
|
|
||||||
</div>
|
|
||||||
<ColorPicker id="picker" :isWidget="true" pickerType="chrome" v-model:pureColor="colorModel"
|
|
||||||
:disableHistory="true" @pureColorChange="change" format="hex8"/>
|
|
||||||
<div id="palette">
|
|
||||||
<div class="row" v-for="(p, i) of palette" :key="i">
|
|
||||||
<div class="color" v-for="(c, j) in p" :key="j" :style="{'background-color': c ? c : '#333'}"
|
|
||||||
@click.exact="setPalette(i, j)"
|
|
||||||
@click.right.alt="(e) => altClickPalette(e, i, j)"
|
|
||||||
@click.right.exact="(e) => rightClickPalette(e, i, j)"
|
|
||||||
draggable="true" @dragstart="paletteDragStart(i, j)" @drop="(e) => dropPalette(e, i, j)"
|
|
||||||
@dragenter="(e) => paletteDragEnter(e, i, j)" @dragover="(e) => paletteDragOver(e, i, j)"/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts">
|
|
||||||
import "vue3-colorpicker/style.css";
|
|
||||||
import {ColorPicker} from "vue3-colorpicker";
|
|
||||||
import {range} from "@/scripts/utils";
|
|
||||||
import {Emit, Model, Prop, Ref} from "vue-property-decorator";
|
|
||||||
import {Options, Vue} from "vue-class-component";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Mouse Usage:
|
|
||||||
* - Alt + Right-click the title to close
|
|
||||||
* - Left-click on a color block to add color to palette
|
|
||||||
* - Left-drag on a color block to move color
|
|
||||||
* - Right-click on a color block to select color
|
|
||||||
* - Alt + Right-click on a color block to remove color
|
|
||||||
*/
|
|
||||||
@Options({components: {ColorPicker}})
|
|
||||||
export default class MyColorPicker extends Vue
|
|
||||||
{
|
|
||||||
@Model('color') color!: string // Color prop in #ffffffff format
|
|
||||||
colorModel = '' // Color model in #ffffffff format
|
|
||||||
colorInput = '' // Color input in ffffff format
|
|
||||||
palette: string[][] = []
|
|
||||||
showClose = false
|
|
||||||
|
|
||||||
@Ref() el!: HTMLElement
|
|
||||||
@Prop({default: null}) initialPos?: {x: number, y: number}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Init
|
|
||||||
*/
|
|
||||||
created(): void
|
|
||||||
{
|
|
||||||
this.colorModel = this.color
|
|
||||||
this.colorInput = this.colorModel.substr(1, 6)
|
|
||||||
|
|
||||||
const storedPalette = localStorage.getItem('palette')
|
|
||||||
this.palette = !storedPalette ? range(6).map(_ => range(10).map(_ => '')) : JSON.parse(storedPalette);
|
|
||||||
this.storePalette()
|
|
||||||
}
|
|
||||||
|
|
||||||
mounted(): void
|
|
||||||
{
|
|
||||||
if (this.initialPos) this.setPos(this.initialPos.x, this.initialPos.y)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Color change
|
|
||||||
*/
|
|
||||||
@Emit('update:color')
|
|
||||||
change(color: string): string
|
|
||||||
{
|
|
||||||
this.colorInput = color.substr(1, 6)
|
|
||||||
return this.colorModel
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set window position
|
|
||||||
*/
|
|
||||||
setPos(x: number, y: number): void
|
|
||||||
{
|
|
||||||
this.el.style.left = x + 'px'
|
|
||||||
this.el.style.top = y + 'px'
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Window dragging
|
|
||||||
*/
|
|
||||||
windowDrag(e: MouseEvent): void
|
|
||||||
{
|
|
||||||
e.preventDefault()
|
|
||||||
let lastX = e.clientX, lastY = e.clientY
|
|
||||||
|
|
||||||
const mousemove = (e: MouseEvent) =>
|
|
||||||
{
|
|
||||||
const dx = lastX - e.clientX, dy = lastY - e.clientY
|
|
||||||
lastX = e.clientX; lastY = e.clientY
|
|
||||||
this.setPos(this.el.offsetLeft - dx, this.el.offsetTop - dy)
|
|
||||||
}
|
|
||||||
const mouseup = () => {document.removeEventListener('mouseup', mouseup); document.removeEventListener('mousemove', mousemove)}
|
|
||||||
document.addEventListener('mouseup', mouseup)
|
|
||||||
document.addEventListener('mousemove', mousemove)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Emit('updatePalette')
|
|
||||||
storePalette(): string[][]
|
|
||||||
{
|
|
||||||
localStorage.setItem('palette', JSON.stringify(this.palette))
|
|
||||||
return this.palette
|
|
||||||
}
|
|
||||||
|
|
||||||
@Emit()
|
|
||||||
close(e?: Event): void
|
|
||||||
{
|
|
||||||
if (e) e.preventDefault()
|
|
||||||
console.log('Color picker close')
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Left click to override
|
|
||||||
*/
|
|
||||||
setPalette(i: number, j: number): void
|
|
||||||
{
|
|
||||||
this.palette[i][j] = this.colorModel
|
|
||||||
this.storePalette()
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Right click to select
|
|
||||||
*/
|
|
||||||
rightClickPalette(e: Event, i: number, j: number): void
|
|
||||||
{
|
|
||||||
e.preventDefault()
|
|
||||||
if (!this.palette[i][j]) return
|
|
||||||
this.colorModel = this.palette[i][j]
|
|
||||||
this.change(this.colorModel)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Alt right click to remove
|
|
||||||
*/
|
|
||||||
altClickPalette(e: Event, i: number, j: number): void
|
|
||||||
{
|
|
||||||
e.preventDefault()
|
|
||||||
this.palette[i][j] = ''
|
|
||||||
this.storePalette()
|
|
||||||
}
|
|
||||||
|
|
||||||
dragging = {i: 0, j: 0}
|
|
||||||
|
|
||||||
paletteDragStart(i: number, j: number): void
|
|
||||||
{
|
|
||||||
this.dragging = {i, j}
|
|
||||||
}
|
|
||||||
|
|
||||||
dropPalette(e: DragEvent, i: number, j: number): void
|
|
||||||
{
|
|
||||||
// We can assume that toI != fromI
|
|
||||||
const fromI = this.dragging.i * 10 + this.dragging.j
|
|
||||||
const toI = i * 10 + j
|
|
||||||
const incr = toI > fromI ? 1 : -1
|
|
||||||
|
|
||||||
const currentColor = this.palette[this.dragging.i][this.dragging.j]
|
|
||||||
for (let index of range(fromI, toI))
|
|
||||||
{
|
|
||||||
const col = index % 10, row = Math.floor(index / 10)
|
|
||||||
const lastI = index + incr
|
|
||||||
const lastC = lastI % 10, lastR = Math.floor(lastI / 10)
|
|
||||||
console.log(lastR, lastC, 'TO', row, col)
|
|
||||||
this.palette[row][col] = this.palette[lastR][lastC]
|
|
||||||
}
|
|
||||||
this.palette[i][j] = currentColor
|
|
||||||
this.storePalette()
|
|
||||||
}
|
|
||||||
|
|
||||||
paletteDragEnter(e: DragEvent, i: number, j: number): void
|
|
||||||
{
|
|
||||||
// TODO: Drag preview
|
|
||||||
console.log('Drag enter')
|
|
||||||
console.log(e)
|
|
||||||
console.log('' + i + ' ' + j)
|
|
||||||
}
|
|
||||||
|
|
||||||
paletteDragOver(e: DragEvent, i: number, j: number): void
|
|
||||||
{
|
|
||||||
// Only allow drag if it's not dragging onto itself
|
|
||||||
if (!(i == this.dragging.i && j == this.dragging.j)) e.preventDefault()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="sass">
|
|
||||||
#ColorPicker
|
|
||||||
position: absolute
|
|
||||||
border-radius: 20px
|
|
||||||
overflow: hidden
|
|
||||||
|
|
||||||
$cp-color: #4d4d4d
|
|
||||||
$txt-color: #cbcbcb
|
|
||||||
background-color: $cp-color
|
|
||||||
box-shadow: 0 0 10px #00000026
|
|
||||||
color: $txt-color
|
|
||||||
|
|
||||||
#title-colors
|
|
||||||
margin: 8px 0
|
|
||||||
font-size: 1.2em
|
|
||||||
padding: 0 15px
|
|
||||||
|
|
||||||
div.close
|
|
||||||
font-size: 10px
|
|
||||||
margin-right: 10px
|
|
||||||
|
|
||||||
div.text
|
|
||||||
flex-grow: 1
|
|
||||||
text-align: left
|
|
||||||
user-select: none
|
|
||||||
|
|
||||||
input
|
|
||||||
background-color: lighten($cp-color, 6)
|
|
||||||
font-family: monospace
|
|
||||||
color: $txt-color
|
|
||||||
border: none
|
|
||||||
padding: 0 10px
|
|
||||||
width: 60px
|
|
||||||
text-align: center
|
|
||||||
border-radius: 8px
|
|
||||||
transition: all 0.25s ease
|
|
||||||
|
|
||||||
input:focus-visible
|
|
||||||
outline: none
|
|
||||||
background-color: lighten($cp-color, 10)
|
|
||||||
|
|
||||||
.vc-colorpicker
|
|
||||||
width: 300px
|
|
||||||
background-color: transparent
|
|
||||||
box-shadow: none
|
|
||||||
padding-bottom: 0
|
|
||||||
border-radius: 0
|
|
||||||
|
|
||||||
.vc-colorpicker--container
|
|
||||||
padding: 0 3px
|
|
||||||
|
|
||||||
.vc-chrome-colorPicker, .vc-chrome-colorPicker-body
|
|
||||||
background-color: transparent
|
|
||||||
|
|
||||||
.vc-display
|
|
||||||
display: none
|
|
||||||
|
|
||||||
.vc-saturation, .vc-saturation__white, .vc-saturation__black
|
|
||||||
border-radius: 5px
|
|
||||||
|
|
||||||
.vc-saturation
|
|
||||||
height: 200px
|
|
||||||
|
|
||||||
.vc-chrome-colorPicker-body
|
|
||||||
margin-left: 10px
|
|
||||||
margin-right: 10px
|
|
||||||
|
|
||||||
#palette
|
|
||||||
width: 300px
|
|
||||||
|
|
||||||
// Transparency texture
|
|
||||||
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAIAAADZF8uwAAAAGUlEQVQYV2M4gwH+YwCGIasIUwhT25BVBADtzYNYrHvv4gAAAABJRU5ErkJggg==)
|
|
||||||
background-repeat: repeat
|
|
||||||
|
|
||||||
.row
|
|
||||||
width: 100%
|
|
||||||
display: flex
|
|
||||||
|
|
||||||
.color:first-child
|
|
||||||
border-left: none
|
|
||||||
|
|
||||||
.row:first-child .color
|
|
||||||
border-top: none
|
|
||||||
|
|
||||||
.color
|
|
||||||
width: 30px
|
|
||||||
height: 30px
|
|
||||||
box-sizing: border-box
|
|
||||||
border-left: 1px solid $cp-color
|
|
||||||
border-top: 1px solid $cp-color
|
|
||||||
flex-grow: 1
|
|
||||||
|
|
||||||
</style>
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div id="Projects">
|
|
||||||
<MyColorPicker v-model:color="color"></MyColorPicker>
|
|
||||||
<button @click="log"></button>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts">
|
|
||||||
import {Options, Vue} from 'vue-class-component';
|
|
||||||
import MyColorPicker from "@/components/color/ColorPicker.vue";
|
|
||||||
|
|
||||||
@Options({components: {MyColorPicker}})
|
|
||||||
export default class Projects extends Vue
|
|
||||||
{
|
|
||||||
color = '#ffffff'
|
|
||||||
|
|
||||||
log(): void
|
|
||||||
{
|
|
||||||
console.log(this.color)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="sass" scoped>
|
|
||||||
|
|
||||||
</style>
|
|
||||||
Reference in New Issue
Block a user