Commit 16fcde72 authored by Master Q's avatar Master Q

init

parents
{
"presets": [
"react"
]
}
\ No newline at end of file
node_modules
{
"compile-hero.disable-compile-files-on-did-save-code": false
}
\ No newline at end of file
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>GameStage</title>
<script src="libs/fyge.min.js"></script>
<script src="libs/svgaParser.min.js"></script>
<!-- <script src="//yun.duiba.com.cn/db_games/libs0924/fyge158.min.js" crossorigin="anonymous"></script> -->
<style>
html,
body {
padding: 0;
margin: 0;
border: 0;
width: 100%;
height: 100%;
overflow: hidden;
position: absolute;
background-color: #ffffff;
/* background: linear-gradient(#93dbb7,#ff0,#b5d89a); */
/* background: linear-gradient(#93dbb7,#b5d89a); */
/* 背景图片,解决加载太慢,白屏问题,加了这个下面的__loading__可以删掉了 */
/* background-size: 100%;
background-position: center;
background-image: url("https://yun.duiba.com.cn/db_games/activity/game/1550472986/resource/assets/playscene/playscenebg.jpg"); */
}
</style>
</head>
<body>
<div id="app"></div>
<!-- <div id="__loading__" style="position:absolute;left:50%;top:50%;margin-left:-45px;color:#ffffff">拼命加载中...</div> -->
<div id="cusEngine" style="line-height:0;font-size:0;position: absolute;">
<canvas id="canvas" style="width: 100%;height: 100%"></canvas>
</div>
<script>
window.addEventListener("load", function () {
console.log('Main:')
//获取canvas
var canvas = document.getElementById("canvas");
canvas.width = document.body.clientWidth * (window.devicePixelRatio || 1)
canvas.height = document.body.clientHeight * (window.devicePixelRatio || 1)
var main = new Main(canvas);
var mouseEvent = main.stage.onMouseEvent.bind(main.stage);
canvas.addEventListener("touchstart", mouseEvent, false);
canvas.addEventListener('touchmove', mouseEvent, false);
canvas.addEventListener('touchend', mouseEvent, false);
window.stage = main.stage
})
</script>
<script src="bundle.js"></script>
</body>
</html>
\ No newline at end of file
This diff is collapsed.
declare module SvgaParser {
/**
* 加载方法
* @param url 资源路径
* @param success
* @param failure
*/
export function loadSvga(url: string, success: (videoItem: VideoEntity) => void, failure?: (err: string) => void): void;
/**
* 导出只是当作类型接口用
*/
export interface VideoEntity {
/**
* SVGA 文件版本
*/
version: string;
/**
* 影片尺寸
*/
videoSize: {
width: number;
height: number;
};
/**
* 帧率,60,30等每秒
*/
FPS: number;
/**
* 总帧数
*/
frames: number;
/**
* base64图片数据记录
*/
images: {
[key: string]: string
};
/**
* 图片是否已被缓存,缓存全局,注意名字覆盖
*/
hasBeenCached: boolean;
/**
* sprite对象数据
*/
sprites: SpriteEntity[];
}
interface SpriteEntity {
/**
* 标识
*/
matteKey: string;
/**
* 图片key值
*/
imageKey: string;
/**
* 帧数据数组
*/
frames: FrameEntity[];
}
/**
* 还有很多其他数据,暂不需要,比如矢量路径和遮罩路径暂时都无
*/
interface FrameEntity {
/**
* 透明度
*/
alpha: number;
/**
* 2维矩阵数据
*/
transform: {
a: number,
b: number,
c: number,
d: number,
tx: number,
ty: number,
};
}
}
declare module "svga-parser" { export = SvgaParser; }
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
// Type definitions for howler.js v2.1.1
// Project: https://github.com/goldfire/howler.js
// Definitions by: Pedro Casaubon <https://github.com/xperiments>
// Alexander Leon <https://github.com/alien35>
// Nicholas Higgins <https://github.com/nicholashza>
// Carlos Urango <https://github.com/cjurango>
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
interface HowlerGlobal {
usingWebAudio: boolean;
html5PoolSize: number;
noAudio: boolean;
autoUnlock: boolean;
autoSuspend: boolean;
ctx: AudioContext;
masterGain: GainNode;
mute(muted: boolean): this;
volume(): number;
volume(volume: number): this;
codecs(ext: string): boolean;
unload(): this;
stereo(pan: number): this;
pos(x: number, y: number, z: number): this | void;
orientation(x: number, y: number, z: number, xUp: number, yUp: number, zUp: number): this | void;
}
declare let Howler: HowlerGlobal;
interface IHowlSoundSpriteDefinition {
[name: string]: [number, number] | [number, number, boolean]
}
interface IHowlProperties {
src: string | string[];
volume?: number;
html5?: boolean;
loop?: boolean;
preload?: boolean;
autoplay?: boolean;
mute?: boolean;
sprite?: IHowlSoundSpriteDefinition;
rate?: number;
pool?: number;
format?: string[] | string;
xhrWithCredentials?: boolean;
onload?: () => void;
onloaderror?: (soundId: number, error: any) => void;
onplay?: (soundId: number) => void;
onplayerror?: (soundId: number, error: any) => void;
onend?: (soundId: number) => void;
onpause?: (soundId: number) => void;
onstop?: (soundId: number) => void;
onmute?: (soundId: number) => void;
onvolume?: (soundId: number) => void;
onrate?: (soundId: number) => void;
onseek?: (soundId: number) => void;
onfade?: (soundId: number) => void;
onunlock?: (soundId: number) => void;
}
interface Howl {
play(spriteOrId?: string | number): number; // .play() is not chainable; the other methods are
pause(id?: number): this;
stop(id?: number): this;
mute(): boolean;
mute(muted: boolean, id?: number): this;
volume(): number;
volume(idOrSetVolume: number): this | number;
volume(volume: number, id: number): this;
fade(from: number, to: number, duration: number, id?: number): this;
rate(): number;
rate(idOrSetRate: number): this | number;
rate(rate: number, id: number): this;
seek(seek?: number, id?: number): this | number;
loop(id?: number): boolean;
loop(loop: boolean, id?: number): this;
playing(id?: number): boolean;
duration(id?: number): number;
state(): 'unloaded' | 'loading' | 'loaded';
load(): this;
unload(): void;
on(event: 'load', callback: () => void, id?: number): this;
on(event: 'loaderror', callback: (soundId: number, error: any) => void, id?: number): this;
on(event: 'play', callback: (soundId: number) => void, id?: number): this;
on(event: 'playerror', callback: (soundId: number, error: any) => void, id?: number): this;
on(event: 'end', callback: (soundId: number) => void, id?: number): this;
on(event: 'pause', callback: (soundId: number) => void, id?: number): this;
on(event: 'stop', callback: (soundId: number) => void, id?: number): this;
on(event: 'mute', callback: (soundId: number) => void, id?: number): this;
on(event: 'volume', callback: (soundId: number) => void, id?: number): this;
on(event: 'rate', callback: (soundId: number) => void, id?: number): this;
on(event: 'seek', callback: (soundId: number) => void, id?: number): this;
on(event: 'fade', callback: (soundId: number) => void, id?: number): this;
on(event: string, callback: Function, id?: number): this;
on(event: 'unlock', callback: (soundId: number) => void, id?: number): this;
once(event: 'load', callback: () => void, id?: number): this;
once(event: 'loaderror', callback: (soundId: number, error: any) => void, id?: number): this;
once(event: 'play', callback: (soundId: number) => void, id?: number): this;
once(event: 'playerror', callback: (soundId: number, error: any) => void, id?: number): this;
once(event: 'end', callback: (soundId: number) => void, id?: number): this;
once(event: 'pause', callback: (soundId: number) => void, id?: number): this;
once(event: 'stop', callback: (soundId: number) => void, id?: number): this;
once(event: 'mute', callback: (soundId: number) => void, id?: number): this;
once(event: 'volume', callback: (soundId: number) => void, id?: number): this;
once(event: 'rate', callback: (soundId: number) => void, id?: number): this;
once(event: 'seek', callback: (soundId: number) => void, id?: number): this;
once(event: 'fade', callback: (soundId: number) => void, id?: number): this;
once(event: string, callback: Function, id?: number): this;
once(event: 'unlock', callback: (soundId: number) => void, id?: number): this;
off(event: string, callback?: Function, id?: number): this;
off(): this;
stereo(pan: number, id?: number): this | void;
pos(x: number, y: number, z: number, id?: number): this | void;
orientation(x: number, y: number, z: number, xUp: number, yUp: number, zUp: number): this | void;
pannerAttr(o: {
coneInnerAngle?: number,
coneOuterAngle?: number, coneOuterGain?: number,
distanceModel: 'inverse' | 'linear', maxDistance: number,
panningModel: 'HRTF' | 'equalpower', refDistance: number, rolloffFactor: number
}, id?: number): this;
}
interface HowlStatic {
new(properties: IHowlProperties): Howl;
}
declare let Howl: HowlStatic;
declare module "howler" {
export let Howler: HowlerGlobal;
export let Howl: HowlStatic;
}
This diff is collapsed.
var Stats = function () {
var startTime = Date.now(), prevTime = startTime;
var ms = 0, msMin = Infinity, msMax = 0;
var fps = 0, fpsMin = Infinity, fpsMax = 0;
var frames = 0, mode = 0;
var container = document.createElement('div');
container.id = 'stats';
container.addEventListener('mousedown', function (event) {
event.preventDefault();
setMode(++mode % 2)
}, false);
container.style.cssText = 'width:80px;opacity:0.9;cursor:pointer';
var fpsDiv = document.createElement('div');
fpsDiv.id = 'fps';
fpsDiv.style.cssText = 'padding:0 0 3px 3px;text-align:left;background-color:#002';
container.appendChild(fpsDiv);
var fpsText = document.createElement('div');
fpsText.id = 'fpsText';
fpsText.style.cssText = 'color:#0ff;font-family:Helvetica,Arial,sans-serif;font-size:9px;font-weight:bold;line-height:15px';
fpsText.innerHTML = 'FPS';
fpsDiv.appendChild(fpsText);
var fpsGraph = document.createElement('div');
fpsGraph.id = 'fpsGraph';
fpsGraph.style.cssText = 'position:relative;width:74px;height:30px;background-color:#0ff';
fpsDiv.appendChild(fpsGraph);
while (fpsGraph.children.length < 74) {
var bar = document.createElement('span');
bar.style.cssText = 'width:1px;height:30px;float:left;background-color:#113';
fpsGraph.appendChild(bar);
}
var msDiv = document.createElement('div');
msDiv.id = 'ms';
msDiv.style.cssText = 'padding:0 0 3px 3px;text-align:left;background-color:#020;display:none';
container.appendChild(msDiv);
var msText = document.createElement('div');
msText.id = 'msText';
msText.style.cssText = 'color:#0f0;font-family:Helvetica,Arial,sans-serif;font-size:9px;font-weight:bold;line-height:15px';
msText.innerHTML = 'MS';
msDiv.appendChild(msText);
var msGraph = document.createElement('div');
msGraph.id = 'msGraph';
msGraph.style.cssText = 'position:relative;width:74px;height:30px;background-color:#0f0';
msDiv.appendChild(msGraph);
while (msGraph.children.length < 74) {
var bar = document.createElement('span');
bar.style.cssText = 'width:1px;height:30px;float:left;background-color:#131';
msGraph.appendChild(bar);
}
var setMode = function (value) {
mode = value;
switch (mode) {
case 0:
fpsDiv.style.display = 'block';
msDiv.style.display = 'none';
break;
case 1:
fpsDiv.style.display = 'none';
msDiv.style.display = 'block';
break;
}
}
var updateGraph = function (dom, value) {
var child = dom.appendChild(dom.firstChild);
child.style.height = value + 'px';
}
return {
REVISION: 11,
domElement: container,
setMode: setMode,
begin: function () {
startTime = Date.now();
},
end: function () {
var time = Date.now();
ms = time - startTime;
msMin = Math.min(msMin, ms);
msMax = Math.max(msMax, ms);
msText.textContent = ms + ' MS (' + msMin + '-' + msMax + ')';
updateGraph(msGraph, Math.min(30, 30 - (ms / 200) * 30));
frames++;
if (time > prevTime + 1000) {
fps = Math.round((frames * 1000) / (time - prevTime));
fpsMin = Math.min(fpsMin, fps);
fpsMax = Math.max(fpsMax, fps);
fpsText.textContent = fps + ' FPS (' + fpsMin + '-' + fpsMax + ')';
updateGraph(fpsGraph, Math.min(30, 30 - (fps / 100) * 30));
prevTime = time;
frames = 0;
}
return time;
},
update: function () {
startTime = this.end();
}
}
};
//执行
var stats = new Stats();
stats.domElement.style.position = 'absolute';
stats.domElement.style.top = '0px';
document.body.appendChild(stats.domElement);
aa();
function aa() {
stats.update();
requestAnimationFrame(aa)
}
This diff is collapsed.
This source diff could not be displayed because it is too large. You can view the blob instead.
declare const app;
declare const PAGE;
declare function getApp();
declare namespace my {
export function postMessage(e);
export function onMessage(e);
export const tb;
}
This diff is collapsed.
{
"name": "gamestage",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"dev": "webpack-dev-server --hot"
},
"author": "",
"license": "ISC",
"devDependencies": {
"awesome-typescript-loader": "^5.2.1",
"babel-core": "^6.26.3",
"babel-loader": "^7.1.5",
"babel-preset-env": "^1.7.0",
"css-loader": "^5.2.6",
"style-loader": "^2.0.0",
"typescript": "^4.3.4",
"webpack": "^5.40.0",
"webpack-cli": "^3.3.12",
"webpack-dev-server": "^3.11.2"
},
"dependencies": {
"@types/matter-js": "^0.17.1",
"babel-preset-react": "^6.24.1",
"matter-js": "^0.17.1",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"ts-loader": "^9.2.3"
}
}
export default class Clock {
startTime = 0;
oldTime = 0;
elapsedTime = 0;
running = false;
constructor(
public autoStart = true
) {
}
start() {
this.startTime = (typeof performance === 'undefined' ? Date : performance).now();
this.oldTime = this.startTime;
this.elapsedTime = 0;
this.running = true;
}
stop() {
this.running = false;
this.autoStart = false;
return this.getElapsedTime();
}
st() {
this.running = false
}
getElapsedTime() {
this.getDelta();
return this.elapsedTime;
}
getDelta() {
let diff = 0;
if (this.autoStart && !this.running) {
this.start();
return 0;
}
if (this.running) {
const newTime = (typeof performance === 'undefined' ? Date : performance).now();
diff = (newTime - this.oldTime) / 1000;
this.oldTime = newTime;
this.elapsedTime += diff;
}
return diff;
}
}
class Layer extends FYGE.Container {
stage: FYGE.Stage
scenseCnt: FYGE.Container
currScense: FYGE.Container
constructor() {
super();
}
init(stage: FYGE.Stage) {
this.stage = stage
stage.addChild(this)
const senseContainer = this.scenseCnt = new FYGE.Container()
// senseContainer.x = this.stageOffsetLeft
// senseContainer.y = this.stageOffsetTop
this.addChild(senseContainer)
}
changeScense(sense: FYGE.Container) {
if (this.currScense) {
this.currScense.destroy()
}
this.scenseCnt.addChild(sense)
}
get stageWidth():number {
return this.stage ? this.stage.viewRect.width : 0
}
get stageHeight():number {
return this.stage ? this.stage.viewRect.height : 0
}
get stageOffsetLeft():number {
return this.stage ? this.stage.viewRect.x : 0
}
get stageOffsetTop():number {
return this.stage ? this.stage.viewRect.y : 0
}
}
export const layer = new Layer()
\ No newline at end of file
import { layer } from "./Layer"
const Texture = FYGE.Texture
const Button = FYGE.Button
const Sprite = FYGE.Sprite
type ButtonTexture = FYGE.Texture | {
tUp: FYGE.Texture,
tDown?: FYGE.Texture,
tDisable?: FYGE.Texture
}
export default class UI {
// public static getPositionAtScense(
// cnt: FYGE.Container,
// )
/**
* UI button
* @param parent 添加 parent
* @param texture 纹理 支持 {tUp: , tDown: , tDisable}
* @param x
* @param y
* @param width
* @param height
* @param clickEvent
* @param that clickEvent click 的this指向
* @returns
*/
public static btn(
parent: FYGE.Container,
texture: ButtonTexture,
width?: number,
height?: number,
x?: number | 'center' | 'left' | 'right',
y?: number | 'center' | 'top' | 'bottom',
clickEvent?: Function,
that?: any
): FYGE.Button {
let btn: FYGE.Button
if ('tUp' in texture) {
btn = new Button(texture.tUp, texture.tDown, texture.tDisable)
} else {
btn = new Button(texture)
}
let fw: number
let fh: number
width && (btn.width = width)
height && (btn.height = height)
fw = btn.width
fh = btn.height
let fx:number = 0
let fy:number = 0
let pw: number = parent.width == 1 ? layer.stageWidth : parent.width
let ph: number = parent.height == 1 ? layer.stageHeight : parent.height
// 初始化 x坐标
if (x) {
if (typeof x == 'string') {
switch(x) {
case 'center':
fx = (pw - fw) / 2
break
case 'right':
fx = pw - fw
break
}
} else {
fx = x
}
}
// 初始化 y坐标
if (y) {
if (typeof y == 'string') {
switch(y) {
case 'center':
fy = (ph - fh) / 2
break
case 'bottom':
fy = ph - fh
break
}
} else {
fy = y
}
}
btn.x = fx
btn.y = fy
clickEvent && btn.addEventListener(FYGE.MouseEvent.CLICK, clickEvent, that)
return parent.addChild(btn)
}
public static Sp(
parent: FYGE.Container,
texture: FYGE.Texture,
width?: number,
height?: number,
x: number=0,
y: number=0,
clickEvent?: Function,
that?: any
): FYGE.Sprite {
let sp: FYGE.Sprite
sp = new Sprite(texture)
width && (sp.width = width)
height && (sp.height = height)
sp.x = x
sp.y = y
clickEvent && sp.addEventListener(FYGE.MouseEvent.CLICK, clickEvent, that)
return parent.addChild(sp)
}
public static addChild(
parent: FYGE.Container,
child: any,
x: number=0,
y: number=0
) {
child.x = x
child.y = y
return parent.addChild(child)
}
}
\ No newline at end of file
import Matter = require("matter-js");
import { SS } from "../../config";
type circleData = {
x: number,
y: number,
radius: number,
color: string
}
function throttle(fn, delay=2000) {
var timer
var flag = true
return function(...args) {
const context = this
if (!flag) return
flag = false
clearTimeout(timer)
fn.apply(context, args)
timer = setTimeout(() => {
flag = true
}, delay)
}
}
export class CircleCnt extends FYGE.Container {
shape: FYGE.Shape
phyBody: Matter.Body
circleData: circleData
constructor(data:circleData) {
super();
this.circleData = data
this.x = data.x
this.y = data.y
this.shape = this.addChild(new FYGE.Shape())
this.shape.beginFill(data.color)
this.shape.drawCircle(data.radius,data.radius, data.radius)
this.shape.endFill()
// this.shape.mouseChildren = false
// this.shape.mouseEnable = false
this.phyBody = Matter.Bodies.circle(this.x * SS, this.y * SS, (this.width / 2) * SS, {
restitution: .3,// 弹性
mass: .5, // 质量
isStatic: false,
isSensor: false, // 传感器 true,可以检测到碰撞,但是不参与碰撞
render: { fillStyle: "#060a19" },
collisionFilter: { group: 1 }, // 参考reademe里面的碰撞规则
})
this.setPhyPos()
var that = this
this.addEventListener(FYGE.Event.ADDED_TO_STAGE, () => {
this.addEventListener(FYGE.Event.ENTER_FRAME, this.syncPos, this)
}, this)
that = new Proxy(this, {
get: function (target, key:string, receiver) {
return Reflect.get(target, key, receiver);
},
set: function (target, key:string, value, receiver) {
var r = Reflect.set(target, key, value, receiver)
if (key == 'x' || key == 'y') {
that.setPhyPos()
}
// console.log(`setting ${key}!`);
return r;
}
})
return that
}
syncPos() {
this.x = this.phyBody.position.x / SS - this.width / 2 + 10;
this.y = this.phyBody.position.y / SS - this.width / 2 + 10;
}
setPhyPos() {
Matter.Body.setPosition(this.phyBody, {
x: (this.x + this.circleData.radius) * SS,
y: (this.y + this.circleData.radius) * SS,
});
}
}
\ No newline at end of file
/** 比例系数--matterjs适配 */
export const SS = 1
#app {
text-align: center;
}
*{
padding: 0;
margin: 0
}
\ No newline at end of file
import React, {Component} from 'react';
import ReactDom from 'react-dom'
class TestCom extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<div>123
{this.props.children}
</div>
)
}
}
console.log(new TestCom())
const r1 = React.createElement(TestCom, {
test:1
}, [
'123123123'
])
console.log(r1)
ReactDom.render(r1, document.getElementById('app'))
window.React = React
\ No newline at end of file
import { layer } from "./Layer";
import MainScense from "./scense/mainScense";
// require('./main.js')
// import { walkSync, walk } from './utils/utils.js'
export class Main {
// 主舞台
stage: FYGE.Stage;
private requestId:number;
private _pause: boolean;
private canvas: HTMLCanvasElement
constructor(canvas: HTMLCanvasElement) {
// 创建舞台
this.stage = new FYGE.Stage(
canvas,
750,
1624,
document.body.clientWidth,
document.body.clientHeight,
FYGE.RENDERER_TYPE.CANVAS,
true // 视图居中裁剪
)
this.canvas = canvas
// stage 初始化
this.stage.addEventListener(FYGE.Event.INIT_STAGE, this.initUI, this)
let self = this
loop()
function loop() {
if (!self._pause) {
FYGE.Tween.flush();
self.stage.flush()
}
self.requestId = window.requestAnimationFrame(loop)
}
}
initUI() {
console.log('初始化')
layer.init(this.stage)
console.log('stage:', this.stage)
const mainScense = new MainScense()
layer.changeScense(mainScense)
// walkSync('./assets/game', (path, file) => {
// console.log(path, file)
// })
}
destroy() {
//Tween都移除,注意吧,可能原先的也被移除,,对于多page时注意,会把其他页面的也去掉
FYGE.Tween.removeAllTweens();
//停掉计时器
//@ts-ignore 为了兼容多page的canvas
window.cancelAnimationFrame(this.requestID);
//舞台销毁
this.stage.destroy();
}
}
//@ts-ignore
window.Main = Main
\ No newline at end of file
This diff is collapsed.
.flip {
position: relative;
width: 60px;
font-size: 50px;
height: 100px;
line-height: 100px;
text-align: center;
}
.flip .digital {
/* display: inline-block;
width: 100%;
position: absolute;
left: 0;
top: 0;
text-align: center; */
backface-visibility: hidden
}
.flip .digital::before, .flip .digital::after{
content: attr(data-num);
position: absolute;
left: 0;
right: 0;
background-color: #fafafa;
overflow: hidden;
background-clip: content-box;
backface-visibility: hidden
}
.flip .digital::before {
top: 0;
bottom: 50%;
/* padding-bottom: 1px; */
border-bottom: 1px solid #ccc;
}
.flip .digital::after {
top: 50%;
bottom: 0;
line-height: 0;
/* padding-top: 1px; */
/* border-top: 1px solid transparent; */
}
.flip .back::after {
transform-origin: center top;
transform: rotateX(.5turn);
}
.flip .back::before,
.flip .curr::after {
z-index: 1;
}
.flip .back::after {
z-index: 2;
}
.flip .curr::before {
z-index: 3;
}
.flip .curr::before {
transform-origin: bottom center;
}
.running .back::after {
z-index: 3;
}
/* .flip .back {
opacity: 0;
}
.running .back {
opacity: 1;
} */
.running .back::after{
transition: all .6s linear;
transform: perspective(1000px) rotateX(0turn);
}
.running .curr::before{
transition: all .6s linear;
transform: perspective(1000px) rotateX(.5turn);
}
\ No newline at end of file
import {addClass, removeClass} from './utils'
import './flip.css'
var Fliper = (function() {
function Fliper(el, curr, back) {
this.el = el
this.currNum = curr
this.backNum = back
this.init()
}
Fliper.prototype = {
init: function() {
this.curr = null
this.back = null
this.flip = null
this.render()
},
render: function() {
this.el.innerHTML = ''
var flip = this.flip = this.el
addClass(flip, 'flip')
var curr = this.curr = document.createElement('div')
addClass(curr, 'curr digital')
var back = this.back = document.createElement('div')
addClass(back, 'back digital')
this.initData()
flip.appendChild(curr)
flip.appendChild(back)
},
initData: function() {
this.curr.dataset.num = this.currNum || 0
this.back.dataset.num = this.backNum || 0
},
flipDown: function (backNum) {
if (backNum) {
this.backNum = backNum
this.back.dataset.num = this.backNum
}
addClass(this.flip, 'running')
setTimeout(() => {
this.currNum = this.backNum
this.initData()
removeClass(this.flip, 'running')
}, 600)
}
}
return Fliper
})()
export default Fliper
\ No newline at end of file
/**
* 自己的埋点
*/
const projectxString = "projectx/";
let projectId;
function getProjectId() {
if (projectId) return projectId;
const windowUrl = window.location.href;
const splitArr = windowUrl.split(projectxString);
if (splitArr.length != 2) {
return projectId = "projectId"
}
const start = windowUrl.indexOf(projectxString) + projectxString.length;
const end = splitArr[1].indexOf("/");
return projectId = windowUrl.substr(start, end);
}
/**
* 对象参数的处理
* @param data
* @returns {string}
*/
function getParams(data) {
const arr = [];
for (let param in data) {
arr.push(encodeURIComponent(param) + '=' + encodeURIComponent(data[param]));
}
//不缓存
arr.push('_=' + Date.now());
return arr.join('&');
}
export function jsonp(url, params) {
const src = url + '?' + getParams(params);
const scriptEl = document.createElement('script');
scriptEl.src = src;
scriptEl.onload = function () {
document.body.removeChild(scriptEl);
};
scriptEl.onerror = function () {
document.body.removeChild(scriptEl);
};
document.body.appendChild(scriptEl);
}
/**
* 埋点
* @param type exposure | click
* @param data
*/
export function sendLog(type, data) {
const projectID = getProjectId();
const appID = CFG.appID; // TODO appID
let { dpm, dcm, dom } = data;
dpm = `${appID}.110.${dpm}`;
dcm = dcm || `202.${projectID}.0.0`;
let params = {
dpm,
dcm,
appId: appID
};
if (dom) params.dom = dom;
let isExposure = (type === 'exposure');
if (isExposure) {
jsonp('//embedlog.duiba.com.cn/exposure/standard', params);
} else {
jsonp('/log/click', params);
}
}
export function md_exposure(dpmId) {
sendLog('exposure', { dpm: `${dpmId}.1` });
}
export function md_click(dpmId) {
sendLog('click', { dpm: `${dpmId}.1` });
}
\ No newline at end of file
import ReactDom from 'react-dom';
import React from 'react'
// import NormalModal from '../components/qgModal/normalModal/index.jsx'
import {HocModal} from '../components/qgModal/HocModal/HocModal.jsx'
const showModalConfig = {
destroyed: true,
appendDom: document.body,
cot: true
}
const ModalMap = new Map()
const ModalDataMap = new Map()
export const ModalCtrl = {
showModal(M, opt = {}, cb) {
// 弹窗react
let TargetModal
// 弹窗实例
let modalRef
//todo 这里后面可以优化下, 二次 修改弹窗配置
opt = Object.assign(
{},
showModalConfig,
opt,
{
appendBody: !opt.appendDom
}
)
// 该组件并为 显示的时候
if (!ModalMap.has(M)) {
var m = document.createElement('div')
opt.appendDom.appendChild(m)
const isDestroyed = opt.destroyed
// 卸载 react 组件,否则组件的实例一直存在
const closeModal = () => {
typeof cb === 'function' && cb()
console.log('组件是否被销毁:', isDestroyed)
if (isDestroyed) {
ModalMap.delete(M)
ReactDom.unmountComponentAtNode(m)
m.remove()
}
}
// TargetModal = <NormalModal transitionName="slide-top" cot={false} visible={true} close={closeModal} {...opt}>
// <M></M>
// </NormalModal>
var T = HocModal(M)
// 存储当前弹窗的props
ModalDataMap.set(M, opt)
TargetModal = <T ref={r =>{
modalRef = r
} } cot={false} appendBody={opt.appendBody} visible={true} close={closeModal} {...opt}></T>
// todo 这里需要注意一下,为什么第一时间不能 获取到 ref 因该是 只有 render 上去才会有
setTimeout(() => {
ModalMap.set(M, modalRef)
}, 0)
ReactDom.render(TargetModal, m)
} else {
modalRef = ModalMap.get(M)
modalRef.showModal()
}
// 返回该弹窗实例
return modalRef
},
renderModal(M, opt) {
var data = ModalDataMap.get(M)
var d1 = Object.assign(data, opt)
ModalDataMap.set(M, d1)
console.log(d1)
var modalRef = ModalMap.get(M)
modalRef && modalRef.forceUpdate()
},
clearModals() {
ModalMap.forEach(m => {
m.hiddenModal({ns: false})
})
}
}
\ No newline at end of file
var whitespaceRE = /\s+/
function addClass(el, cls) {
if (!cls || !(cls = cls.trim())) {
return
}
/* istanbul ignore else */
if (el.classList) {
if (cls.indexOf(' ') > -1) {
cls.split(whitespaceRE).forEach(function (c) {
return el.classList.add(c);
});
} else {
el.classList.add(cls);
}
} else {
var cur = " " + (el.getAttribute('class') || '') + " ";
if (cur.indexOf(' ' + cls + ' ') < 0) {
el.setAttribute('class', (cur + cls).trim());
}
}
}
// 移除class
function removeClass(el, cls) {
/* istanbul ignore if */
if (!cls || !(cls = cls.trim())) {
return
}
/* istanbul ignore else */
if (el.classList) {
if (cls.indexOf(' ') > -1) {
cls.split(whitespaceRE).forEach(function (c) {
return el.classList.remove(c);
});
} else {
el.classList.remove(cls);
}
if (!el.classList.length) {
el.removeAttribute('class');
}
} else {
var cur = " " + (el.getAttribute('class') || '') + " ";
var tar = ' ' + cls + ' ';
while (cur.indexOf(tar) >= 0) {
cur = cur.replace(tar, ' ');
}
cur = cur.trim();
if (cur) {
el.setAttribute('class', cur);
} else {
el.removeAttribute('class');
}
}
}
// 设置 style
function setStyles (el, styles) {
if (!styles) return
var stylesKeys = Object.keys(styles)
if (stylesKeys.length) {
stylesKeys.forEach(function (item) {
el.style[item] = styles[item]
})
}
}
// transtion 动画
var transitionAction = (function () {
var transitionProp = 'transition' // transiton 动画
var animationProp = 'animation' // animation 动画
var transitionEndEvent = 'transitionend'; // transitionend 事件 用于动画结束的时候去除动画 class
var animationEndEvent = 'animationend'; // animationend 事件 用于动画结束的时候去除动画 class
// 以下是兼容浏览器方法。
if (window.ontransitionend === undefined &&
window.onwebkittransitionend !== undefined
) {
transitionEndEvent = 'webkitTransitionEnd';
}
if (window.onanimationend === undefined &&
window.onwebkitanimationend !== undefined
) {
animationEndEvent = 'webkitAnimationEnd';
}
// getTimeout 获取当前动画的最大跨度时间,
function getTimeout(delays, durations) {
/* istanbul ignore next */
while (delays.length < durations.length) {
delays = delays.concat(delays);
}
return Math.max.apply(null, durations.map(function (d, i) {
return toMs(d) + toMs(delays[i])
}))
}
// 转化时间
function toMs(s) {
return Number(s.slice(0, -1).replace(',', '.')) * 1000
}
// 获取当前动画的信息,如delay duration
function getTransitionInfo(el, expectedType) {
var styles = window.getComputedStyle(el)
// JSDOM may return undefined for transition properties
var transitionDelays = (styles[transitionProp + 'Delay'] || '').split(', ')
var transitionDurations = (styles[transitionProp + 'Duration'] || '').split(', ')
var transitionTimeout = getTimeout(transitionDelays, transitionDurations)
var animationDelays = (styles[animationProp + 'Delay'] || '').split(', ')
var animationDurations = (styles[animationProp + 'Duration'] || '').split(', ')
var animationTimeout = getTimeout(animationDelays, animationDurations)
var type = transitionProp // 默认值
var timeout = 0
var propCount = 0
if (expectedType === transitionProp) {
if (transitionTimeout > 0) {
type = transitionProp
timeout = transitionTimeout
propCount = transitionDurations.length
}
} else {expectedType === animationProp} {
if (animationTimeout > 0) {
type = animationProp
timeout = animationTimeout
propCount = animationDurations.length
}
}
return {
type: type, // 当前动画类型,是transiton 动画 还是 animation动画
timeout: timeout,
propCount: propCount
}
}
// 以下是重要代码,是在动画结束的时候,执行回调function
function whenTransitionEnd (el, expectedType, cb) {
var ref = getTransitionInfo(el, expectedType)
var timeout = ref.timeout;
var propCount = ref.propCount;
var event = expectedType === transitionProp ? transitionEndEvent : animationEndEvent;
var runOnce = true
var end = function () {
el.removeEventListener(event, end)
if (runOnce) {
cb();
runOnce = false
}
};
el.addEventListener(event, end);
setTimeout(function () {
end()
}, timeout + 1);
}
// 以下就是我简单封装的动画方法
return function (ops) {
var el = ops.el
this.transitionName = ops.transitionName || 'transition' // 动画的name 用于动画展示
var transitionName = this.transitionName
var type = ops.type || 'transition' // transtion 或者 animation
var showStartClsName = transitionName + '-enter'
var showActiveClsName = transitionName + '-enter-active'
var hiddenStartClsName = transitionName + '-leave-to'
var hiddenActiveClsName = transitionName + '-leave-active'
this.changeTransition = function(name) {
this.transitionName = name
}
this.show = function(cb) {
addClass(el, showStartClsName)
el.style.display = 'block' // 从display none 到 block 要有初始化状态
setTimeout(function () { // 加入 微队列,这样才能动画展示 这里是重点
addClass(el, showActiveClsName)
setTimeout(() => {
removeClass(el, showStartClsName)
whenTransitionEnd(el, type, function() {
removeClass(el, showActiveClsName + ' ' + showStartClsName)
typeof cb === 'function' && cb()
})
}, 0)
},0)
}
this.hidden = function(cb) {
addClass(el, hiddenActiveClsName) // hidden 的动画,就相对简单,只需要加上动画就行了,因为没有 display none 的干扰
addClass(el, hiddenStartClsName)
whenTransitionEnd(el, type, function() {
removeClass(el, hiddenStartClsName + ' ' + hiddenActiveClsName)
el.style.display = 'none'
typeof cb === 'function' && cb()
})
}
}
})()
export default transitionAction
\ No newline at end of file
This diff is collapsed.
/**
* Vue 的on off emit 事件 做消息中心
*/
class Vue {
static ins;
constructor() {
// 事件通道调度中心
this._events = Object.create(null);
}
$on(event, fn) {
if (Array.isArray(event)) {
event.map(item => {
this.$on(item, fn);
});
} else {
(this._events[event] || (this._events[event] = [])).push(fn);
}
return this;
}
$once(event, fn) {
function on() {
this.$off(event, on);
fn.apply(this, arguments);
}
on.fn = fn;
this.$on(event, on);
return this;
}
$off(event, fn) {
if (!arguments.length) {
this._events = Object.create(null);
return this;
}
if (Array.isArray(event)) {
event.map(item => {
this.$off(item, fn);
});
return this;
}
const cbs = this._events[event];
if (!cbs) {
return this;
}
if (!fn) {
this._events[event] = null;
return this;
}
let cb;
let i = cbs.length;
while (i--) {
cb = cbs[i];
if (cb === fn || cb.fn === fn) {
cbs.splice(i, 1);
break;
}
}
return this;
}
$emit(event) {
let cbs = this._events[event];
if (cbs) {
const args = [].slice.call(arguments, 1);
cbs.map(item => {
args ? item.apply(this, args) : item.call(this);
});
}
return this;
}
}
const vueControl = new Vue()
export default vueControl
\ No newline at end of file
{
"compilerOptions": {
"module": "commonjs", // 编译出的代码采用的模块规范
"noImplicitAny": false,
"noEmitOnError": true,
"target": "es5", // 编译出的代码采用 ES 的哪个版本
"sourceMap": true, // 输出 Source Map 方便调试
"lib": [
"dom",
"es5",
"es2015"
]
},
"exclude": [ // 不编译这些目录里的文件
"node_modules"
]
}
\ No newline at end of file
const path = require('path')
module.exports = {
mode: 'development',
entry: {
index: './src/main.ts'
},
devtool: 'source-map',
module: {
rules: [
{
test: /\.css$/,
use: ['style-loader', 'css-loader']
},
{
test: /\.jsx?$/,
use: ['babel-loader']
},
{
test: /\.tsx?$/,
use: ["ts-loader"],
exclude:/node_modules/
}
]
},
resolve: {
alias: {
'@': './src'
},
extensions: ['.ts', '.js', '.css']
},
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, './dist')
},
devServer: {
host: '0.0.0.0',
port: 9002,
hot: true,
open: true
}
}
\ No newline at end of file
This diff is collapsed.
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