mirror of
https://github.com/pipipi-pikachu/PPTist.git
synced 2025-04-15 02:20:00 +08:00
feat: ColorPicker 添加取色吸管(#78)
This commit is contained in:
parent
02224738af
commit
90b28454e2
5
package-lock.json
generated
5
package-lock.json
generated
@ -8391,6 +8391,11 @@
|
||||
"integrity": "sha1-e15vfmZen7QfMAB+2eDUHpf7IUA=",
|
||||
"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": {
|
||||
"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",
|
||||
|
@ -19,6 +19,7 @@
|
||||
"dexie": "^3.0.3",
|
||||
"file-saver": "^2.0.5",
|
||||
"hfmath": "0.0.2",
|
||||
"html-to-image": "^1.9.0",
|
||||
"lodash": "^4.17.20",
|
||||
"mitt": "^3.0.0",
|
||||
"pinia": "^2.0.11",
|
||||
|
Binary file not shown.
Binary file not shown.
@ -26,10 +26,6 @@
|
||||
font-family: '素材集市康康体';
|
||||
src: url(../fonts/素材集市康康体.ttf);
|
||||
}
|
||||
@font-face {
|
||||
font-family: '联盟起艺卢帅正锐黑体';
|
||||
src: url(../fonts/联盟起艺卢帅正锐黑体.ttf);
|
||||
}
|
||||
@font-face {
|
||||
font-family: '素材集市酷方体';
|
||||
src: url(../fonts/素材集市酷方体.ttf);
|
||||
@ -41,8 +37,4 @@
|
||||
@font-face {
|
||||
font-family: '锐字真言体';
|
||||
src: url(../fonts/锐字真言体.ttf);
|
||||
}
|
||||
@font-face {
|
||||
font-family: '阿里汉仪智能黑体';
|
||||
src: url(../fonts/阿里汉仪智能黑体.ttf);
|
||||
}
|
@ -19,7 +19,8 @@
|
||||
</div>
|
||||
|
||||
<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 class="picker-presets">
|
||||
@ -74,6 +75,7 @@
|
||||
import { computed, defineComponent, onMounted, ref, watch } from 'vue'
|
||||
import tinycolor, { ColorFormats } from 'tinycolor2'
|
||||
import { debounce } from 'lodash'
|
||||
import { toCanvas } from 'html-to-image'
|
||||
|
||||
import Alpha from './Alpha.vue'
|
||||
import Checkboard from './Checkboard.vue'
|
||||
@ -203,6 +205,72 @@ export default defineComponent({
|
||||
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 {
|
||||
themeColors,
|
||||
standardColors,
|
||||
@ -213,6 +281,7 @@ export default defineComponent({
|
||||
changeColor,
|
||||
selectPresetColor,
|
||||
recentColors,
|
||||
pickColor,
|
||||
}
|
||||
},
|
||||
})
|
||||
@ -268,7 +337,23 @@ export default defineComponent({
|
||||
}
|
||||
|
||||
.picker-field {
|
||||
display: flex;
|
||||
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 {
|
||||
|
@ -37,9 +37,7 @@ export const WEB_FONTS = [
|
||||
{ label: '站酷快乐体', value: '站酷快乐体' },
|
||||
{ label: '字制区喜脉体', value: '字制区喜脉体' },
|
||||
{ label: '素材集市康康体', value: '素材集市康康体' },
|
||||
{ label: '联盟起艺卢帅正锐黑体', value: '联盟起艺卢帅正锐黑体' },
|
||||
{ label: '素材集市酷方体', value: '素材集市酷方体' },
|
||||
{ label: '途牛类圆体', value: '途牛类圆体' },
|
||||
{ label: '锐字真言体', value: '锐字真言体' },
|
||||
{ label: '阿里汉仪智能黑体', value: '阿里汉仪智能黑体' },
|
||||
]
|
@ -86,6 +86,7 @@ import {
|
||||
VolumeSmall,
|
||||
VideoTwo,
|
||||
Formula,
|
||||
ElectronicPen,
|
||||
} from '@icon-park/vue-next'
|
||||
|
||||
export default {
|
||||
@ -195,6 +196,7 @@ export default {
|
||||
app.component('IconLogout', Logout)
|
||||
app.component('IconClear', Clear)
|
||||
app.component('IconFolderClose', FolderClose)
|
||||
app.component('IconElectronicPen', ElectronicPen)
|
||||
|
||||
// 视频播放器
|
||||
app.component('IconPause', Pause)
|
||||
|
Loading…
x
Reference in New Issue
Block a user