feat: draw 分笔画绘制代码完成
This commit is contained in:
parent
577466b645
commit
978dd5ba3e
|
@ -14,10 +14,10 @@
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body style="margin: 0">
|
<body style="margin: 0">
|
||||||
|
<div id='drawArea'></div>
|
||||||
<div id='comment'>
|
<div id='comment'>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div id='drawArea'></div>
|
<script src="./bundle.js"></script>
|
||||||
<script src="./bundle.js"></script>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
|
@ -29,10 +29,10 @@ import '../src/cnchar/plugin/radical';
|
||||||
// import '../npm/idiom/cnchar.idiom.min.js';
|
// import '../npm/idiom/cnchar.idiom.min.js';
|
||||||
// import '../npm/xhy/cnchar.xhy.min.js';
|
// import '../npm/xhy/cnchar.xhy.min.js';
|
||||||
// import '../npm/radical/cnchar.radical.min.js';
|
// import '../npm/radical/cnchar.radical.min.js';
|
||||||
import initComment from 'tc-comment';
|
// import initComment from 'tc-comment';
|
||||||
initComment({
|
// initComment({
|
||||||
el: '#app'
|
// el: '#comment'
|
||||||
});
|
// });
|
||||||
|
|
||||||
console.log(cnchar);
|
console.log(cnchar);
|
||||||
|
|
||||||
|
@ -119,6 +119,33 @@ cnchar.draw('中国', {
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface Window {
|
||||||
|
aaa: any;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
window.aaa = cnchar.draw('你好九', {
|
||||||
|
type: cnchar.draw.TYPE.ANIMATION,
|
||||||
|
style: {
|
||||||
|
radicalColor: '#44f',
|
||||||
|
backgroundColor: '#ccc'
|
||||||
|
},
|
||||||
|
animation: {
|
||||||
|
animateComplete () {
|
||||||
|
console.log('animateComplete');
|
||||||
|
},
|
||||||
|
loopAnimate: true,
|
||||||
|
autoAnimate: false, // false 时点击出发animate 只能触发一次
|
||||||
|
// stepByStep: false
|
||||||
|
},
|
||||||
|
test: {
|
||||||
|
onTestStatus (d: any) {
|
||||||
|
console.log(d);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// cnchar.draw('你好', {
|
// cnchar.draw('你好', {
|
||||||
// type: cnchar.draw.TYPE.ANIMATION,
|
// type: cnchar.draw.TYPE.ANIMATION,
|
||||||
// style: {
|
// style: {
|
||||||
|
|
|
@ -26,4 +26,8 @@ export default class HanziWriter {
|
||||||
x: number;
|
x: number;
|
||||||
y: number;
|
y: number;
|
||||||
};
|
};
|
||||||
|
pauseAnimation(): void;
|
||||||
|
resumeAnimation(): void;
|
||||||
|
animateStroke(strokeNum: number, options: {onComplete(): void}): void;
|
||||||
|
V: any;
|
||||||
}
|
}
|
|
@ -30,9 +30,8 @@ export declare interface IWriter {
|
||||||
text: Array<string>;
|
text: Array<string>;
|
||||||
writers: Array<HanziWriter>;
|
writers: Array<HanziWriter>;
|
||||||
init (): void;
|
init (): void;
|
||||||
animate (complete: IComplete): void;
|
startAnimation(): boolean;
|
||||||
animateStart(): void;
|
drawNextStroke(onComplete?: ()=>void): boolean;
|
||||||
loopAnimate(): void;
|
pauseAnimation(): void;
|
||||||
_animateSingle (index: number, complete: IComplete): void;
|
resumeAnimation(): void;
|
||||||
_animateStep (index: number, complete: IComplete): void;
|
|
||||||
}
|
}
|
|
@ -0,0 +1,171 @@
|
||||||
|
/*
|
||||||
|
* @Author: theajack
|
||||||
|
* @Date: 2021-08-05 23:05:21
|
||||||
|
* @LastEditor: theajack
|
||||||
|
* @LastEditTime: 2021-08-06 00:30:19
|
||||||
|
* @Description: Coding something
|
||||||
|
* @FilePath: \cnchar\src\cnchar\plugin\draw\animation-stroke.ts
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {IComplete, IWriter} from 'src/cnchar-types/plugin/draw';
|
||||||
|
import {IDrawOption} from 'src/cnchar-types/plugin/draw/common';
|
||||||
|
import HanziWriter from 'src/cnchar-types/plugin/draw/hanzi-writer';
|
||||||
|
|
||||||
|
const DRAW_MODE = {
|
||||||
|
INITIAL: 0,
|
||||||
|
ANIMATION: 1,
|
||||||
|
STROKE: 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
export class AnimationWriter {
|
||||||
|
writer: IWriter;
|
||||||
|
|
||||||
|
currentCharIndex: number;
|
||||||
|
currentStrokeIndex: number;
|
||||||
|
|
||||||
|
drawMode: number;
|
||||||
|
isPaused: boolean;
|
||||||
|
option: IDrawOption;
|
||||||
|
writers: Array<HanziWriter>;
|
||||||
|
strokeDrawLocked: boolean;
|
||||||
|
|
||||||
|
constructor (writer: IWriter) {
|
||||||
|
this.writer = writer;
|
||||||
|
this.option = writer.option;
|
||||||
|
this.writers = writer.writers;
|
||||||
|
this.isPaused = false;
|
||||||
|
this.drawMode = DRAW_MODE.INITIAL;
|
||||||
|
this.currentCharIndex = 0;
|
||||||
|
this.currentStrokeIndex = 0;
|
||||||
|
this.strokeDrawLocked = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _getCurrentCharStrokeNumber () {
|
||||||
|
return this.writers[this.currentCharIndex].V.strokes.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _isStepMode () {
|
||||||
|
return this.option.stepByStep;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _animate (complete: IComplete = () => {}) {
|
||||||
|
if (this._isStepMode()) { // 汉字之间连续绘制{
|
||||||
|
if (this.option.showCharacter === false) {
|
||||||
|
this.writers.forEach(writer => {
|
||||||
|
writer.hideCharacter();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
this._animateStep(0, complete);
|
||||||
|
} else { // 汉字一起绘制,笔画最多的绘制完成才算全部绘制完成
|
||||||
|
let index = 0;
|
||||||
|
for (let i = 0; i < this.writers.length; i++) {
|
||||||
|
this._animateSingle(i, () => {
|
||||||
|
index++;
|
||||||
|
if (index === this.writers.length) {
|
||||||
|
complete();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
drawNextStroke (onComplete: ()=>void) {
|
||||||
|
if (this.drawMode === DRAW_MODE.ANIMATION) {
|
||||||
|
console.warn('当前为自动绘制模式');
|
||||||
|
return false;
|
||||||
|
} else if (this.drawMode === DRAW_MODE.INITIAL) {
|
||||||
|
this.drawMode = DRAW_MODE.STROKE;
|
||||||
|
}
|
||||||
|
if (this.strokeDrawLocked) {
|
||||||
|
console.warn('请等待上一步绘制完成');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
this.strokeDrawLocked = true;
|
||||||
|
if (this.currentCharIndex === 0 && this.currentStrokeIndex === 0) {
|
||||||
|
this.writers.forEach(writer => {
|
||||||
|
writer.hideCharacter();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
this.writers[this.currentCharIndex].animateStroke(this.currentStrokeIndex, {
|
||||||
|
onComplete: () => {
|
||||||
|
onComplete();
|
||||||
|
this.strokeDrawLocked = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const thisCharStrokeNumber = this._getCurrentCharStrokeNumber();
|
||||||
|
if (this.currentStrokeIndex >= thisCharStrokeNumber - 1) {
|
||||||
|
this.currentStrokeIndex = 0;
|
||||||
|
this.currentCharIndex ++;
|
||||||
|
if (this.currentCharIndex === this.writer.text.length) {
|
||||||
|
this.currentCharIndex = 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.currentStrokeIndex ++;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
start () {
|
||||||
|
if (this.drawMode !== DRAW_MODE.INITIAL) {
|
||||||
|
console.warn('当前为手动绘制模式');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
this.drawMode = DRAW_MODE.ANIMATION;
|
||||||
|
if (this.option.loopAnimate) {
|
||||||
|
this._loop();
|
||||||
|
} else {
|
||||||
|
this._animate(this.option.animateComplete);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
pause () {
|
||||||
|
if (this.isPaused || !this._isStepMode()) return;
|
||||||
|
this.isPaused = true;
|
||||||
|
|
||||||
|
this.writers[this.currentCharIndex].pauseAnimation();
|
||||||
|
}
|
||||||
|
|
||||||
|
resume () {
|
||||||
|
if (!this.isPaused || !this._isStepMode()) return;
|
||||||
|
this.isPaused = false;
|
||||||
|
|
||||||
|
this.writers[this.currentCharIndex].resumeAnimation();
|
||||||
|
}
|
||||||
|
|
||||||
|
private _loop () {
|
||||||
|
const opt = this.option;
|
||||||
|
this._animate(() => {
|
||||||
|
if (opt.animateComplete)
|
||||||
|
opt.animateComplete();
|
||||||
|
setTimeout(() => {
|
||||||
|
this._loop();
|
||||||
|
}, opt.delayBetweenStrokes);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// animate单个汉字
|
||||||
|
private _animateSingle (index: number, complete: IComplete): void {
|
||||||
|
if (index >= this.writers.length) {
|
||||||
|
complete(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.writers[index].animateCharacter({
|
||||||
|
onComplete: () => {
|
||||||
|
complete(false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
private _animateStep (index: number, complete: IComplete = () => {}): void {
|
||||||
|
this.currentCharIndex = index;
|
||||||
|
this._animateSingle(index, (end: boolean) => {
|
||||||
|
if (!end) {
|
||||||
|
setTimeout(() => {
|
||||||
|
this._animateStep(index + 1, complete);
|
||||||
|
}, this.option.delayBetweenStrokes);
|
||||||
|
} else {
|
||||||
|
complete();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,7 +3,7 @@ import {TYPE, merge, TEST_STATUS} from './default-option';
|
||||||
import {pickCnChar} from './util';
|
import {pickCnChar} from './util';
|
||||||
import {buildLinesStr} from './line';
|
import {buildLinesStr} from './line';
|
||||||
import {stroke} from './stroke';
|
import {stroke} from './stroke';
|
||||||
import {IComplete, IWriter, IWriterOption} from 'cnchar-types/plugin/draw/index';
|
import {IWriter, IWriterOption} from 'cnchar-types/plugin/draw/index';
|
||||||
import {
|
import {
|
||||||
TDrawType,
|
TDrawType,
|
||||||
IDrawOption,
|
IDrawOption,
|
||||||
|
@ -18,6 +18,7 @@ import {
|
||||||
ITestStatusData
|
ITestStatusData
|
||||||
} from 'cnchar-types/plugin/draw/common';
|
} from 'cnchar-types/plugin/draw/common';
|
||||||
import {querySelector} from './dom';
|
import {querySelector} from './dom';
|
||||||
|
import {AnimationWriter} from './animation-stroke';
|
||||||
|
|
||||||
// export const DEFAULT_WIDTH: number = 60;
|
// export const DEFAULT_WIDTH: number = 60;
|
||||||
|
|
||||||
|
@ -36,7 +37,7 @@ export class Writer implements IWriter {
|
||||||
type: TDrawType;
|
type: TDrawType;
|
||||||
text: Array<string>;
|
text: Array<string>;
|
||||||
writers: Array<HanziWriter>;
|
writers: Array<HanziWriter>;
|
||||||
animateStart: () => void;
|
animation: AnimationWriter;
|
||||||
constructor ({
|
constructor ({
|
||||||
el = 'cnchar-draw',
|
el = 'cnchar-draw',
|
||||||
text = '',
|
text = '',
|
||||||
|
@ -101,23 +102,12 @@ export class Writer implements IWriter {
|
||||||
this.el.appendChild(node);
|
this.el.appendChild(node);
|
||||||
});
|
});
|
||||||
if (this.type === TYPE.ANIMATION) {
|
if (this.type === TYPE.ANIMATION) {
|
||||||
let isStart = false;
|
this.animation = new AnimationWriter(this);
|
||||||
this.animateStart = () => {
|
|
||||||
if (isStart) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
isStart = true;
|
|
||||||
if (this.option.loopAnimate) {
|
|
||||||
this.loopAnimate();
|
|
||||||
} else {
|
|
||||||
this.animate(this.option.animateComplete);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
if (this.option.autoAnimate) {
|
if (this.option.autoAnimate) {
|
||||||
this.animateStart();
|
this.startAnimation();
|
||||||
} else {
|
} else {
|
||||||
const start = () => {
|
const start = () => {
|
||||||
this.animateStart();
|
this.startAnimation();
|
||||||
this.el.removeEventListener('click', start, false);
|
this.el.removeEventListener('click', start, false);
|
||||||
};
|
};
|
||||||
this.el.addEventListener('click', start, false);
|
this.el.addEventListener('click', start, false);
|
||||||
|
@ -148,59 +138,17 @@ export class Writer implements IWriter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
animate (complete: IComplete = () => {}) {
|
startAnimation () {
|
||||||
const opt = this.option;
|
return this.animation.start();
|
||||||
if (opt.stepByStep) { // 汉字之间连续绘制
|
|
||||||
if (opt.showCharacter === false) {
|
|
||||||
this.writers.forEach(writer => {
|
|
||||||
writer.hideCharacter();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
this._animateStep(0, complete);
|
|
||||||
} else { // 汉字一起绘制,笔画最多的绘制完成才算全部绘制完成
|
|
||||||
let index = 0;
|
|
||||||
for (let i = 0; i < this.writers.length; i++) {
|
|
||||||
this._animateSingle(i, () => {
|
|
||||||
index++;
|
|
||||||
if (index === this.writers.length) {
|
|
||||||
complete();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
loopAnimate () {
|
drawNextStroke (onComplete: ()=>void = () => {}) {
|
||||||
const opt = this.option;
|
return this.animation.drawNextStroke(onComplete);
|
||||||
this.animate(() => {
|
|
||||||
if (opt.animateComplete)
|
|
||||||
opt.animateComplete();
|
|
||||||
setTimeout(() => {
|
|
||||||
this.loopAnimate();
|
|
||||||
}, opt.delayBetweenStrokes);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
// animate单个汉字
|
pauseAnimation () {
|
||||||
_animateSingle (index: number, complete: IComplete): void {
|
this.animation.pause();
|
||||||
if (index >= this.writers.length) {
|
|
||||||
complete(true);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.writers[index].animateCharacter({
|
|
||||||
onComplete: () => {
|
|
||||||
complete(false);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
_animateStep (index: number, complete: IComplete = () => {}): void {
|
resumeAnimation () {
|
||||||
this._animateSingle(index, (end: boolean) => {
|
this.animation.resume();
|
||||||
if (!end) {
|
|
||||||
setTimeout(() => {
|
|
||||||
this._animateStep(index + 1, complete);
|
|
||||||
}, this.option.delayBetweenStrokes);
|
|
||||||
} else {
|
|
||||||
complete();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue