Skip to content

Commit

Permalink
v1.0.0 alpha release!
Browse files Browse the repository at this point in the history
  • Loading branch information
cangshudada007 committed Mar 2, 2021
1 parent de62750 commit ebfd207
Show file tree
Hide file tree
Showing 16 changed files with 483 additions and 65 deletions.
3 changes: 2 additions & 1 deletion example/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ import 'react-app-polyfill/ie11';
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import './index.less';
import KeyBoard from '../src/index';
import "../dist/keyboard.min.css"
import KeyBoard from '../dist';

const App = () => {
return (
Expand Down
32 changes: 17 additions & 15 deletions src/components/default/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,17 @@ import {
NUMBER_CODE,
SYMBOL_CODE,
} from '../../constants/key_code';
import { KeyBoardContext } from '../..';
import { KeyBoardContext, IKeyCode } from '../..';
import useEventEmitter from '../../hooks/useEventEmitter';

export interface IProps {
change: (value: string) => void;
trigger: (parmas: Record<'data' | 'type', string>) => void;
trigger: (parmas: IKeyCode) => void;
translate: (value: string) => void;
}

// 最后一行按钮列表
const defaultLineList: Record<'data' | 'type', string>[] = [
const defaultLineList: IKeyCode[] = [
{
data: '.?123',
type: 'change2num',
Expand All @@ -42,7 +42,10 @@ const defaultLineList: Record<'data' | 'type', string>[] = [
},
];

const DefaultBoard = (props: IProps, ref: React.MutableRefObject<any>) => {
// 上一次存的val值
let oldVal: string = '';

const DefaultBoard = (props: IProps, ref: any) => {
const { translate, trigger, change } = props;
const { modeList, handApi, closeKeyBoard } = useContext(KeyBoardContext);
// 键盘列表
Expand All @@ -52,7 +55,7 @@ const DefaultBoard = (props: IProps, ref: React.MutableRefObject<any>) => {
DEFAULT_CODE.line3,
]);
// 第四行变动的键码
const [line4, setLine4] = useState<Record<'data' | 'type', string>[]>([]);
const [line4, setLine4] = useState<IKeyCode[]>([]);
// 大小写
const [isUpper, setUpperStatus] = useState(false);
// 是否显示符号键盘
Expand All @@ -61,12 +64,11 @@ const DefaultBoard = (props: IProps, ref: React.MutableRefObject<any>) => {
const [isNum, setNumberStatus] = useState(false);
// 中英文模式
const [isCn, setLanStatus] = useState(true);
// 上一次存的val值
const [oldVal, setoldVal] = useState('');

useEffect(() => {
setLine4(JSON.parse(JSON.stringify(defaultLineList)));

// 判定是否存在手写
if (modeList.find(mode => mode === 'handwrite') && handApi) {
setLine4(dataSource => {
dataSource.splice(2, 0, {
Expand All @@ -79,36 +81,36 @@ const DefaultBoard = (props: IProps, ref: React.MutableRefObject<any>) => {

// 清空上一次储存的值
useEventEmitter.on('resultReset', () => {
setoldVal('');
oldVal = '';
});
}, []);

// 暴露给父组件的子组件方法
useImperativeHandle(ref, () => {
return {
_keyButtonClick(parmas: Record<'data' | 'type', string>) {
_keyButtonClick(parmas: IKeyCode) {
keyButtonClick(parmas);
},
};
});

/**
* @description 按钮点击事件
* @param {(Record<'data' | 'type', string>)} { data, type }
* @param {IKeyCode} { data, type }
*/
function keyButtonClick({ data, type }: Record<'data' | 'type', string>) {
function keyButtonClick({ data, type }: IKeyCode) {
switch (type) {
// 关闭
case 'close':
{
setoldVal('');
oldVal = '';
closeKeyBoard();
}
break;
// 大小写
case 'upper':
{
setoldVal('');
oldVal = '';
setUpperStatus(!isUpper);
}
break;
Expand Down Expand Up @@ -181,7 +183,7 @@ const DefaultBoard = (props: IProps, ref: React.MutableRefObject<any>) => {
{
// 如果是中文模式只删存好的字段
if (isCn && type === 'delete' && oldVal) {
setoldVal(oldVal.substr(0, oldVal.length - 1));
oldVal = oldVal.substr(0, oldVal.length - 1);
translate(oldVal);
} else {
if (type === 'handwrite') {
Expand All @@ -200,7 +202,7 @@ const DefaultBoard = (props: IProps, ref: React.MutableRefObject<any>) => {
// 中文需要转
if (isCn && !isNum && !isSymbol) {
translate(oldVal + data);
setoldVal(oldVal + data);
oldVal = oldVal + data;
} else {
// 英文直接输出
change(data);
Expand Down
211 changes: 202 additions & 9 deletions src/components/handWrite/handPaintBoard.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,147 @@
import React, { useRef, useState, useEffect } from 'react';

import { KeyBoardContext } from '../..';
import useEventEmitter from '../../hooks/useEventEmitter';
import React, { useRef, useState, useEffect, useContext } from 'react';
import { getWordFromHandWrite } from '../../serve';
export interface IProps {
lib: 'CN' | 'EN';
}

// canvas上下文
let ctx: CanvasRenderingContext2D | null | undefined;
// 是否按下
let isMouseDown = false,
x: number = 0, // 当前canvas相距左上角x
y: number = 0, // 当前canvas相距左上角y
oldX: number = 0, // 当前canvas相距左上角x
oldY: number = 0, // 当前canvas相距左上角y
clickX: number[] = [], // 轨迹X
clickY: number[] = [], // 轨迹Y
clickC: number[] = []; // 轨迹标志位,为1则是终点
// 定时器id
let timer: NodeJS.Timeout | undefined = undefined;

const HandBoard: React.FC<IProps> = props => {
const paintRef: React.RefObject<HTMLCanvasElement> = useRef(null);
const [width, setWidth] = useState(0);
const [height, setHeight] = useState(0);
// canvas dom
const canvas: React.RefObject<HTMLCanvasElement> = useRef(null);
const [width, setWidth] = useState(500); // 宽
const [height, setHeight] = useState(500); // 高
const { color, transitionTime } = useContext(KeyBoardContext);

useEffect(() => {
ctx = canvas.current?.getContext('2d');
paintBoardInit();
useEventEmitter.on('updateBound', () => {
updateBound();
});

return () => {
window.removeEventListener('transitionend', updateBound);
window.removeEventListener('animationend', updateBound);
window.removeEventListener('resize', updateBound);
window.removeEventListener('scroll', updateBound);
useEventEmitter.remove('updateBound');
};
}, []);

/**
* @description 面板初始化
*/
function paintBoardInit() {
reload();
// 此处兼容CSSTransition动画过程之前计算
setTimeout(() => {
updateBound();
}, transitionTime);
window.addEventListener('transitionend', updateBound);
window.addEventListener('animationend', updateBound);
window.addEventListener('resize', updateBound);
window.addEventListener('scroll', updateBound);
}

/**
* @description 更新尺寸以及位置
*/
function updateBound() {
if (!document.querySelector('.paint-board')) return;
const bound = document
.querySelector('.paint-board')
?.getBoundingClientRect();
// 设置距离左上角坐标
if (bound) {
x = bound.x;
y = bound.y;
}
// 设置距离宽高
setWidth(
parseFloat(
window.getComputedStyle(
document.querySelector('.paint-board') as Element
).width
)
);
setHeight(
parseFloat(
window.getComputedStyle(
document.querySelector('.paint-board') as Element
).height
)
);
}

/**
* @description canvas重置
*/
function reload() {
if (!canvas || !ctx) return;
clickX = [];
clickY = [];
clickC = [];
ctx.clearRect(0, 0, width, height);
}

/**
* @description 获取x坐标
* @param {(React.TouchEvent<HTMLCanvasElement>
* | React.MouseEvent<HTMLCanvasElement, MouseEvent>)} event
*/
function getCx(
event:
| React.TouchEvent<HTMLCanvasElement>
| React.MouseEvent<HTMLCanvasElement, MouseEvent>
): number {
// mouse事件
if (event.type.includes('mouse')) {
const _event = event as React.MouseEvent<HTMLCanvasElement, MouseEvent>;
return Math.floor(_event.clientX - x);
} else if (event.type.includes('touch')) {
// touch事件
const _event = event as React.TouchEvent<HTMLCanvasElement>;
return Math.floor(_event.targetTouches[0].clientX - x);
}
return 0;
}

/**
* @description 获取y坐标
* @param {(React.TouchEvent<HTMLCanvasElement>
* | React.MouseEvent<HTMLCanvasElement, MouseEvent>)} event
*/
function getCy(
event:
| React.TouchEvent<HTMLCanvasElement>
| React.MouseEvent<HTMLCanvasElement, MouseEvent>
): number {
// mouse事件
if (event.type.includes('mouse')) {
const _event = event as React.MouseEvent<HTMLCanvasElement, MouseEvent>;
return Math.floor(_event.clientY - y);
} else if (event.type.includes('touch')) {
// touch事件
const _event = event as React.TouchEvent<HTMLCanvasElement>;
return Math.floor(_event.targetTouches[0].clientY - y);
}
return 0;
}

/**
* @description 鼠标按下
Expand All @@ -18,7 +152,16 @@ const HandBoard: React.FC<IProps> = props => {
event:
| React.TouchEvent<HTMLCanvasElement>
| React.MouseEvent<HTMLCanvasElement, MouseEvent>
) {}
) {
if (!ctx) return;
isMouseDown = true;
const cx = getCx(event);
const cy = getCy(event);
timer && clearTimeout(timer);
oldX = cx;
oldY = cy;
ctx.beginPath();
}

/**
* @description 鼠标移动
Expand All @@ -29,17 +172,67 @@ const HandBoard: React.FC<IProps> = props => {
event:
| React.TouchEvent<HTMLCanvasElement>
| React.MouseEvent<HTMLCanvasElement, MouseEvent>
) {}
) {
if (!ctx) return;

// mouse事件 阻止默认事件 touch事件不需要 详见https://developer.mozilla.org/zh-CN/docs/Web/API/EventTarget/addEventListener
if (event.type.includes('mouse')) {
event.preventDefault();
}

if (isMouseDown) {
const cx = getCx(event);
const cy = getCy(event);
clickX.push(cx);
clickY.push(cy);
clickC.push(0);
//画图
ctx.strokeStyle = color;
ctx.fillStyle = color;
ctx.lineWidth = 4;
ctx.lineCap = 'round';
ctx.moveTo(oldX, oldY);
ctx.lineTo(cx, cy);
ctx.stroke();
oldX = cx;
oldY = cy;
}
}

/**
* @description 鼠标松开
*/
function mouseup() {}
function mouseup() {
if (isMouseDown) {
isMouseDown = false;
timer = setTimeout(() => {
reload();
}, 1500);
//标记最后一点为终点
clickC.pop();
clickC.push(1);
getWords();
}
}

/**
* @description 获取文字
*/
async function getWords() {
const { data } = await getWordFromHandWrite(
clickX,
clickY,
clickC,
props.lib
);

useEventEmitter.emit('getWordsFromServer', data?.v || '');
}

return (
<div className="paint-board">
<canvas
ref={paintRef}
ref={canvas}
width={width}
height={height}
onTouchStart={down}
Expand Down
1 change: 0 additions & 1 deletion src/components/handWrite/handwrite.less
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
height: 450px;
background: #ededed;
border-radius: 30px;

canvas {
width: 100%;
height: 100%;
Expand Down

0 comments on commit ebfd207

Please sign in to comment.