fix: coler picker support touch (#4477)

* fix: coler picker support touch

* fix: update

* fix: add getClientXY util

* fix: move getClientXY to util/dom
This commit is contained in:
kooriookami 2021-11-22 17:01:09 +08:00 committed by GitHub
parent 900d62a77e
commit 94e0421623
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 59 additions and 10 deletions

View File

@ -21,11 +21,12 @@ const _mount = (template: string, data: () => { [key: string]: any }) => {
type ColorPickerVM = ComponentPublicInstance<{
handleClick: (opt: {
target: Nullable<HTMLElement>
type: string
clientX: number
clientY: number
}) => void
thumbTop: number
handleDrag: (opt: { clientX: number; clientY: number }) => void
handleDrag: (opt: { type: string; clientX: number; clientY: number }) => void
}>
describe('Color-picker', () => {
@ -188,6 +189,7 @@ describe('Color-picker', () => {
.mockReturnValue(4)
;(hueSlideWrapper.vm as ColorPickerVM).handleClick({
target: null,
type: 'mouseup',
clientX: 0,
clientY: 100,
})
@ -229,6 +231,7 @@ describe('Color-picker', () => {
.mockReturnValue(4)
;(hueSlideWrapper.vm as ColorPickerVM).handleClick({
target: null,
type: 'mouseup',
clientX: 0,
clientY: 100,
})
@ -268,6 +271,7 @@ describe('Color-picker', () => {
.mockReturnValue(4)
;(alphaWrapper.vm as ColorPickerVM).handleClick({
target: null,
type: 'mouseup',
clientX: 50,
clientY: 0,
})
@ -289,7 +293,11 @@ describe('Color-picker', () => {
await wrapper.find('.el-color-picker__trigger').trigger('click')
const colorPickerWrapper = wrapper.findComponent(ColorPicker)
const svPanelWrapper = colorPickerWrapper.findComponent({ ref: 'svPanel' })
;(svPanelWrapper.vm as ColorPickerVM).handleDrag({ clientX: 0, clientY: 0 })
;(svPanelWrapper.vm as ColorPickerVM).handleDrag({
type: 'mousemove',
clientX: 0,
clientY: 0,
})
wrapper.vm.$nextTick(() => {
expect(wrapper.vm.color._saturation !== 50).toBeTruthy()
expect(wrapper.vm.color._value !== 50).toBeTruthy()
@ -404,6 +412,7 @@ describe('Color-picker', () => {
.mockReturnValue(4)
;(hueSlideWrapper.vm as ColorPickerVM).handleClick({
target: null,
type: 'mouseup',
clientX: 0,
clientY: 1000,
})

View File

@ -28,6 +28,7 @@ import {
getCurrentInstance,
shallowRef,
} from 'vue'
import { getClientXY } from '@element-plus/utils/dom'
import draggable from '../draggable'
import type { PropType } from 'vue'
@ -112,9 +113,10 @@ export default defineComponent({
function handleDrag(event) {
const el = instance.vnode.el as HTMLElement
const rect = el.getBoundingClientRect()
const { clientX, clientY } = getClientXY(event)
if (!props.vertical) {
let left = event.clientX - rect.left
let left = clientX - rect.left
left = Math.max(thumb.value.offsetWidth / 2, left)
left = Math.min(left, rect.width - thumb.value.offsetWidth / 2)
@ -127,7 +129,7 @@ export default defineComponent({
)
)
} else {
let top = event.clientY - rect.top
let top = clientY - rect.top
top = Math.max(thumb.value.offsetHeight / 2, top)
top = Math.min(top, rect.height - thumb.value.offsetHeight / 2)

View File

@ -21,6 +21,7 @@ import {
getCurrentInstance,
defineComponent,
} from 'vue'
import { getClientXY } from '@element-plus/utils/dom'
import draggable from '../draggable'
import type { PropType } from 'vue'
@ -56,6 +57,7 @@ export default defineComponent({
update()
}
)
// methods
function handleClick(event: Event) {
const target = event.target
@ -64,13 +66,15 @@ export default defineComponent({
handleDrag(event)
}
}
function handleDrag(event) {
const el = instance.vnode.el as HTMLElement
const rect = el.getBoundingClientRect()
const { clientX, clientY } = getClientXY(event)
let hue
if (!props.vertical) {
let left = event.clientX - rect.left
let left = clientX - rect.left
left = Math.min(left, rect.width - thumb.value.offsetWidth / 2)
left = Math.max(thumb.value.offsetWidth / 2, left)
@ -80,7 +84,7 @@ export default defineComponent({
360
)
} else {
let top = event.clientY - rect.top
let top = clientY - rect.top
top = Math.min(top, rect.height - thumb.value.offsetHeight / 2)
top = Math.max(thumb.value.offsetHeight / 2, top)
@ -92,6 +96,7 @@ export default defineComponent({
}
props.color.set('hue', hue)
}
function getThumbLeft() {
const el = instance.vnode.el
@ -114,10 +119,12 @@ export default defineComponent({
(hue * (el.offsetHeight - thumb.value.offsetHeight / 2)) / 360
)
}
function update() {
thumbLeft.value = getThumbLeft()
thumbTop.value = getThumbTop()
}
// mounded
onMounted(() => {
const dragConfig = {

View File

@ -28,6 +28,7 @@ import {
getCurrentInstance,
onMounted,
} from 'vue'
import { getClientXY } from '@element-plus/utils/dom'
import draggable from '../draggable'
import type { PropType } from 'vue'
@ -54,6 +55,7 @@ export default defineComponent({
const value = props.color.get('value')
return { hue, value }
})
// methods
function update() {
const saturation = props.color.get('saturation')
@ -71,9 +73,10 @@ export default defineComponent({
function handleDrag(event) {
const el = instance.vnode.el
const rect = el.getBoundingClientRect()
const { clientX, clientY } = getClientXY(event)
let left = event.clientX - rect.left
let top = event.clientY - rect.top
let left = clientX - rect.left
let top = clientY - rect.top
left = Math.max(0, left)
left = Math.min(left, rect.width)
@ -87,6 +90,7 @@ export default defineComponent({
value: 100 - (top / rect.height) * 100,
})
}
// watch
watch(
() => colorValue.value,

View File

@ -19,6 +19,8 @@ export default function (element: HTMLElement, options: IOptions) {
const upFn = function (event: Event) {
off(document, 'mousemove', moveFn)
off(document, 'mouseup', upFn)
off(document, 'touchmove', moveFn)
off(document, 'touchend', upFn)
document.onselectstart = null
document.ondragstart = null
@ -27,15 +29,21 @@ export default function (element: HTMLElement, options: IOptions) {
options.end?.(event)
}
on(element, 'mousedown', function (event) {
const downFn = function (event: Event) {
if (isDragging) return
event.preventDefault()
document.onselectstart = () => false
document.ondragstart = () => false
on(document, 'mousemove', moveFn)
on(document, 'mouseup', upFn)
on(document, 'touchmove', moveFn)
on(document, 'touchend', upFn)
isDragging = true
options.start?.(event)
})
}
on(element, 'mousedown', downFn)
on(element, 'touchstart', downFn)
}

View File

@ -234,3 +234,22 @@ export const getOffsetTopDistance = (
}
export const stop = (e: Event) => e.stopPropagation()
export const getClientXY = (event: MouseEvent | TouchEvent) => {
let clientX: number
let clientY: number
if (event.type === 'touchend') {
clientY = (event as TouchEvent).changedTouches[0].clientY
clientX = (event as TouchEvent).changedTouches[0].clientX
} else if (event.type.startsWith('touch')) {
clientY = (event as TouchEvent).touches[0].clientY
clientX = (event as TouchEvent).touches[0].clientX
} else {
clientY = (event as MouseEvent).clientY
clientX = (event as MouseEvent).clientX
}
return {
clientX,
clientY,
}
}