feat: draw 分笔画绘制代码完成

This commit is contained in:
theajack 2021-08-06 00:35:09 +08:00
parent 577466b645
commit 978dd5ba3e
6 changed files with 226 additions and 77 deletions

View File

@ -14,10 +14,10 @@
</style>
</head>
<body style="margin: 0">
<div id='drawArea'></div>
<div id='comment'>
</div>
<div id='drawArea'></div>
<script src="./bundle.js"></script>
<script src="./bundle.js"></script>
</body>
</html>

View File

@ -29,10 +29,10 @@ import '../src/cnchar/plugin/radical';
// import '../npm/idiom/cnchar.idiom.min.js';
// import '../npm/xhy/cnchar.xhy.min.js';
// import '../npm/radical/cnchar.radical.min.js';
import initComment from 'tc-comment';
initComment({
el: '#app'
});
// import initComment from 'tc-comment';
// initComment({
// el: '#comment'
// });
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('你好', {
// type: cnchar.draw.TYPE.ANIMATION,
// style: {

View File

@ -26,4 +26,8 @@ export default class HanziWriter {
x: number;
y: number;
};
pauseAnimation(): void;
resumeAnimation(): void;
animateStroke(strokeNum: number, options: {onComplete(): void}): void;
V: any;
}

View File

@ -30,9 +30,8 @@ export declare interface IWriter {
text: Array<string>;
writers: Array<HanziWriter>;
init (): void;
animate (complete: IComplete): void;
animateStart(): void;
loopAnimate(): void;
_animateSingle (index: number, complete: IComplete): void;
_animateStep (index: number, complete: IComplete): void;
startAnimation(): boolean;
drawNextStroke(onComplete?: ()=>void): boolean;
pauseAnimation(): void;
resumeAnimation(): void;
}

View File

@ -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();
}
});
}
}

View File

@ -3,7 +3,7 @@ import {TYPE, merge, TEST_STATUS} from './default-option';
import {pickCnChar} from './util';
import {buildLinesStr} from './line';
import {stroke} from './stroke';
import {IComplete, IWriter, IWriterOption} from 'cnchar-types/plugin/draw/index';
import {IWriter, IWriterOption} from 'cnchar-types/plugin/draw/index';
import {
TDrawType,
IDrawOption,
@ -18,6 +18,7 @@ import {
ITestStatusData
} from 'cnchar-types/plugin/draw/common';
import {querySelector} from './dom';
import {AnimationWriter} from './animation-stroke';
// export const DEFAULT_WIDTH: number = 60;
@ -36,7 +37,7 @@ export class Writer implements IWriter {
type: TDrawType;
text: Array<string>;
writers: Array<HanziWriter>;
animateStart: () => void;
animation: AnimationWriter;
constructor ({
el = 'cnchar-draw',
text = '',
@ -101,23 +102,12 @@ export class Writer implements IWriter {
this.el.appendChild(node);
});
if (this.type === TYPE.ANIMATION) {
let isStart = false;
this.animateStart = () => {
if (isStart) {
return;
}
isStart = true;
if (this.option.loopAnimate) {
this.loopAnimate();
} else {
this.animate(this.option.animateComplete);
}
};
this.animation = new AnimationWriter(this);
if (this.option.autoAnimate) {
this.animateStart();
this.startAnimation();
} else {
const start = () => {
this.animateStart();
this.startAnimation();
this.el.removeEventListener('click', start, false);
};
this.el.addEventListener('click', start, false);
@ -148,59 +138,17 @@ export class Writer implements IWriter {
}
}
}
animate (complete: IComplete = () => {}) {
const opt = this.option;
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();
}
});
}
}
startAnimation () {
return this.animation.start();
}
loopAnimate () {
const opt = this.option;
this.animate(() => {
if (opt.animateComplete)
opt.animateComplete();
setTimeout(() => {
this.loopAnimate();
}, opt.delayBetweenStrokes);
});
drawNextStroke (onComplete: ()=>void = () => {}) {
return this.animation.drawNextStroke(onComplete);
}
// animate单个汉字
_animateSingle (index: number, complete: IComplete): void {
if (index >= this.writers.length) {
complete(true);
return;
}
this.writers[index].animateCharacter({
onComplete: () => {
complete(false);
}
});
pauseAnimation () {
this.animation.pause();
}
_animateStep (index: number, complete: IComplete = () => {}): void {
this._animateSingle(index, (end: boolean) => {
if (!end) {
setTimeout(() => {
this._animateStep(index + 1, complete);
}, this.option.delayBetweenStrokes);
} else {
complete();
}
});
resumeAnimation () {
this.animation.resume();
}
}