feat: ColorPicker 添加取色吸管(#78)

This commit is contained in:
pipipi-pikachu 2022-03-18 22:17:43 +08:00
parent 02224738af
commit 90b28454e2
8 changed files with 94 additions and 11 deletions

5
package-lock.json generated
View File

@ -8391,6 +8391,11 @@
"integrity": "sha1-e15vfmZen7QfMAB+2eDUHpf7IUA=", "integrity": "sha1-e15vfmZen7QfMAB+2eDUHpf7IUA=",
"dev": true "dev": true
}, },
"html-to-image": {
"version": "1.9.0",
"resolved": "https://registry.npmmirror.com/html-to-image/-/html-to-image-1.9.0.tgz",
"integrity": "sha512-9gaDCIYg62Ek07F2pBk76AHgYZ2gxq2YALU7rK3gNCqXuhu6cWzsOQqM7qGbjZiOzxGzrU1deDqZpAod2NEwbA=="
},
"html-webpack-plugin": { "html-webpack-plugin": {
"version": "3.2.0", "version": "3.2.0",
"resolved": "https://registry.npmmirror.com/html-webpack-plugin/download/html-webpack-plugin-3.2.0.tgz?cache=0&sync_timestamp=1635212553430&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2Fhtml-webpack-plugin%2Fdownload%2Fhtml-webpack-plugin-3.2.0.tgz", "resolved": "https://registry.npmmirror.com/html-webpack-plugin/download/html-webpack-plugin-3.2.0.tgz?cache=0&sync_timestamp=1635212553430&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2Fhtml-webpack-plugin%2Fdownload%2Fhtml-webpack-plugin-3.2.0.tgz",

View File

@ -19,6 +19,7 @@
"dexie": "^3.0.3", "dexie": "^3.0.3",
"file-saver": "^2.0.5", "file-saver": "^2.0.5",
"hfmath": "0.0.2", "hfmath": "0.0.2",
"html-to-image": "^1.9.0",
"lodash": "^4.17.20", "lodash": "^4.17.20",
"mitt": "^3.0.0", "mitt": "^3.0.0",
"pinia": "^2.0.11", "pinia": "^2.0.11",

View File

@ -26,10 +26,6 @@
font-family: '素材集市康康体'; font-family: '素材集市康康体';
src: url(../fonts/素材集市康康体.ttf); src: url(../fonts/素材集市康康体.ttf);
} }
@font-face {
font-family: '联盟起艺卢帅正锐黑体';
src: url(../fonts/联盟起艺卢帅正锐黑体.ttf);
}
@font-face { @font-face {
font-family: '素材集市酷方体'; font-family: '素材集市酷方体';
src: url(../fonts/素材集市酷方体.ttf); src: url(../fonts/素材集市酷方体.ttf);
@ -42,7 +38,3 @@
font-family: '锐字真言体'; font-family: '锐字真言体';
src: url(../fonts/锐字真言体.ttf); src: url(../fonts/锐字真言体.ttf);
} }
@font-face {
font-family: '阿里汉仪智能黑体';
src: url(../fonts/阿里汉仪智能黑体.ttf);
}

View File

@ -19,7 +19,8 @@
</div> </div>
<div class="picker-field"> <div class="picker-field">
<EditableInput :value="color" @colorChange="value => changeColor(value)" /> <EditableInput class="input" :value="color" @colorChange="value => changeColor(value)" />
<div class="straw" @click="pickColor()"><IconElectronicPen theme="two-tone" :fill="['#333', '#e2c2c2']" /></div>
</div> </div>
<div class="picker-presets"> <div class="picker-presets">
@ -74,6 +75,7 @@
import { computed, defineComponent, onMounted, ref, watch } from 'vue' import { computed, defineComponent, onMounted, ref, watch } from 'vue'
import tinycolor, { ColorFormats } from 'tinycolor2' import tinycolor, { ColorFormats } from 'tinycolor2'
import { debounce } from 'lodash' import { debounce } from 'lodash'
import { toCanvas } from 'html-to-image'
import Alpha from './Alpha.vue' import Alpha from './Alpha.vue'
import Checkboard from './Checkboard.vue' import Checkboard from './Checkboard.vue'
@ -203,6 +205,72 @@ export default defineComponent({
updateRecentColorsCache() updateRecentColorsCache()
} }
const pickColor = () => {
const targetRef: HTMLElement | null = document.querySelector('.canvas')
if (!targetRef) return
const maskRef = document.createElement('div')
maskRef.style.cssText = 'position: fixed; top: 0; left: 0; bottom: 0; right: 0; z-index: 9999; cursor: wait;'
document.body.appendChild(maskRef)
const colorBlockRef = document.createElement('div')
colorBlockRef.style.cssText = 'position: absolute; top: -100px; left: -100px; width: 16px; height: 16px; border: 1px solid #000; z-index: 999'
maskRef.appendChild(colorBlockRef)
const { left, top } = targetRef.getBoundingClientRect()
const filter = (node: HTMLElement) => !(node.classList && node.classList.contains('operate'))
toCanvas(targetRef, { filter, fontEmbedCSS: '' }).then(canvasRef => {
canvasRef.style.cssText = `position: absolute; top: ${top}px; left: ${left}px; cursor: crosshair;`
maskRef.style.cursor = 'default'
maskRef.appendChild(canvasRef)
const ctx = canvasRef.getContext('2d')
if (!ctx) return
let currentColor = ''
const handleMousemove = (e: MouseEvent) => {
const x = e.x
const y = e.y
const mouseX = x - left
const mouseY = y - top
const [r, g, b, a] = ctx.getImageData(mouseX, mouseY, 1, 1).data
currentColor = `rgba(${r}, ${g}, ${b}, ${(a / 255).toFixed(2)})`
colorBlockRef.style.left = x + 10 + 'px'
colorBlockRef.style.top = y + 10 + 'px'
colorBlockRef.style.backgroundColor = currentColor
}
const handleMouseleave = () => {
currentColor = ''
colorBlockRef.style.left = '-100px'
colorBlockRef.style.top = '-100px'
colorBlockRef.style.backgroundColor = ''
}
const handleMousedown = (e: MouseEvent) => {
if (currentColor && e.button === 0) {
const tColor = tinycolor(currentColor)
hue.value = tColor.toHsl().h
color.value = tColor.toRgb()
updateRecentColorsCache()
}
document.body.removeChild(maskRef)
canvasRef.removeEventListener('mousemove', handleMousemove)
canvasRef.removeEventListener('mouseleave', handleMouseleave)
window.removeEventListener('mousedown', handleMousedown)
}
canvasRef.addEventListener('mousemove', handleMousemove)
canvasRef.addEventListener('mouseleave', handleMouseleave)
window.addEventListener('mousedown', handleMousedown)
})
}
return { return {
themeColors, themeColors,
standardColors, standardColors,
@ -213,6 +281,7 @@ export default defineComponent({
changeColor, changeColor,
selectPresetColor, selectPresetColor,
recentColors, recentColors,
pickColor,
} }
}, },
}) })
@ -268,7 +337,23 @@ export default defineComponent({
} }
.picker-field { .picker-field {
display: flex;
margin-bottom: 8px; margin-bottom: 8px;
.straw {
width: 24px;
height: 24px;
margin-top: 4px;
margin-left: 4px;
display: flex;
justify-content: flex-end;
align-items: center;
font-size: 22px;
cursor: pointer;
}
.input {
flex: 1;
}
} }
.picker-presets { .picker-presets {

View File

@ -37,9 +37,7 @@ export const WEB_FONTS = [
{ label: '站酷快乐体', value: '站酷快乐体' }, { label: '站酷快乐体', value: '站酷快乐体' },
{ label: '字制区喜脉体', value: '字制区喜脉体' }, { label: '字制区喜脉体', value: '字制区喜脉体' },
{ label: '素材集市康康体', value: '素材集市康康体' }, { label: '素材集市康康体', value: '素材集市康康体' },
{ label: '联盟起艺卢帅正锐黑体', value: '联盟起艺卢帅正锐黑体' },
{ label: '素材集市酷方体', value: '素材集市酷方体' }, { label: '素材集市酷方体', value: '素材集市酷方体' },
{ label: '途牛类圆体', value: '途牛类圆体' }, { label: '途牛类圆体', value: '途牛类圆体' },
{ label: '锐字真言体', value: '锐字真言体' }, { label: '锐字真言体', value: '锐字真言体' },
{ label: '阿里汉仪智能黑体', value: '阿里汉仪智能黑体' },
] ]

View File

@ -86,6 +86,7 @@ import {
VolumeSmall, VolumeSmall,
VideoTwo, VideoTwo,
Formula, Formula,
ElectronicPen,
} from '@icon-park/vue-next' } from '@icon-park/vue-next'
export default { export default {
@ -195,6 +196,7 @@ export default {
app.component('IconLogout', Logout) app.component('IconLogout', Logout)
app.component('IconClear', Clear) app.component('IconClear', Clear)
app.component('IconFolderClose', FolderClose) app.component('IconFolderClose', FolderClose)
app.component('IconElectronicPen', ElectronicPen)
// 视频播放器 // 视频播放器
app.component('IconPause', Pause) app.component('IconPause', Pause)