Commit 348afab9 authored by liujiaxin's avatar liujiaxin

111

parent 8a5f5330
import { onHomeworkFinish, RandomInt, playAudioByUrl, loadDragonBones } from "../script/util";
import { defaultData } from "../script/defaultData";
import { assign, createMachine, interpret, actions, forwardTo, matchesState } from "../script/xstate";
const { pure , send, raise, sendParent } = actions;
class AssetCacher {
constructor(data, progress, complete) {
this.data = data;
this.obj = JSON.parse(JSON.stringify(data))
this.complete = complete;
this.progress = progress;
}
_extractResource(data) {
if (!Array.isArray(data)) {
data = Object.values(data)
}
const urls = [];
for (var item of data) {
if (typeof item === 'string' && item.startsWith('http')) {
urls.push(item);
continue
}
const us = this._extractResource(item);
for (const u of us) {
urls.push(u)
}
}
return urls
}
_replaceResource(objs, urls, assets) {
const fn = (obj) => {
Object.keys(obj).forEach(key => {
const v = obj[key];
if (typeof v == 'string' && v.startsWith('http')) {
const i = urls.indexOf(v);
if (i > -1) {
obj[key] = assets[i]
}
return
}
if (v){
this._replaceResource(v)
}
})
}
fn(objs);
return objs
}
start() {
const urls = this._extractResource(this.data);
cc.assetManager.loadAny(urls, null, this.progress, (err, data) => {
const objs = [];
for (const asset of data) {
if (asset.constructor.name === 'ImageBitmap') {
const t = new cc.Texture2D()
t.initWithData(asset);
objs.push(t);
} else if (asset.constructor.name === 'AudioBuffer') {
const clip = new cc.AudioClip()
clip._nativeAsset = asset;
objs.push(clip);
}
}
const r = this._replaceResource(JSON.parse(JSON.stringify(this.data)),urls, objs)
this.complete && this.complete();
});
}
}
cc.Class({
extends: cc.Component,
properties: {
/*ant: {
default: null,
type: cc.Node,
},
apple: {
default: null,
type: cc.Node,
},
bird: {
default: null,
type: cc.Node,
},
car: {
default: null,
type: cc.Node,
},
cat: {
default: null,
type: cc.Node,
},
cow: {
default: null,
type: cc.Node,
},
duck: {
default: null,
type: cc.Node,
},
egg: {
default: null,
type: cc.Node,
},
farmer: {
default: null,
type: cc.Node,
},
fish: {
default: null,
type: cc.Node,
},
girl: {
default: null,
type: cc.Node,
},
hen: {
default: null,
type: cc.Node,
},
house: {
default: null,
type: cc.Node,
},*/
rightAudio: {
default: null,
type: cc.AudioClip,
},
wrongAudio: {
default: null,
type: cc.AudioClip,
},
},
playAni(idx, name, times = 1) {
// const cat = cc.find(`Canvas/frame-border/ground/${node}`);
const node = this._animaNodeList[idx]
var dragonDisplay = node.getComponent(dragonBones.ArmatureDisplay);
const state = dragonDisplay.playAnimation(name, times);
return state;
},
// 生命周期 onLoad
onLoad() {
this.initSceneData();
this.initSize();
window.ccc = this;
},
_imageResList: null,
_audioResList: null,
_animaResList: null,
_animaNodeList : null,
_lastFingerPosition: null,
initSceneData() {
this._imageResList = [];
this._audioResList = [];
this._animaResList = [];
this._animaNodeList = [];
this._lastFingerPosition= {
pos: null,
dirty: false
};
},
_designSize: null, // 设计分辨率
_frameSize: null, // 屏幕分辨率
_mapScaleMin: null, // 场景中常用缩放(取大值)
_mapScaleMax: null, // 场景中常用缩放(取小值)
_cocosScale: null, // cocos 自缩放 (较少用到)
initSize() {
// 注意cc.winSize只有在适配后(修改fitHeight/fitWidth后)才能获取到正确的值,因此使用cc.getFrameSize()来获取初始的屏幕大小
let screen_size = cc.view.getFrameSize().width / cc.view.getFrameSize().height
let design_size = cc.Canvas.instance.designResolution.width / cc.Canvas.instance.designResolution.height
let f = screen_size >= design_size
cc.Canvas.instance.fitHeight = f
cc.Canvas.instance.fitWidth = !f
const frameSize = cc.view.getFrameSize();
this._frameSize = frameSize;
this._designSize = cc.view.getDesignResolutionSize();
let sx = cc.winSize.width / frameSize.width;
let sy = cc.winSize.height / frameSize.height;
this._cocosScale = Math.min(sx, sy);
sx = frameSize.width / this._designSize.width;
sy = frameSize.height / this._designSize.height;
this._mapScaleMin = Math.min(sx, sy) * this._cocosScale;
this._mapScaleMax = Math.max(sx, sy) * this._cocosScale;
},
createStateMachine(){
const check = [
{ target: '#game.end', cond: (ctx, evt) => {
console.log('[answer NEXT] check if end', ctx.questionIndex >= ctx.questionsCount - 1);
return ctx.questionIndex >= ctx.questionsCount -1
} },
{ target: 'hint' } // reenter 'hint' state
]
const QuestionState = {
id: 'question',
initial: 'hint',
states: {
hint: {
invoke: {
src: (ctx, event) => {
console.log(`[hint] play question ${ctx.questionIndex}: ${ctx.questionPlayTimes } audio`);
ctx.questionPlayTimes += 1;
return new Promise((resolve,reject) => {
playAudioByUrl(this.data.hotZoneItemArr[ctx.questionIndex].audio_url, () => {
console.log('hint finish');
resolve()
})
})
},
onDone: 'answer',
onError: 'answer'
}
},
answer: {
after: {
10000: [
{
target: '#QuestionsArray.next',
actions: raise('CHECK'),
cond: (ctx, evt) => {
console.log('[timeout check] check if end', ctx.questionPlayTimes , ctx.maxQuestionTryTimes);
return ctx.questionPlayTimes >= ctx.maxQuestionTryTimes;
}
},
{ target: 'retry', actions: raise('CHECK') } // reenter 'hint' state
]
},
invoke: {
/*src: (ctx) => {
ctx.questionPlayTimes += 1;
const rt = RandomInt(4500, 5500)
console.log('[answer] thinking and playing', rt, rt<5000 ? 'should 1111': '');
return new Promise((resolve,reject) => {
setTimeout(() => {
if(rt < 5000) {
console.log('[answer] finish, go done', rt % 2);
}
if (rt % 2 == 1) {
resolve()
} else {
reject()
}
}, rt)
})
},
onDone: {
target: '#QuestionsArray.next',
actions: raise('CHECK')
},
onError: {
target: 'retry',
actions: raise('CHECK')
},*/
src: (context, event) => (callback, onReceive) => {
console.log('[answer] thinking and playing');
// This will send the 'INC' event to the parent every second
const id = setInterval(() => {
const region = this.data.hotZoneItemArr[context.questionIndex];
const result = this.checkInRegion(region.rectPercent);
console.log('checkInRegion', region.rectPercent, result);
if (result) {
callback('RIGHT')
// playAudioByUrl(this.data.begin_audio, () => {
// console.log('game begin audio finish');
// })
} else if (this._lastFingerPosition.dirty) {
callback('WRONG')
}
}, 1000);
// Perform cleanup
return () => clearInterval(id);
},
},
on: {
/*CHECK: {
actions: (context, evt) => {
const region = this.data.hotZoneItemArr[context.questionIndex];
const result = this.checkInRegion(region.rectPercent);
console.log('checkInRegion', region.rectPercent, result);
if (result) {
// forwardTo('RIGHT')
send({type: 'RIGHT' });
}
}
},*/
/*CHECK: [
{
actions: send('RIGHT'),
cond: (context, evt) => {
const region = this.data.hotZoneItemArr[context.questionIndex];
const result = this.checkInRegion(region.rectPercent);
console.log('checkInRegion', region.rectPercent, result);
if (result) {
// forwardTo('RIGHT')
send({type: 'RIGHT' });
}
}
},
{actions: raise('WRONG')},
],*/
/*RIGHT: {
target: '#QuestionsArray.next',
actions: raise('CHECK')
},
WRONG: {
target: 'retry',
actions: raise('CHECK')
}*/
RIGHT: {
target: 'right',
},
WRONG: {
target: 'wrong',
}
}
},
right: {
invoke: {
src: (context, event) => {
this._lastFingerPosition.pos = null;
this._lastFingerPosition.dirty = false;
return new Promise((resolve, reject) => {
console.log('answer right');
playAudioByUrl(this.rightAudio, () => {
resolve()
})
});
},
onDone: {
target: '#QuestionsArray.next',
actions: raise('CHECK')
},
onError: {
target: '#QuestionsArray.next',
actions: raise('CHECK')
}
}
},
wrong:{
invoke: {
src: (context, event) => {
this._lastFingerPosition.pos = null;
this._lastFingerPosition.dirty = false;
return new Promise((resolve, reject) => {
console.log('answer wrong');
playAudioByUrl(this.wrongAudio, () => {
resolve()
})
});
},
onDone: {
target: 'retry',
actions: raise('CHECK')
},
onError: {
target: 'retry',
actions: raise('CHECK')
}
}
},
retry: {
on: {
CHECK: [
{ target: 'hint' },
{
target: '#QuestionsArray.next',
actions: raise('CHECK'),
cond: (ctx, evt) => {
const c = ctx.questionPlayTimes >= ctx.maxQuestionTryTimes;
// ctx.questionPlayTimes = ctx.questionPlayTimes + 1;
console.log('#QuestionsArray.next', c)
return c
}
}
]
},
},
}
}
const QuestionsArrayStatus = {
id: 'QuestionsArray',
initial: 'play',
states: {
play: {
...QuestionState
},
next: {
on: {
CHECK: [
{
target: '#game.end',
cond: (ctx, evt) => {
ctx.questionIndex += 1;
ctx.questionPlayTimes = 0
console.log('#game.end', ctx.questionIndex >= ctx.questionsCount )
return ctx.questionIndex >= ctx.questionsCount
}
},
{target: 'play'}
]
}
}
}
}
const state = {
id: 'game',
initial: 'begin',
context: {
questionIndex: 0,
questionPlayTimes: 0,
maxQuestionTryTimes: 2,
questionsCount: this.data.hotZoneItemArr.length,
},
states: {
begin: {
invoke: {
src: (ctx) => {
console.log('game begin');
if(window.courseware && window.courseware.openOsmoFingerRead) {
window.courseware.openOsmoFingerRead()
}
return new Promise((resolve,reject) => {
playAudioByUrl(this.data.begin_audio, () => {
console.log('game begin audio finish');
resolve()
})
});
},
onDone: 'playing',
onError: 'playing'
}
},
playing: {
entry: () => {
console.log('entry play stage');
cc.assetManager.loadRemote(this.data.playing_audio, (err, audioClip) => {
cc.audioEngine.playMusic(audioClip, true, 0.8);
});
},
exit: () => {
console.log('exit play stage');
cc.audioEngine.stopMusic();
},
on: {
NEXT: 'end'
},
// ...QuestionsStates
...QuestionsArrayStatus
},
end: {
entry: (ctx, event) => {
console.log('game end', ctx, event);
if(window.courseware && window.courseware.closeOsmoFingerRead) {
window.courseware.closeOsmoFingerRead()
}
playAudioByUrl(this.data.end_audio, () => {
console.log('game finish');
})
// return new Promise((resolve,reject) => {
// setTimeout(() => {
// console.log('hint finish');
// resolve()
// }, 2000)
// })
}
},
}
};
const after = {};
for(let i = 0 ;i < this.data.hotZoneItemArr.length; i++) {
const t = this.data.hotZoneItemArr[i];
const k = +t.labelText * 1000;
after[k]= {
actions: () => {
console.log(k)
this.playAni(i, 'normal')
}
}
}
state.states.begin.after = after;
// state.states.begin.after = {
// 1000: { actions: () => {console.log(1000)} },
// 2000: { actions: () => {console.log(2000)} },
// }
const gameMachine = createMachine(state);
window.gameMachine = gameMachine;
const gameMachineService = interpret(gameMachine).onTransition((state) => {
// console.log(1, state.value, state.context);
});
gameMachineService.start();
window.gameMachineService = gameMachineService;
},
// 生命周期 start
start() {
let getData = this.getData.bind(this);
if (window && window.courseware) {
getData = window.courseware.getData;
}
getData((data) => {
console.log('data:', data);
this.data = data || this.getDefaultData();
this.data = JSON.parse(JSON.stringify(this.data))
const baseRect = this.data.bgItem.rect;
this.data.hotZoneItemArr.forEach(block => {
block.rectPercent = {
x: block.rect.x / baseRect.width,
y: block.rect.y / baseRect.height,
width: block.rect.width / baseRect.width,
height: block.rect.height / baseRect.height,
}
});
console.log(this.data);
this.preloadItem()
});
window.air = window.air || {}
if (window.air) {
window.air.osmoFingerReadCallback = (pos) => {
if (this.gameMachineService) {
return;
}
// const st = this.gameMachineService.state.value.constructor.name == 'Object'
// && this.gameMachineService.state.value['playing']
// && this.gameMachineService.state.value['playing'].constructor.name == 'Object'
// && this.gameMachineService.state.value['playing']['play']
// && this.gameMachineService.state.value['playing']['play'] == 'answer'
// if (st) {
// }
const p = JSON.parse(pos);
this._lastFingerPosition = {
pos:{
x: p.x * 2,
y: p.y
},
dirty: true
}
return
let dirty = false;
const lp = this._lastFingerPosition;
const p2 = lp.pos;
if (!p2) {
lp.pos = {
x: p.x * 2,
y: p.y
};
lp.dirty = true;
return
}
const detlaX = Math.abs(p2.x - p.x);
const detlaY = Math.abs(p2.y - p.y);
lp.pos = {
x: p.x * 2,
y: p.y
};
if (detlaX < 0.05 && detlaY < 0.05) {
lp.dirty = false;
} else {
lp.dirty = true;
}
}
}
},
checkInRegion(r) {
const p = this._lastFingerPosition ? this._lastFingerPosition.pos || {x:0, y:0} : {x:0, y:0};
const w = p.x > r.x && p.x < (r.x + r.width);
const h = p.y > r.y && p.y < (r.y + r.height);
return w && h;
},
getData(func) {
if (window && window.courseware) {
window.courseware.getData(func, 'scene');
return;
}
const middleLayer = cc.find('middleLayer');
if (middleLayer) {
const middleLayerComponent = middleLayer.getComponent('middleLayer');
middleLayerComponent.getData(func);
return;
}
func(this.getDefaultData());
},
getDefaultData() {
return defaultData;
},
preloadItem() {
this.addPreloadImage();
this.addPreloadAudio();
this.addPreloadAnima();
this.preload();
},
addPreloadImage() {
this._imageResList.push({ url: this.data.bgItem.url});
// this._imageResList.push({ url: this.data.pic_url_2 });
for (const q of this.data.hotZoneItemArr) {
this._audioResList.push({ url: q.texPngData.url });
}
},
addPreloadAudio() {
this._audioResList.push({ url: this.data.begin_audio });
this._audioResList.push({ url: this.data.playing_audio });
this._audioResList.push({ url: this.data.end_audio });
for (const q of this.data.hotZoneItemArr) {
this._audioResList.push({ url: q.audio_url });
}
},
addPreloadAnima() {
},
preload() {
const preloadArr = this._imageResList.concat(this._audioResList).concat(this._animaResList);
console.log(preloadArr);
cc.assetManager.loadAny(preloadArr, null, (f, t, item) => {
// console.log(f, t, item)
}, (err, data) => {
console.log(err, data);
// for (const asset of data) {
// if (asset.constructor.name === 'ImageBitmap') {
// const t = new cc.Texture2D()
// t.initWithData(asset);
// } else if (asset.constructor.name === 'AudioBuffer') {
// const clip = new cc.AudioClip()
// clip._nativeAsset = asset;
// }
// }
const ground = cc.find(`Canvas/frame-border/ground`);
for(const zone of this.data.hotZoneItemArr) {
const n = new cc.Node();
n.scale = 0.25;
const db = n.addComponent(dragonBones.ArmatureDisplay);
this._animaNodeList.push(n);
loadDragonBones(db, {
tex: zone.texPngData.url,
atlas: zone.texJsonData.url,
ske: zone.skeJsonData.url,
}).then(({width, height}) => {
// v.armatureName = 'armature
n.width = width;
n.height = height;
n.parent = ground
});
}
this.loadEnd();
if (window && window["air"] && window["air"].hideAirClassLoading) {
window["air"].hideAirClassLoading();
}
cc.debug.setDisplayStats(false);
});
},
loadEnd() {
this.initData();
this.initAudio();
this.initView();
// this.initListener();
this.createStateMachine();
},
_cantouch: null,
initData() {
// 所有全局变量 默认都是null
this._cantouch = true;
},
audioBtn: null,
initAudio() {
const audioNode = cc.find('Canvas/res/audio');
const getAudioByResName = (resName) => {
return audioNode.getChildByName(resName).getComponent(cc.AudioSource);
}
this.audioBtn = getAudioByResName('btn');
},
initView() {
this.initBg();
this.initPic();
this.initBtn();
this.initIcon();
},
initBg() {
const bgNode = cc.find('Canvas/bg');
bgNode.scale = this._mapScaleMax;
console.log('this._mapScaleMax', this._mapScaleMax);
},
pic1: null,
pic2: null,
initPic() {
const canvas = cc.find('Canvas');
const maxW = canvas.width * 0.7;
// this.getSprNodeByUrl(this.data.pic_url, (sprNode) => {
// const picNode1 = sprNode;
// picNode1.scale = maxW / picNode1.width;
// picNode1.baseX = picNode1.x;
// canvas.addChild(picNode1);
// this.pic1 = picNode1;
// const labelNode = new cc.Node();
// labelNode.color = cc.Color.YELLOW;
// const label = labelNode.addComponent(cc.Label);
// label.string = this.data.text;
// label.fontSize = 60;
// label.lineHeight = 60;
// label.font = cc.find('Canvas/res/font/BRLNSDB').getComponent('cc.Label').font;
// picNode1.addChild(labelNode);
// });
// this.getSprNodeByUrl(this.data.pic_url_2, (sprNode) => {
// const picNode2 = sprNode;
// picNode2.scale = maxW / picNode2.width;
// canvas.addChild(picNode2);
// picNode2.x = canvas.width;
// picNode2.baseX = picNode2.x;
// this.pic2 = picNode2;
// const labelNode = new cc.Node();
// const label = labelNode.addComponent(cc.RichText);
// const size = 60
// label.font = cc.find('Canvas/res/font/BRLNSDB').getComponent(cc.Label).font;
// label.string = `<outline color=#751e00 width=4><size=${size}><color=#ffffff>${this.data.text}</color></size></outline>`
// label.lineHeight = size;
// picNode2.addChild(labelNode);
// });
},
initIcon() {
// const iconNode = this.getSprNode('icon');
// iconNode.zIndex = 5;
// iconNode.anchorX = 1;
// iconNode.anchorY = 1;
// iconNode.parent = cc.find('Canvas');
// iconNode.x = iconNode.parent.width / 2 - 10;
// iconNode.y = iconNode.parent.height / 2 - 10;
// iconNode.on(cc.Node.EventType.TOUCH_START, () => {
// this.playAudioByUrl(this.data.audio_url);
// })
},
curPage: null,
initBtn() {
this.curPage = 0;
const bottomPart = cc.find('Canvas/bottomPart');
bottomPart.zIndex = 5; // 提高层级
bottomPart.x = bottomPart.parent.width / 2;
bottomPart.y = -bottomPart.parent.height / 2;
const leftBtnNode = bottomPart.getChildByName('btn_left');
//节点中添加了button组件 则可以添加click事件监听
leftBtnNode.on('click', () => {
if (!this._cantouch) {
return;
}
if (this.curPage == 0) {
return;
}
this.curPage = 0
this.leftMove();
// 游戏结束时需要调用这个方法通知系统作业完成
onHomeworkFinish();
cc.audioEngine.play(this.audioBtn.clip, false, 0.8)
})
const rightBtnNode = bottomPart.getChildByName('btn_right');
//节点中添加了button组件 则可以添加click事件监听
rightBtnNode.on('click', () => {
if (!this._cantouch) {
return;
}
if (this.curPage == 1) {
return;
}
this.curPage = 1
this.rightMove();
cc.audioEngine.play(this.audioBtn.clip, false, 0.5)
})
},
leftMove() {
// this._cantouch = false;
// const len = this.pic1.parent.width;
// cc.tween(this.pic1)
// .to(1, { x: this.pic1.baseX }, { easing: 'cubicInOut' })
// .start();
// cc.tween(this.pic2)
// .to(1, { x: this.pic2.baseX }, { easing: 'cubicInOut' })
// .call(() => {
// this._cantouch = true;
// })
// .start();
},
rightMove() {
// this._cantouch = false;
// const len = this.pic1.parent.width;
// cc.tween(this.pic1)
// .to(1, { x: this.pic1.baseX - len }, { easing: 'cubicInOut' })
// .start();
// cc.tween(this.pic2)
// .to(1, { x: this.pic2.baseX - len }, { easing: 'cubicInOut' })
// .call(() => {
// this._cantouch = true;
// })
// .start();
},
// update (dt) {},
// ------------------------------------------------
getSprNode(resName) {
const sf = cc.find('Canvas/res/img/' + resName).getComponent(cc.Sprite).spriteFrame;
const node = new cc.Node();
node.addComponent(cc.Sprite).spriteFrame = sf;
return node;
},
getSpriteFrimeByUrl(url, cb) {
cc.loader.load({ url }, (err, img) => {
const spriteFrame = new cc.SpriteFrame(img)
if (cb) {
cb(spriteFrame);
}
})
},
getSprNodeByUrl(url, cb) {
const node = new cc.Node();
const spr = node.addComponent(cc.Sprite);
this.getSpriteFrimeByUrl(url, (sf) => {
spr.spriteFrame = sf;
if (cb) {
cb(node);
}
})
},
playAudioByUrl(audio_url, cb = null) {
if (audio_url) {
cc.assetManager.loadRemote(audio_url, (err, audioClip) => {
const audioId = cc.audioEngine.play(audioClip, false, 0.8);
if (cb) {
cc.audioEngine.setFinishCallback(audioId, () => {
cb();
});
}
});
}
},
// ------------------------------------------
});
export const defaultData = { export const defaultData = {
"audio_url": "http://staging-teach.cdn.ireadabc.com/6d85e61e0382ad44380a47896c70fe2c.mp3",
"bgItem": {
"url": "http://staging-teach.cdn.ireadabc.com/8ffac3f84cfc0922f9f4726a01573aae.jpg",
"rect": {
"x": 350.64,
"y": 0,
"width": 275.72,
"height": 366
}
},
"hotZoneItemArr": [{
"id": "1637814752903",
"index": 0,
"audio_url": "http://staging-teach.cdn.ireadabc.com/190e0bec7c2c45936f4c5e8d2e76ca8c.mp3",
"itemType": "rect",
"fontScale": 0.76328125,
"imgScale": 1,
"imgSizeW": 0,
"imgSizeH": 0,
"mapScale": 0.76328125,
"skeJsonData": {
"url": "http://staging-teach.cdn.ireadabc.com/3466fc145510a329e9f61dfd535bf95d.json",
"name": "猫_ske.json"
},
"texJsonData": {
"url": "http://staging-teach.cdn.ireadabc.com/e45a23326fb71daf6315b75965fef44d.json",
"name": "猫_tex.json"
},
"texPngData": {
"url": "http://staging-teach.cdn.ireadabc.com/e6a86345144c118fbf0ef07b1c9076e3.png",
"name": "猫_tex.png"
},
"dragDot": {
"x": 488.5,
"y": 181.91712898751734
},
"gIdx": "0",
"labelText": "2.3",
"posX": 390.4300007490556,
"posY": 203.80396410953333,
"rect": {
"x": 17.22,
"y": 187,
"width": 45.14,
"height": 33.61
}
}, {
"id": "1637814801418",
"index": 1,
"audio_url": "http://staging-teach.cdn.ireadabc.com/6f0b27f38ecabcbe0ea6747ecbc2a4ef.mp3",
"itemType": "rect",
"fontScale": 0.76328125,
"imgScale": 1,
"imgSizeW": 0,
"imgSizeH": 0,
"mapScale": 0.76328125,
"skeJsonData": {
"url": "http://staging-teach.cdn.ireadabc.com/55951c794b414ab58cca023642819e37.json",
"name": "母鸡_ske.json"
},
"texJsonData": {
"url": "http://staging-teach.cdn.ireadabc.com/47b93323b1d1e1e6020704c537f46820.json",
"name": "母鸡_tex.json"
},
"texPngData": {
"url": "http://staging-teach.cdn.ireadabc.com/dd66021ff860b02a559d59817c71e27f.png",
"name": "母鸡_tex.png"
},
"dragDot": {
"x": 488.5,
"y": 181.91712898751734
},
"gIdx": "0",
"labelText": "4",
"posX": 848,
"posY": 68.5,
"rect": {
"x": 175.35,
"y": 34,
"width": 98.14,
"height": 25.38
}
}],
"begin_audio": "http://staging-teach.cdn.ireadabc.com/ce8446cedac3c367f4625c5a9b2c6095.mp3",
"end_audio": "http://staging-teach.cdn.ireadabc.com/0436231aed1f91741e0d67b235240df6.mp3",
"playing_audio": "http://staging-teach.cdn.ireadabc.com/5a653a762babdfb2499d10a5efa8e837.mp3"
}
/*{
"bgItem": { "bgItem": {
"url": "http://staging-teach.cdn.ireadabc.com/8ffac3f84cfc0922f9f4726a01573aae.jpg", "url": "http://staging-teach.cdn.ireadabc.com/8ffac3f84cfc0922f9f4726a01573aae.jpg",
"rect": { "rect": {
...@@ -84,7 +172,7 @@ export const defaultData = { ...@@ -84,7 +172,7 @@ export const defaultData = {
"begin_audio": "http://staging-teach.cdn.ireadabc.com/ce8446cedac3c367f4625c5a9b2c6095.mp3", "begin_audio": "http://staging-teach.cdn.ireadabc.com/ce8446cedac3c367f4625c5a9b2c6095.mp3",
"end_audio": "http://staging-teach.cdn.ireadabc.com/0436231aed1f91741e0d67b235240df6.mp3", "end_audio": "http://staging-teach.cdn.ireadabc.com/0436231aed1f91741e0d67b235240df6.mp3",
"playing_audio": "http://staging-teach.cdn.ireadabc.com/5a653a762babdfb2499d10a5efa8e837.mp3" "playing_audio": "http://staging-teach.cdn.ireadabc.com/5a653a762babdfb2499d10a5efa8e837.mp3"
} }*/
/* /*
{ {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment