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> </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>

View File

@ -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: {

View File

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

View File

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

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