Commit fd54cd1c authored by 张媛's avatar 张媛

添加组件源码预览功能

parent 444aea85
.codeContainer{
.code{
background-color: #333333;
margin: 20px;
border-radius: 4px;
box-shadow: grey 0 0px 3px 0px, #333333 0 0 0 0px;
color: #FFFFFF;
font-size: 13px;
}
.title{
color:#ffffff;
font-size: 16px;
font-weight: bold;
}
}
\ No newline at end of file
...@@ -3,6 +3,9 @@ module.exports = { ...@@ -3,6 +3,9 @@ module.exports = {
stories: ['../src/**/*.stories.tsx'], stories: ['../src/**/*.stories.tsx'],
addons:[ addons:[
"@storybook/addon-essentials", "@storybook/addon-essentials",
"@storybook/addon-info" // "@storybook/addon-info",
// "@storybook/addon-docs",
// "@storybook/addon-storysource",
] ]
}; };
\ No newline at end of file
import { themes } from '@storybook/theming'; import { themes } from '@storybook/theming';
import "codemirror/lib/codemirror.css";
import "codemirror/lib/codemirror.js";
import 'codemirror/mode/javascript/javascript';
import 'codemirror/theme/dracula.css';
import "codemirror/addon/fold/foldcode.js";
import "codemirror/addon/fold/foldgutter.js";
import "codemirror/addon/fold/brace-fold.js";
import "codemirror/addon/fold/comment-fold.js";
import "./global.less";
const customViewports = { const customViewports = {
kindleFire2: { kindleFire2: {
name: 'Kindle Fire 2', name: 'Kindle Fire 2',
...@@ -16,7 +28,7 @@ const customViewports = { ...@@ -16,7 +28,7 @@ const customViewports = {
}, },
}; };
export const parameters = { export const parameters = {
layout: 'fullscreen', layout: 'centered',
controls: { controls: {
matchers: { matchers: {
color: /(background|color)$/i, color: /(background|color)$/i,
...@@ -28,3 +40,4 @@ export const parameters = { ...@@ -28,3 +40,4 @@ export const parameters = {
}, },
viewport: { viewports: customViewports }, viewport: { viewports: customViewports },
}; };
.code{
background-color: #333333;
padding: 20px;
border-radius: 4px;
box-shadow: grey 0 0px 3px 0px, #333333 0 0 0 0px;
color: #FFFFFF;
font-size: 13px;
}
\ No newline at end of file
const path = require('path'); const path = require('path');
module.exports = ({config, mode}) => { module.exports = ({config, mode}) => {
config.module.rules.push({ config.module.rules.push({
test: /\.(less|css)$/, test: /\.less$/,
loaders: ["style-loader", "css-loader", "less-loader"], loaders: ["style-loader", "css-loader", "less-loader"],
include: path.resolve(__dirname, '../') include: path.resolve(__dirname, '../')
}); });
// config.module.rules.push( {
// test: /\.css$/,
// //user可为loader加入选项
// use: [
// 'style-loader',
// {loader: 'css-loader',options: {importLoaders: 1}},
// {loader: 'postcss-loader',options: {plugins: [require('autoprefixer')({browsers:["last 5 versions"]})]}}
// ],
// })
config.module.rules.push({ config.module.rules.push({
test: /\.(js|jsx|ts|tsx)$/, test: /\.(js|jsx|ts|tsx)$/,
loader: require.resolve('babel-loader'), loader: require.resolve('babel-loader'),
......
This diff is collapsed.
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
"main": "index.js", "main": "index.js",
"scripts": { "scripts": {
"test": "echo \"Error: no test specified\" && exit 1", "test": "echo \"Error: no test specified\" && exit 1",
"storybook": "start-storybook -p 9003 -c .storybook" "storybook": "start-storybook -s src/asserts -p 9003 -c .storybook"
}, },
"keywords": [], "keywords": [],
"author": "", "author": "",
...@@ -16,11 +16,13 @@ ...@@ -16,11 +16,13 @@
"@storybook/addon-essentials": "^6.3.2", "@storybook/addon-essentials": "^6.3.2",
"@storybook/addon-links": "^6.3.2", "@storybook/addon-links": "^6.3.2",
"@storybook/addon-notes": "^5.3.21", "@storybook/addon-notes": "^5.3.21",
"@storybook/addon-storysource": "^6.3.2",
"@storybook/addons": "^6.3.2", "@storybook/addons": "^6.3.2",
"@storybook/react": "^6.3.2", "@storybook/react": "^6.3.2",
"@types/storybook__react": "^5.2.1", "@types/storybook__react": "^5.2.1",
"babel-loader": "^8.2.2", "babel-loader": "^8.2.2",
"babel-plugin-import": "^1.13.3", "babel-plugin-import": "^1.13.3",
"highlight.js": "^10.6.0",
"storybook-readme": "^5.0.9", "storybook-readme": "^5.0.9",
"typescript": "^4.3.5", "typescript": "^4.3.5",
"webpack-combine-loaders": "^2.0.4" "webpack-combine-loaders": "^2.0.4"
...@@ -31,13 +33,18 @@ ...@@ -31,13 +33,18 @@
"@storybook/preset-ant-design": "^0.0.2", "@storybook/preset-ant-design": "^0.0.2",
"antd": "^4.16.6", "antd": "^4.16.6",
"babel-preset-react-app": "^10.0.0", "babel-preset-react-app": "^10.0.0",
"codemirror": "^5.62.0",
"css-loader": "5.2.6", "css-loader": "5.2.6",
"js-beautify": "^1.14.0",
"less": "3.13.1", "less": "3.13.1",
"less-loader": "5.0.0", "less-loader": "5.0.0",
"postcss-loader": "^6.1.1",
"react": "^17.0.2", "react": "^17.0.2",
"react-codemirror2": "^7.2.1",
"react-dom": "^17.0.2", "react-dom": "^17.0.2",
"resolve-url-loader": "^4.0.0", "resolve-url-loader": "^4.0.0",
"style-loader": "2.0.0", "save-dev": "0.0.1-security",
"style-loader": "^2.0.0",
"styled-components": "^5.3.0" "styled-components": "^5.3.0"
} }
} }
import React from 'react'; import React from 'react';
import { CarouselComponent } from "./carouseComponent"; import { CarouselComponent } from "./carouseComponent";
import { useEffect } from 'react';
import {createStage,isExistStage} from "../../common/createStage" import {createStage,isExistStage} from "../../common/createStage"
interface TestProps { interface TestProps {
/**item组件*/ /**item组件*/
...@@ -19,12 +20,12 @@ interface TestProps { ...@@ -19,12 +20,12 @@ interface TestProps {
} }
export const CarouselCom = (pros:TestProps)=>{ export const CarouselCom = (pros:TestProps)=>{
createStage(); createStage()
isExistStage(()=>{ isExistStage(()=>{
stage.removeAllChildren(); window.stage.removeAllChildren();
const carouseCom = new CarouselComponent(pros.carouselItem, pros.itemWidth, pros.itemHeight, pros.vertical, pros.num, pros.k); const {carouselItem,itemWidth,itemHeight,vertical,num,k} = pros
stage.addChild(carouseCom); const carouseCom = new CarouselComponent(carouselItem, itemWidth, itemHeight,vertical, num, k);
carouseCom.position.set(10,20) window.stage.addChild(carouseCom);
carouseCom.updateData(pros.data); carouseCom.updateData(pros.data);
}) })
return ( return (
......
import React from 'react';
import { UnControlled as CodeMirror } from 'react-codemirror2';
const jsBeautify = require("js-beautify").html;
interface Props {
code:string
}
const CodePanel =(args:Props) => {
return(
<div className = "code">
<CodeMirror value={args.code}
options = {{
mode:"javascript",
theme:"dracula",
lineNumbers: true,
lineWrapping: false,
indentWithTabs: true,
smartIndent: true,
}}
/>
</div>
)
}
export const CodeCom = ()=>{
let useCode = getUseCodeStr();
let sourceCode = getSourceCode();
let itemCode = getItemCodeStr();
return (
<div className = "codeContainer">
<label className="title">组件使用代码:</label>
<CodePanel code ={useCode}/>
<label className="title">carouselItem代码:</label>
<CodePanel code ={itemCode}/>
<label className="title">组件源码代码:</label>
<CodePanel code ={sourceCode}/>
</div>
)
}
const getItemCodeStr = ()=>{
return `
class carouselItem extends window.FYGE.Container {
constructor(data) {
super();
let itemBg = window.FYGE.Sprite.fromUrl("test/prizeItemBg.png");
this.addChild(itemBg);
let itemName = new window.FYGE.TextField();
itemName.text = data.name;
itemName.size = 24;
itemName.fillColor = "#000000";
itemName.textAlign = window.FYGE.TEXT_ALIGN.CENTER;
itemName.textWidth = itemBg.width;
this.addChild(itemName);
itemName.position.set(0, 200);
let itemImg = window.FYGE.Sprite.fromUrl(data.icon);
itemBg.addChild(itemImg);
itemImg.width = 183;
itemImg.height = 183;
itemImg.position.set(5, 5);
}
}
`
}
const getUseCodeStr = ()=>{
return `
const {carouselItem,itemWidth,itemHeight,vertical,num,k} = pros
const carouseCom = new CarouselComponent(carouselItem, itemWidth, itemHeight,vertical, num, k);
window.stage.addChild(carouseCom);
carouseCom.updateData(pros.data);
`
}
const getSourceCode = ()=>{
return `
export class CarouselComponent extends FYGE.Container {
bgContainer: FYGE.Container;
itemComponent: any;
itemWidth: number;
itemHeight: number;
vertical: boolean;
timer: any;
listContainer1: any;
listContainer2: any;
listWidth: number;
listHeight: number;
bgmask: FYGE.Graphics;
num: number;
k: number;//缓动系数,系数越大移动越快。在0-1之间。
totalStep: number;//累计移动了多少距离
stopStep: number;//滑动多少距离之后暂停一下
/**
*
* @param itemComponent //item组件
* @param itemWidth //每一个item的宽度
* @param itemHeight //每一个item的高度
* @param vertical //是否是垂直的
* @param num //要显示的个数
* @param k ////缓动系数,系数越大移动越快。在0-1之间
*/
constructor(itemComponent, itemWidth, itemHeight, vertical = false, num = 3, k = 0.24) {
super();
this.num = num;
this.totalStep = 0;
this.bgContainer = new FYGE.Container();
this.itemComponent = itemComponent;
this.itemHeight = itemHeight;
this.itemWidth = itemWidth;
this.vertical = vertical;
this.k = k;
if (this.vertical) {
this.stopStep = itemHeight;
this.bgmask = new FYGE.Graphics();
this.bgmask.beginFill();
this.bgmask.drawRect(0, 0, itemWidth, num * itemHeight)
this.bgmask.endFill();
} else {
this.stopStep = itemWidth;
this.bgmask = new FYGE.Graphics();
this.bgmask.beginFill();
this.bgmask.drawRect(0, 0, num * itemWidth, itemHeight)
this.bgmask.endFill();
}
}
//更新数据触发轮播
updateData(data) {
this.removeChildren();
this.bgContainer.removeChildren();
this.timer && clearTimeout(this.timer);
this.timer = null;
this.addChild(this.bgmask);
this.listContainer1 = new FYGE.Container();
this.listContainer2 = new FYGE.Container();
data.forEach((el, index) => {
let picture1 = new this.itemComponent(el);
let picture2 = new this.itemComponent(el);
if (!this.vertical) {
picture1.position.set(index * this.itemWidth, 0);
picture2.position.set(index * this.itemWidth, 0);
} else {
picture1.position.set(0, index * this.itemHeight);
picture2.position.set(0, index * this.itemHeight);
}
this.listContainer1.addChild(picture1);
this.listContainer2.addChild(picture2);
})
if (!this.vertical) {
this.listWidth = data.length * this.itemWidth;
this.listContainer1.position.set(0, 0)
this.listContainer2.position.set(data.length * this.itemWidth, 0)
} else {
this.listHeight = data.length * this.itemHeight;
this.listContainer1.position.set(0, 0)
this.listContainer2.position.set(0, data.length * this.itemHeight)
}
this.bgContainer.addChild(this.listContainer1);
this.bgContainer.addChild(this.listContainer2);
this.addChild(this.bgContainer);
this.bgContainer.mask = this.bgmask;
setTimeout(() => {
this.loop();
}, 1000)
}
loop() {
this.timer && clearTimeout(this.timer);
this.timer = null;
var step = (this.stopStep - this.totalStep) * this.k;
step = parseInt(step.toFixed(0))
step = step ? step : 1;
var sum = this.totalStep + step;
if (sum > this.stopStep) {
step = this.stopStep - this.totalStep;
}
// console.log(step)
if (!this.vertical) {
let x1 = this.listContainer1.x
let x2 = this.listContainer2.x
if (x1 + this.listWidth < 0) {
x1 = this.listWidth + (x1 + this.listWidth);
}
if (x2 + this.listWidth < 0) {
x2 = this.listWidth + (x2 + this.listWidth);
}
this.listContainer1.position.set(x1 - step, 0)
this.listContainer2.position.set(x2 - step, 0)
} else {
let y1 = this.listContainer1.y
let y2 = this.listContainer2.y
if (y1 + this.listHeight < 0) {
y1 = this.listHeight + (y1 + this.listHeight);
}
if (y2 + this.listHeight < 0) {
y2 = this.listHeight + (y2 + this.listHeight);
}
this.listContainer1.position.set(0, y1 - step)
this.listContainer2.position.set(0, y2 - step)
}
this.totalStep = this.totalStep + step
if (Math.abs(this.stopStep - this.totalStep) < 0.1) {
this.setTimeoutSelf(() => {
this.timer = this.setTimeoutSelf(() => {
this.loop()
}, 50)
}, 1000)
this.totalStep = 0;
} else {
this.timer = this.setTimeoutSelf(() => {
this.loop()
}, 50)
}
}
setTimeoutSelf(cb, interval) { // 实现setTimeout功能
let now = Date.now
let stime = now()
let etime = stime
let loop = () => {
var timeoutTimer = requestAnimationFrame(loop)
etime = now()
if (etime - stime >= interval) {
cb()
cancelAnimationFrame(timeoutTimer)
}
}
loop()
}
destroy() {
this.timer && clearTimeout(this.timer);
this.timer = null;
}
}
`
}
\ No newline at end of file
import React from 'react';
import { UnControlled as CodeMirror } from 'react-codemirror2';
const jsBeautify = require("js-beautify").html;
interface Props {
code:string
}
const CodePanel =(args:Props) => {
return(
<div className = "code">
<CodeMirror value={args.code}
options = {{
mode:"javascript",
theme:"dracula",
lineNumbers: true,
lineWrapping: false,
indentWithTabs: true,
smartIndent: true,
}}
/>
</div>
)
}
export const CodeCom = ()=>{
let useCode = getUseCodeStr();
let sourceCode = getSourceCode();
return (
<div className = "codeContainer">
<label className="title">组件使用代码:</label>
<CodePanel code ={useCode}/>
<label className="title">组件源码代码:</label>
<CodePanel code ={sourceCode}/>
</div>
)
}
//使用代码
const getUseCodeStr = ()=>{
return `
const goldCoinAni = new GoldCoinAni(pros.start, pros.end, pros.imgUrl, pros.callBack, pros.isMinus, pros.curvature, pros.goldNum, pros.coordNum);
window.stage.addChild(goldCoinAni);
goldCoinAni.triggerAni();
`
}
//源码
const getSourceCode = ()=>{
return`
export class GoldCoinAni extends FYGE.Container {
start: any;
end: any;
imgUrl: string; //金币的图标。
isMinus: boolean; //true为向上凸,false为向下凹。
startCallback: any; //第一个金币动效结束后的回调函数
endCallback: any; //最后一个金币动效结束后的回调函数
callback:any;
lineCoords: any; //根据起始点计算出来的贝赛曲线坐标。
curvature: number; //0-1之间,0代表直线,1代表最弯
goldNum: number; //动效上面金币个数。
time: number;//动效完成时间。
coordNum:any;//坐标串个数
/**
*
* @param start 动效起点,[120,30]
* @param end 动效终点,[120,30]
* @param imgUrl 动效图片
* @param callback 每一个金币动效结束时的回调
* @param isMinus true为向上凸,false为向下凹。
* @param curvature 0-1之间,0代表直线,1代表最弯
* @param goldNum 动效上面金币个数
* @param time 动效完成时间
* @param coordNum 路线上的坐标串个数
*/
constructor(
start,
end,
imgUrl,
callback?: (start,end) => void,
isMinus = false,
curvature = 0.8,
goldNum = 10,
time = 500,
coordNum = 50,
) {
super();
this.start = start;
this.end = end;
this.imgUrl = imgUrl;
this.curvature = curvature;
this.isMinus = isMinus;
this.goldNum = goldNum;
this.callback = callback;
this.coordNum = goldNum > coordNum? goldNum:coordNum;
this.time = Math.floor( time / this.coordNum );
this.initUi();
}
initUi() {}
/**
* 重设起点和终点
* @param start [120,30]
* @param end [120,30]
*/
triggerAni(start = null, end = null) {
if(start)this.start = start;
if(end) this.end = end;
this.lineCoords = this.getBeiSaiCoords(this.start, this.end);
this._produceGoldCoinAni(this.createNewGoldCoin,(goldCodeNum)=>{
this.callback && this.callback(goldCodeNum)
});
}
createNewGoldCoin = (goldNum) => {
this._produceGoldCoinAni(() => {},(goldCodeNum) => {this.callback && this.callback(goldCodeNum)},goldNum);
}
/**
*
* @param createNewGoldCoin 金币移动时的回调函数。
* @param callback 到达终点位置后的回调函数
* @param goldCodeNum 产生的金币编号。
*/
_produceGoldCoinAni(
createNewGoldCoin?: (goldNum: number) => void,
callback?: (goldCodeNum) => void,
goldCodeNum = 1
) {
let coin = FYGE.Sprite.fromUrl(this.imgUrl);
this.addChild(coin);
coin["goldCodeNum"] = goldCodeNum;
let index = 0;
let timer = null;
let x = Math.floor(this.lineCoords.length/this.goldNum);
var loop = () => {
timer && clearTimeout(timer);
if (index === this.lineCoords.length) {
callback && callback( coin["goldCodeNum"] );
this.removeChild(coin);
return;
}
coin.position.set(
this.lineCoords[index][0],
this.lineCoords[index][1]
);
if( goldCodeNum < this.goldNum && ((index+1)% x === 0) ){
goldCodeNum ++;
createNewGoldCoin && createNewGoldCoin(goldCodeNum);
}
index = index + 1;
timer = this.setTimeoutSelf(() => {
loop();
}, this.time);
};
loop();
}
setTimeoutSelf(cb, interval) { // 实现setTimeout功能
let now = Date.now
let stime = now()
let etime = stime
let loop = () => {
var timeoutTimer = requestAnimationFrame(loop)
etime = now()
if (etime - stime >= interval) {
cb()
cancelAnimationFrame(timeoutTimer)
}
}
loop()
}
/**
* 输入起点终点坐标,得到贝塞曲线坐标
* @param start
* @param end
*/
getBeiSaiCoords(start, end) {
let x1 = start[0];
let y1 = start[1];
let x2 = end[0];
let y2 = end[1];
let x3 = (x1 + x2) / 2 + (y1 - y2) * this.curvature;
let y3 = (y1 + y2) / 2 + (x2 - x1) * this.curvature;
if (this.isMinus) {
x3 = (x1 + x2) / 2 - (y1 - y2) * this.curvature;
y3 = (y1 + y2) / 2 - (x2 - x1) * this.curvature;
}
let coords = [];
let speed =Number(1/this.coordNum);
for (let t = 0; t <= 1; t += speed) {
var x = quadraticBezier(x1, x3, x2, t);
var y = quadraticBezier(y1, y3, y2, t);
coords.push([x, y]);
}
function quadraticBezier(p1, p3, p2, t) {
var k = 1 - t;
return k * k * p1 + 2 * (1 - t) * t * p3 + t * t * p2;
}
return coords;
}
}
`
}
\ No newline at end of file
import React from 'react'; import React from 'react';
import {GoldCoinAni} from "./goldCoinAni"; import {GoldCoinAni} from "./goldCoinAni";
import {createStage,isExistStage} from "../../common/createStage" import {createStage,isExistStage} from "../../common/createStage"
import { useEffect } from 'react';
interface TestProps { interface TestProps {
/**动效起点,[120,30] */ /**动效起点,[120,30] */
start: Array<number>; start: Array<number>;
...@@ -21,15 +22,12 @@ interface TestProps { ...@@ -21,15 +22,12 @@ interface TestProps {
/**路线上的坐标串个数 */ /**路线上的坐标串个数 */
coordNum?:number coordNum?:number
} }
const goldCoinReceiveAniCallback =(goldCode)=>{
console.log(goldCode);
}
export const GoldCoinCom = (pros:TestProps)=>{ export const GoldCoinCom = (pros:TestProps)=>{
createStage(); createStage()
isExistStage(()=>{ isExistStage(()=>{
stage.removeAllChildren(); window.stage.removeAllChildren();
const goldCoinAni = new GoldCoinAni(pros.start, pros.end, pros.imgUrl, pros.callBack, pros.isMinus, pros.curvature, pros.goldNum, pros.coordNum); const goldCoinAni = new GoldCoinAni(pros.start, pros.end, pros.imgUrl, pros.callBack, pros.isMinus, pros.curvature, pros.goldNum, pros.coordNum);
stage.addChild(goldCoinAni); window.stage.addChild(goldCoinAni);
goldCoinAni.triggerAni(); goldCoinAni.triggerAni();
}) })
return ( return (
......
import React from 'react'; import React from 'react';
import {PolygonAxiosSystem} from "./polygonAxiosSystem"; import {PolygonAxiosSystem} from "./polygonAxiosSystem";
import {createStage,isExistStage} from "../../common/createStage" import {createStage,isExistStage} from "../../common/createStage";
import { useEffect } from 'react';
interface TestProps { interface TestProps {
/**坐标系统中心点x坐标 */ /**坐标系统中心点x坐标 */
centerX: number; centerX: number;
...@@ -13,12 +14,12 @@ interface TestProps { ...@@ -13,12 +14,12 @@ interface TestProps {
/**坐标系统的单位长度,一个刻度多长 */ /**坐标系统的单位长度,一个刻度多长 */
unitLength:number; unitLength:number;
/**坐标系统顺时针旋转多少度,原坐标系统基准轴水平向右,也是drawShape传的第一个数值所在的坐标轴*/ /**坐标系统顺时针旋转多少度,原坐标系统基准轴水平向右,也是drawShape传的第一个数值所在的坐标轴*/
rotateDeg:number; rotateDeg?:number;
/**坐标轴名称,默认无 */ /**坐标轴名称,默认无 */
labels:Array<string>; labels?:Array<string>;
/**坐标系统样式*/ /**坐标系统样式*/
style:any; style?:any;
/**坐标值 */ /**坐标值:传到坐标系统中绘制出来的值,不属于构建坐标系统的参数 */
value:string; value:string;
} }
export const PolygonSystemCom = (args:TestProps)=>{ export const PolygonSystemCom = (args:TestProps)=>{
...@@ -34,8 +35,8 @@ export const PolygonSystemCom = (args:TestProps)=>{ ...@@ -34,8 +35,8 @@ export const PolygonSystemCom = (args:TestProps)=>{
args.labels, args.labels,
args.style args.style
); );
stage.removeAllChildren(); window.stage.removeAllChildren();
stage.addChild(polygonAxiosSystem); window.stage.addChild(polygonAxiosSystem);
console.log(args.value) console.log(args.value)
polygonAxiosSystem.updateData(args.value); polygonAxiosSystem.updateData(args.value);
}) })
......
This diff is collapsed.
// var aa = this.addChild(new RichText(
// [
// { text: "啊请问请问", style: { color: "#000000", size: 30 } },
// { text: "=2134324234啊请问请问", style: { color: "#ff0000", size: 30 } },
// { text: "驱蚊器问问", style: { color: "#000000", size: 30 } }
// ]
// ))
// aa.text = [
// { text: "啊请问请问", style: { color: "#000000", size: 30 } },
// { text: "=2134", style: { color: "#ff0000", size: 30 } },
// { text: "驱蚊器问问", style: { color: "#000000", size: 30 } }
// ]
// aa.position.set(375, 800);
// [{text: "测试",style:{color: ""}},{},{}]
interface IRichTextEle {
text: string,
style: { color: string, size: number }
}
export class RichText extends FYGE.Container {
private static cache: FYGE.TextField[] = []
/**
*
* @param text
*/
constructor(text?: IRichTextEle[]) {
super()
if (text) this.text = text;
}
/**
* 水平对齐方式,默认居中
*/
get textAlign() {
return this._textAlign
}
set textAlign(value: FYGE.TEXT_ALIGN) {
if (this._textAlign !== value) {
this._textAlign = value;
this.adaptate();
}
}
private _textAlign: FYGE.TEXT_ALIGN = FYGE.TEXT_ALIGN.CENTER;
/**
* 垂直居中方式,默认居中
*/
get verticalAlign() {
return this._verticalAlign
}
set verticalAlign(value: FYGE.VERTICAL_ALIGN) {
if (this._verticalAlign !== value) {
this._verticalAlign = value;
this.adaptate();
}
}
private _verticalAlign: FYGE.VERTICAL_ALIGN = FYGE.VERTICAL_ALIGN.MIDDLE;
/**
* 文字间隙
*/
get gap(): number {
return this._gap;
};
set gap(value: number) {
if (this._gap != value) {
this._gap = value;
this.adaptate();
}
};
private _gap: number = 0;
/**
* 文本
*/
private _text: IRichTextEle[];
/**
* 按顺序
*/
get text(): IRichTextEle[] {
return this._text
}
/**
*
*/
set text(value: IRichTextEle[]) {
this._text = value;
var arr = value || [];
for (var i = 0; i < arr.length; i++) {
let a = arr[i];
let c: FYGE.TextField = this.children[i] || this.addChild(RichText.cache.shift() || new FYGE.TextField());
c.text = a.text;
c.fillColor = a.style.color;
c.size = a.style.size;
}
//如果多了,去掉后面的,回收
if (this.children.length > arr.length) {
//移除后序
for (var i = this.children.length - 1; i >= arr.length; i--) {
let c = this.children[i];
this.removeChild(c);
RichText.cache.push(c);
}
}
//适配
this.adaptate()
}
/**
* 适配,
*/
private adaptate() {
if (!this.children.length) return
var len = this.children.length;
//算总长度
var sum = 0;
for (var m = 0; m < len; m++) {
sum += this.children[m].textWidth;
}
sum += (len - 1) * this._gap;
//算出左边第一个元素的位置
var left: number;
if (this._textAlign == FYGE.TEXT_ALIGN.LEFT) {
left = 0
}
else if (this._textAlign == FYGE.TEXT_ALIGN.RIGHT) {
left = -sum
} else {
left = -sum / 2
}
var temSum = 0;
for (var i = 0; i < this.children.length; i++) {
this.children[i].x = left + temSum
temSum += this.children[i].textWidth + this._gap;
}
var up: number;
if (this._verticalAlign == FYGE.VERTICAL_ALIGN.UP) {
up = 0
}
else if (this._verticalAlign == FYGE.VERTICAL_ALIGN.DOWN) {
up = -1
} else {
up = -1 / 2
}
for (var i = 0; i < this.children.length; i++) {
this.children[i].y = this.children[i].textHeight * up;
}
}
}
\ No newline at end of file
import React from 'react';
import {RichText} from "./RichText";
import {createStage,isExistStage} from "../../common/createStage";
import { useEffect } from 'react';
interface TestProps {
/** 要展示的文本内容 */
textArr:Array<any>;
/** 文本中心点的x坐标 */
x:number;
/** 文本中心点的y坐标 */
y:number;
}
export const RichTextCom = (args:TestProps)=>{
createStage();
isExistStage(()=>{
window.stage.removeAllChildren();
const richText = new RichText();
richText.position.set(args.x,args.y)
richText.text = args.textArr;
window.stage.addChild(richText);
})
return (
<div></div>
)
}
\ No newline at end of file
import React from 'react';
import { UnControlled as CodeMirror } from 'react-codemirror2';
const jsBeautify = require("js-beautify").html;
interface Props {
code:string
}
const CodePanel =(args:Props) => {
return(
<div className = "code">
<CodeMirror value={args.code}
options = {{
mode:"javascript",
theme:"dracula",
lineNumbers: true,
lineWrapping: false,
indentWithTabs: true,
smartIndent: true,
}}
/>
</div>
)
}
export const CodeCom = ()=>{
let useCode = getUseCodeStr();
let sourceCode = getSourceCode();
return (
<div className = "codeContainer">
<label className="title">组件使用代码:</label>
<CodePanel code ={useCode}/>
<label className="title">组件源码代码:</label>
<CodePanel code ={sourceCode}/>
</div>
)
}
//使用代码
const getUseCodeStr = ()=>{
return `
const richText = new RichText();
richText.position.set(args.x,args.y)
richText.text = args.textArr;
window.stage.addChild(richText);
`
}
//源码
const getSourceCode = ()=>{
return`
// var aa = this.addChild(new RichText(
// [
// { text: "啊请问请问", style: { color: "#000000", size: 30 } },
// { text: "=2134324234啊请问请问", style: { color: "#ff0000", size: 30 } },
// { text: "驱蚊器问问", style: { color: "#000000", size: 30 } }
// ]
// ))
// aa.text = [
// { text: "啊请问请问", style: { color: "#000000", size: 30 } },
// { text: "=2134", style: { color: "#ff0000", size: 30 } },
// { text: "驱蚊器问问", style: { color: "#000000", size: 30 } }
// ]
// aa.position.set(375, 800);
// [{text: "测试",style:{color: ""}},{},{}]
interface IRichTextEle {
text: string,
style: { color: string, size: number }
}
export class RichText extends FYGE.Container {
private static cache: FYGE.TextField[] = []
/**
*
* @param text
*/
constructor(text?: IRichTextEle[]) {
super()
if (text) this.text = text;
}
/**
* 水平对齐方式,默认居中
*/
get textAlign() {
return this._textAlign
}
set textAlign(value: FYGE.TEXT_ALIGN) {
if (this._textAlign !== value) {
this._textAlign = value;
this.adaptate();
}
}
private _textAlign: FYGE.TEXT_ALIGN = FYGE.TEXT_ALIGN.CENTER;
/**
* 垂直居中方式,默认居中
*/
get verticalAlign() {
return this._verticalAlign
}
set verticalAlign(value: FYGE.VERTICAL_ALIGN) {
if (this._verticalAlign !== value) {
this._verticalAlign = value;
this.adaptate();
}
}
private _verticalAlign: FYGE.VERTICAL_ALIGN = FYGE.VERTICAL_ALIGN.MIDDLE;
/**
* 文字间隙
*/
get gap(): number {
return this._gap;
};
set gap(value: number) {
if (this._gap != value) {
this._gap = value;
this.adaptate();
}
};
private _gap: number = 0;
/**
* 文本
*/
private _text: IRichTextEle[];
/**
* 按顺序
*/
get text(): IRichTextEle[] {
return this._text
}
/**
*
*/
set text(value: IRichTextEle[]) {
this._text = value;
var arr = value || [];
for (var i = 0; i < arr.length; i++) {
let a = arr[i];
let c: FYGE.TextField = this.children[i] || this.addChild(RichText.cache.shift() || new FYGE.TextField());
c.text = a.text;
c.fillColor = a.style.color;
c.size = a.style.size;
}
//如果多了,去掉后面的,回收
if (this.children.length > arr.length) {
//移除后序
for (var i = this.children.length - 1; i >= arr.length; i--) {
let c = this.children[i];
this.removeChild(c);
RichText.cache.push(c);
}
}
//适配
this.adaptate()
}
/**
* 适配,
*/
private adaptate() {
if (!this.children.length) return
var len = this.children.length;
//算总长度
var sum = 0;
for (var m = 0; m < len; m++) {
sum += this.children[m].textWidth;
}
sum += (len - 1) * this._gap;
//算出左边第一个元素的位置
var left: number;
if (this._textAlign == FYGE.TEXT_ALIGN.LEFT) {
left = 0
}
else if (this._textAlign == FYGE.TEXT_ALIGN.RIGHT) {
left = -sum
} else {
left = -sum / 2
}
var temSum = 0;
for (var i = 0; i < this.children.length; i++) {
this.children[i].x = left + temSum
temSum += this.children[i].textWidth + this._gap;
}
var up: number;
if (this._verticalAlign == FYGE.VERTICAL_ALIGN.UP) {
up = 0
}
else if (this._verticalAlign == FYGE.VERTICAL_ALIGN.DOWN) {
up = -1
} else {
up = -1 / 2
}
for (var i = 0; i < this.children.length; i++) {
this.children[i].y = this.children[i].textHeight * up;
}
}
}
`
}
\ No newline at end of file
import React from 'react'; import React from 'react';
import { CarouselCom } from '../canvasCom/carouselCom/carouselCom'; import { CarouselCom } from '../canvasCom/carouselCom/carouselCom';
import { CodeCom } from "../canvasCom/carouselCom/codeCom"
class carouselItem extends FYGE.Container { import {
Title,
Subtitle,
Description,
ArgsTable,
PRIMARY_STORY,
} from '@storybook/addon-docs';
import { clearStage } from '../common/createStage';
class carouselItem extends window.FYGE.Container {
constructor(data) { constructor(data) {
super(); super();
let itemBg = FYGE.Sprite.fromUrl("//yun.duiba.com.cn/spark/assets/029a53c6dc60b0c3a4538862cbeb0e3a329152f4.png"); let itemBg = window.FYGE.Sprite.fromUrl("test/prizeItemBg.png");
this.addChild(itemBg); this.addChild(itemBg);
let itemName = new FYGE.TextField(); let itemName = new window.FYGE.TextField();
itemName.text = data.name; itemName.text = data.name;
itemName.size = 24; itemName.size = 24;
itemName.fillColor = "#000000"; itemName.fillColor = "#000000";
itemName.textAlign = FYGE.TEXT_ALIGN.CENTER; itemName.textAlign = window.FYGE.TEXT_ALIGN.CENTER;
itemName.textWidth = itemBg.width; itemName.textWidth = itemBg.width;
this.addChild(itemName); this.addChild(itemName);
itemName.position.set(0, 200); itemName.position.set(0, 200);
let itemImg = FYGE.Sprite.fromUrl(data.icon); let itemImg = window.FYGE.Sprite.fromUrl(data.icon);
itemBg.addChild(itemImg); itemBg.addChild(itemImg);
itemImg.width = 183; itemImg.width = 183;
itemImg.height = 183; itemImg.height = 183;
...@@ -26,12 +34,38 @@ export default { ...@@ -26,12 +34,38 @@ export default {
title: 'Canvas组件/轮播组件', title: 'Canvas组件/轮播组件',
//👇 Creates specific argTypes //👇 Creates specific argTypes
argTypes: { argTypes: {
backgroundColor: { control: 'color' }, label: {
description: 'Overwritten description',
table: {
type: {
summary: 'Something short',
detail: 'Something really really long'
},
},
control: {
type: null,
},
},
}, },
args: { args: {
//👇 Now all Button stories will be primary. //👇 Now all Button stories will be primary.
primary: true, primary: false,
},
parameters: {
docs: {
page: () => {
clearStage();
return( <>
<Title />
<Subtitle />
<Description />
<ArgsTable story={PRIMARY_STORY} />
<CodeCom/>
</>)
}, },
}
},
}; };
//👇 We create a “template” of how args map to rendering //👇 We create a “template” of how args map to rendering
const Template = (args) => <CarouselCom {...args} />; const Template = (args) => <CarouselCom {...args} />;
...@@ -54,7 +88,7 @@ Primary.args = { ...@@ -54,7 +88,7 @@ Primary.args = {
{ {
"rule": "ru_1", "rule": "ru_1",
"name": "飞科剃须刀1", "name": "飞科剃须刀1",
"icon": "//yun.duiba.com.cn/polaris/一波1.8644720387778750b4af371deb5f86562897aab2.jpg", "icon": "prize.jpg",
"coins": 10000, "coins": 10000,
"stock": 111111111111, "stock": 111111111111,
"channel":0 "channel":0
...@@ -62,7 +96,7 @@ Primary.args = { ...@@ -62,7 +96,7 @@ Primary.args = {
{ {
"rule": "ru_1", "rule": "ru_1",
"name": "飞科剃须刀2", "name": "飞科剃须刀2",
"icon": "//yun.duiba.com.cn/polaris/一波1.8644720387778750b4af371deb5f86562897aab2.jpg", "icon": "prize.jpg",
"coins": 100, "coins": 100,
"stock": 0, "stock": 0,
"channel":0 "channel":0
...@@ -70,7 +104,7 @@ Primary.args = { ...@@ -70,7 +104,7 @@ Primary.args = {
{ {
"rule": "ru_1", "rule": "ru_1",
"name": "飞科剃须刀3", "name": "飞科剃须刀3",
"icon": "//yun.duiba.com.cn/polaris/一波1.8644720387778750b4af371deb5f86562897aab2.jpg", "icon": "prize.jpg",
"coins": 100, "coins": 100,
"stock": 0, "stock": 0,
"channel":0 "channel":0
...@@ -78,7 +112,7 @@ Primary.args = { ...@@ -78,7 +112,7 @@ Primary.args = {
{ {
"rule": "ru_1", "rule": "ru_1",
"name": "飞科剃须刀4", "name": "飞科剃须刀4",
"icon": "//yun.duiba.com.cn/polaris/一波1.8644720387778750b4af371deb5f86562897aab2.jpg", "icon": "prize.jpg",
"coins": 100, "coins": 100,
"stock": 0, "stock": 0,
"channel":2 "channel":2
...@@ -86,7 +120,7 @@ Primary.args = { ...@@ -86,7 +120,7 @@ Primary.args = {
{ {
"rule": "ru_1", "rule": "ru_1",
"name": "飞科剃须刀5", "name": "飞科剃须刀5",
"icon": "//yun.duiba.com.cn/polaris/一波1.8644720387778750b4af371deb5f86562897aab2.jpg", "icon": "prize.jpg",
"coins": 100, "coins": 100,
"stock": 0, "stock": 0,
"channel":2 "channel":2
...@@ -94,7 +128,7 @@ Primary.args = { ...@@ -94,7 +128,7 @@ Primary.args = {
{ {
"rule": "ru_1", "rule": "ru_1",
"name": "飞科剃须刀6", "name": "飞科剃须刀6",
"icon": "//yun.duiba.com.cn/polaris/一波1.8644720387778750b4af371deb5f86562897aab2.jpg", "icon": "prize.jpg",
"coins": 100, "coins": 100,
"stock": 0, "stock": 0,
"channel":1 "channel":1
...@@ -102,7 +136,7 @@ Primary.args = { ...@@ -102,7 +136,7 @@ Primary.args = {
{ {
"rule": "ru_1", "rule": "ru_1",
"name": "飞科剃须刀7", "name": "飞科剃须刀7",
"icon": "//yun.duiba.com.cn/polaris/一波1.8644720387778750b4af371deb5f86562897aab2.jpg", "icon": "prize.jpg",
"coins": 100, "coins": 100,
"stock": 1, "stock": 1,
"channel":0 "channel":0
...@@ -110,7 +144,7 @@ Primary.args = { ...@@ -110,7 +144,7 @@ Primary.args = {
{ {
"rule": "ru_1", "rule": "ru_1",
"name": "飞科剃须刀8", "name": "飞科剃须刀8",
"icon": "//yun.duiba.com.cn/polaris/一波1.8644720387778750b4af371deb5f86562897aab2.jpg", "icon": "prize.jpg",
"coins": 100, "coins": 100,
"stock": 1, "stock": 1,
"channel":2 "channel":2
...@@ -118,7 +152,7 @@ Primary.args = { ...@@ -118,7 +152,7 @@ Primary.args = {
{ {
"rule": "ru_1", "rule": "ru_1",
"name": "飞科剃须刀0", "name": "飞科剃须刀0",
"icon": "//yun.duiba.com.cn/polaris/一波1.8644720387778750b4af371deb5f86562897aab2.jpg", "icon": "prize.jpg",
"coins": 100, "coins": 100,
"stock": 1, "stock": 1,
"channel":2 "channel":2
......
import React from 'react'; import React from 'react';
import { GoldCoinCom } from '../canvasCom/goldCoinCom/GoldCoinCom.tsx'; import { GoldCoinCom } from '../canvasCom/goldCoinCom/GoldCoinCom';
import { CodeCom } from '../canvasCom/goldCoinCom/codeCom';
import {
Title,
Subtitle,
Description,
ArgsTable,
PRIMARY_STORY,
} from '@storybook/addon-docs';
import { clearStage } from '../common/createStage';
export default { export default {
component: GoldCoinCom, component: GoldCoinCom,
title: 'Canvas组件/金币动效', title: 'Canvas组件/金币动效',
//👇 Creates specific argTypes //👇 Creates specific argTypes
argTypes: { argTypes: {
backgroundColor: { control: 'color' }, label: {
description: 'Overwritten description',
table: {
type: {
summary: 'Something short',
detail: 'Something really really long'
}, },
args: {
//👇 Now all Button stories will be primary.
primary: true,
}, },
control: {
type: null,
},
},
},
parameters: {
docs: {
page: () => {
clearStage();
return( <>
<Title />
<Subtitle />
<Description />
<ArgsTable story={PRIMARY_STORY} />
<CodeCom></CodeCom>
</>)
},
}
},
}; };
const goldCoinReceiveAniCallback =(goldCode)=>{ const goldCoinReceiveAniCallback =(goldCode)=>{
console.log(goldCode);
} }
//👇 We create a “template” of how args map to rendering //👇 We create a “template” of how args map to rendering
const Template = (args) => <GoldCoinCom {...args} />; const Template = (args) => <GoldCoinCom {...args} />;
...@@ -22,13 +53,19 @@ const Template = (args) => <GoldCoinCom {...args} />; ...@@ -22,13 +53,19 @@ const Template = (args) => <GoldCoinCom {...args} />;
export const Primary = Template.bind({}); export const Primary = Template.bind({});
Primary.parameters = { Primary.parameters = {
layout: 'centered', layout: 'centered',
backgrounds: {
values: [
{ name: 'red', value: '#f00' },
{ name: 'green', value: '#0f0' },
],
},
}; };
Primary.args = { Primary.args = {
primary: true, primary: true,
label: '金币动效', label: '金币动效',
start:[100, 200], start:[100, 200],
end:[516, 200], end:[516, 200],
imgUrl:"//yun.duiba.com.cn/spark/assets/eed18886070638f6119f04ba849cf93e23e0d186.png", imgUrl:"homeGoldIconImg.png",
callBack: goldCoinReceiveAniCallback.bind(this), callBack: goldCoinReceiveAniCallback.bind(this),
isMinus:true, isMinus:true,
curvature:0.2, curvature:0.2,
......
import React from 'react'; import React from 'react';
import { PolygonSystemCom } from '../canvasCom/polygonSystemCom/PolygonSystemCom.tsx'; import { PolygonSystemCom } from '../canvasCom/polygonSystemCom/PolygonSystemCom';
import {CodeCom} from "../canvasCom/polygonSystemCom/codeCom"
import {
Title,
Subtitle,
Description,
ArgsTable,
PRIMARY_STORY,
} from '@storybook/addon-docs';
import { clearStage } from '../common/createStage';
export default { export default {
component: PolygonSystemCom, component: PolygonSystemCom,
title: 'Canvas组件/多变形坐标系统', title: 'Canvas组件/多变形坐标系统',
//👇 Creates specific argTypes //👇 Creates specific argTypes
argTypes: { argTypes: {
backgroundColor: { control: 'color' }, label: {
description: 'Overwritten description',
table: {
type: {
summary: 'Something short',
detail: 'Something really really long'
},
},
control: {
type: null,
}, },
args: { },
//👇 Now all Button stories will be primary. },
primary: true, parameters: {
docs: {
page: () => {
clearStage();
return( <>
<Title />
<Subtitle />
<Description />
<ArgsTable story={PRIMARY_STORY} />
<CodeCom></CodeCom>
</>)
},
}
}, },
}; };
...@@ -30,7 +61,7 @@ Primary.args = { ...@@ -30,7 +61,7 @@ Primary.args = {
axiosNodeNum:3, //3个坐标节点 axiosNodeNum:3, //3个坐标节点
unitLength:30, //坐标系统的单位长度,一个刻度多长。 unitLength:30, //坐标系统的单位长度,一个刻度多长。
rotateDeg:90, rotateDeg:90,
labels:["haha","heihei"], labels:["haha","heihei","heihei"],
value:"70,100,90", value:"70,100,90",
style:{ style:{
gridStyle: { gridStyle: {
...@@ -45,7 +76,6 @@ Primary.args = { ...@@ -45,7 +76,6 @@ Primary.args = {
color: "#7c3c23", color: "#7c3c23",
size: 24, size: 24,
}, },
}
}
}; };
import React from 'react';
import { RichTextCom } from '../canvasCom/richTextCom/RichTextCom';
import { CodeCom } from '../canvasCom/richTextCom/codeCom';
import {
Title,
Subtitle,
Description,
ArgsTable,
PRIMARY_STORY,
} from '@storybook/addon-docs';
import { clearStage } from '../common/createStage';
export default {
component: RichTextCom,
title: 'Canvas组件/丰富文本',
//👇 Creates specific argTypes
argTypes: {
label: {
description: 'Overwritten description',
table: {
type: {
summary: 'Something short',
detail: 'Something really really long'
},
},
control: {
type: null,
},
},
},
parameters: {
docs: {
page: () => {
clearStage();
return( <>
<Title />
<Subtitle />
<Description />
<ArgsTable story={PRIMARY_STORY} />
<CodeCom></CodeCom>
</>)
},
}
},
};
//👇 We create a “template” of how args map to rendering
const Template = (args) => <RichTextCom {...args} />;
//👇 Each story then reuses that template
export const Primary = Template.bind({});
Primary.parameters = {
layout: 'centered',
backgrounds: {
values: [
{ name: 'red', value: '#f00' },
{ name: 'green', value: '#0f0' },
],
},
};
Primary.args = {
primary: true,
label: '丰富文本',
textArr: [
{ text: "啊请问请问", style: { color: "#00FF7F", size: 30 } },
{ text: "=2134324234啊请问请问", style: { color: "#ff0000", size: 30 } },
{ text: "驱蚊器问问", style: { color: "#9932CC", size: 30 } }
],
x:400,
y:100,
};
export const createStage = ()=>{ export const createStage = ()=>{
const height = document.body.clientHeight*(window.devicePixelRatio || 1)||1624; const height = document.body.clientHeight*(window.devicePixelRatio || 1)||1624;
const width = document.body.clientWidth*(window.devicePixelRatio || 1)||750; const width = document.body.clientWidth*(window.devicePixelRatio || 1)||750;
console.log("ssssss",document.body.clientHeight,document.body.clientWidth) // const height = 800;
let canvas = document.getElementById("canvas-container") // const width = 750;
const scale = window.devicePixelRatio;
let canvas = document.getElementById("canvas-container");
if(!canvas){ if(!canvas){
canvas = document.createElement("canvas"); canvas = document.createElement("canvas");
canvas.setAttribute("id","canvas-container") canvas.setAttribute("id","canvas-container")
canvas.setAttribute("height",height+""); canvas.setAttribute("height",height+"");
canvas.setAttribute("width",width+""); canvas.setAttribute("width",width+"");
canvas.style.position = "absolute";
canvas.style.top = 0 + "px";
canvas.style.left = 0 + "px";
document.body.appendChild(canvas); document.body.appendChild(canvas);
}else{ }else{
return; return;
} }
var stage = new FYGE.Stage( var stage = new window.FYGE.Stage(
canvas, canvas,
width, width,
height, height,
document.body.clientWidth, width,
document.body.clientHeight, height,
FYGE.RENDERER_TYPE.CANVAS, window.FYGE.RENDERER_TYPE.CANVAS,
false, false,
false false
) )
...@@ -31,7 +38,7 @@ export const createStage = ()=>{ ...@@ -31,7 +38,7 @@ export const createStage = ()=>{
canvas.addEventListener("click",mouseEvent,false); canvas.addEventListener("click",mouseEvent,false);
function loop() { function loop() {
stage.flush(); stage.flush();
FYGE.Tween.flush(); window.FYGE.Tween.flush();
requestAnimationFrame(loop); requestAnimationFrame(loop);
} }
...@@ -39,8 +46,8 @@ export const createStage = ()=>{ ...@@ -39,8 +46,8 @@ export const createStage = ()=>{
window.stage = stage; window.stage = stage;
} }
export const isExistStage = (cb)=>{ export const isExistStage = (cb)=>{
if(stage){ if(window.stage){
cb(); cb && cb();
}else{ }else{
setTimeout(isExistStage,100); setTimeout(isExistStage,100);
} }
......
interface Window {
FYGE: any;
stage: any;
}
\ No newline at end of file
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