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=",
|
"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",
|
||||||
|
@ -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",
|
||||||
|
Binary file not shown.
Binary file not shown.
@ -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);
|
|
||||||
}
|
|
@ -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 {
|
||||||
|
@ -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: '阿里汉仪智能黑体' },
|
|
||||||
]
|
]
|
@ -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)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user