zoukankan      html  css  js  c++  java
  • 自写一个ant-design-pro AnimationList组件

    ant design蚂蚁金服基于react打造的一个服务于企业级产品的UI框架。而ant design pro呢?就是基于Ant Design这个框架搭建的中后台管理控制台的脚手架。

    话不多说,今天给大家分享一个自己写的一个组件。

    源码如下:

    index.tsx文件:

      1 import React,{Fragment} from 'react';
      2 import styles from './index.less'; 
      3 import undefined from '@/e2e/__mocks__/antd-pro-merge-less';
      4 export interface State {
      5     list:Array<any>,
      6     cacheList:Array<any>,
      7     eventIF:boolean,
      8 }
      9 export interface Props {
     10      style?:any,
     11      styleSon?:any,
     12      val?:valFrom,
     13      dataSource?:Array<dataSource>,
     14      onClickSon?:any,
     15      onMouseEnterSon?:any,
     16      onMouseLeaveSon?:any
     17  }
     18 interface valFrom{
     19     type?:TYPE|string,//动画类型
     20     direction?:DIRECTION|string,//方向
     21     time?:number,//时间 单位s
     22     delay?:number,//动画执行前的延时时间 单位s
     23     sonDelay?:number//列表子项动画延时
     24     domId?:string,//事件绑定dom id
     25     event?:EVENT|string,//动画执行事件
     26     hideModel?:boolean//背景是否显示
     27 
     28 } 
     29 export const enum TYPE{FADEIN}
     30 export const enum DIRECTION{TOP,BUTTOM,LEFT,REGIST,TOPLEFT,TOPREGIST,BUTTOMLEFT,BUTTOMREGIST}
     31 export const enum EVENT{CLICK,MOUSEENTER}
     32 interface dataSource{keys:any,title:any,style?:any}
     33 export class Father extends React.Component<Props, State> {
     34     constructor(props: Props) {
     35         super(props);
     36         this.state = { 
     37             list:[],//列表项
     38             cacheList:[],//暂时存储,观望是否绑定dom
     39             eventIF:false,//是否触发了event事件
     40         };
     41         if(this.props.val !== undefined){
     42             const val:valFrom = this.props.val;
     43             if(this.props.val.type != undefined && !(val.type===TYPE.FADEIN || val.type==="fadeIn")){
     44                 throw Error(`type定义错误:错误值为 ${val.type},type取值为{enum:TYPE,'fadeIn'}`,);
     45             }
     46             if(this.props.val.direction != undefined && !(val.direction === DIRECTION.TOP || val.direction === DIRECTION.BUTTOM || 
     47                 val.direction === DIRECTION.LEFT||val.direction === DIRECTION.REGIST || val.direction === DIRECTION.TOPLEFT ||
     48                 val.direction === DIRECTION.TOPREGIST || val.direction === DIRECTION.BUTTOMLEFT || val.direction === DIRECTION.BUTTOMREGIST ||
     49                 val.direction === 'top' || val.direction === 'buttom' || val.direction=== 'left' || val.direction === 'regist' ||
     50                 val.direction=== 'topLeft' || val.direction === 'topRegist' || val.direction === 'buttomLeft' || val.direction === 'buttomRegist')){
     51                 throw Error(`direction定义错误:错误值为 ${val.direction},direction取值为{enum:DIRECTION,'top','buttom','left','regist',
     52                 'topLeft','topRegist','buttomLeft','buttomRegist'}`);
     53             }
     54             window.onload = function(){
     55                 if(val.domId !== undefined){    
     56                     if(document.getElementById(val.domId)===undefined || document.getElementById(val.domId)===null){
     57                         throw Error(`指定id的DOM元素不存在!`,);
     58                     }
     59                     if(val.event === undefined){
     60                         console.warn(`指定DOM元素情况下未指定绑定事件event!`);
     61                     }
     62                 } 
     63             }
     64             if(val.event !== undefined){
     65                 if(!(val.event === EVENT.CLICK || val.event === EVENT.MOUSEENTER  || val.event === 'click' ||
     66                 val.event === 'mouseEnter')){
     67                     throw Error(`event定义错误:错误值为 ${val.event},event取值为{enum:EVENT,'click','mouseEnter'}`,);
     68                 }
     69                 if(val.domId === undefined){
     70                     console.warn(`绑定事件后未指定DOM元素!`);
     71                 }
     72             }
     73         }  
     74     }
     75     isWidth=(strs:Array<any>):number=>{
     76         let str : Array<string> = [];
     77         for(let i=0;i<strs.length;i++){
     78             if(strs[i].type!==undefined && strs[i].type===Son){
     79                 str.push(strs[i].props.children);
     80             }
     81         }
     82         let max:number = 0;
     83         let reg:RegExp =  /[u4E00-u9FA5uF900-uFA2D]/i;
     84         str.forEach(element => {
     85             let forMax = 0;
     86             for(let i=0;i<element.length;i++){
     87                 if(reg.test(element.charAt(i))){
     88                     forMax+=2;
     89                 }else{
     90                     forMax++;
     91                 }
     92             }
     93             if(forMax > max){
     94                 max = forMax;
     95             }
     96         });
     97         return max;
     98     }
     99     isWidth1=(maxWidth:number,data:Array<dataSource>):number=>{
    100         let max:number = maxWidth;
    101         let reg:RegExp =  /[u4E00-u9FA5uF900-uFA2D]/i;
    102         data.forEach(element => {
    103             let forMax = 0;
    104             for(let i=0;i<element.title.length;i++){
    105                 if(reg.test(element.title.charAt(i))){
    106                     forMax+=2;
    107                 }else{
    108                     forMax++;
    109                 }
    110             }
    111             if(forMax > max){
    112                 max = forMax;
    113             }
    114         });
    115         return max;
    116     }
    117     setList=():void=>{
    118         //清零
    119         this.state.list.length = 0;
    120         const list = [...this.state.cacheList];
    121         this.setState({list,eventIF:true});
    122         //解除绑定
    123         if(this.props.val != undefined && this.props.val.domId != undefined){
    124             let dom:any = document.getElementById(this.props.val.domId);
    125             let event:string = "click";
    126             if(this.props.val.event === EVENT.MOUSEENTER){
    127                 event = "mouseenter";
    128             }
    129             dom.removeEventListener(event,this.setList);        
    130         }
    131     }
    132     bindEvent=(val:any):void=>{
    133         if(this.props.val != undefined && this.props.val.domId != undefined && this.props.val.event != undefined){
    134             const dom:any = document.getElementById(this.props.val.domId);
    135             let event:string = "click";
    136             if(this.props.val.event === EVENT.MOUSEENTER){
    137                 event = "mouseenter";
    138             }
    139             dom.addEventListener(event,this.setList);                
    140         }
    141     }
    142     render() { 
    143         //默认动画效果
    144         const defVal:valFrom = {
    145             type:TYPE.FADEIN,
    146             direction:DIRECTION.LEFT,
    147             time:.5,
    148             sonDelay:.1,
    149             delay:0,
    150         };
    151         const defV = {...defVal,...this.props.val}
    152         //Son项数
    153         let index:number = 0;
    154         //最大文字占格
    155         let number=0;
    156         //字体大小
    157         let fontSize:number = 13;
    158         //Son高度
    159         let formatHeight:number = 26;
    160         //Father及Son宽度
    161         let formatWidth:number = 0;
    162        
    163         let sonStr:any = this.props.children;
    164         // //宽高自适应
    165         if(this.props.children != undefined){
    166             width = this.isWidth(sonStr);
    167         }
    168         if(this.props.dataSource != undefined){
    169             width = this.isWidth1(width,this.props.dataSource);
    170         }
    171         fontSize = this.props.style!==undefined && this.props.style.fontSize!==undefined?Number.parseInt(this.props.style.fontSize):13;
    172         formatHeight = fontSize*2;
    173         formatWidth = fontSize*width*0.6;
    174         
    175         //绑定dom后是否隐藏模板
    176         let hideModel = "visible";
    177         if(!this.state.eventIF){
    178             //清零
    179             this.state.list.length = 0;
    180             this.state.cacheList.length = 0;
    181             //子项写入
    182             if(this.props.children != null && this.props.children != undefined){  
    183                 for(let i=0;i<sonStr.length;i++){
    184                     if(sonStr[i].type!==undefined && sonStr[i].type===Son){
    185                         this.state.cacheList.push(<List title={sonStr[i].props.children} style={sonStr[i].props.style} styleSon={this.props.styleSon}
    186                         animation={defV} index={index++} formatHeight={formatHeight}
    187                         formatWidth = {formatWidth} keys={this.props.children[i].props.keys !==undefined?
    188                         this.props.children[i].props.keys:Number.MAX_VALUE-i} onClick={this.props.children[i].props.onClick}
    189                         onClickSon={this.props.onClickSon} onMouseEnter={this.props.children[i].props.onMouseEnter}
    190                         onMouseEnterSon={this.props.onMouseEnterSon} onMouseLeave={this.props.children[i].props.onMouseLeave}
    191                         onMouseLeaveSon={this.props.onMouseLeaveSon}/>);
    192                     }
    193                 }
    194             }
    195             if(this.props.dataSource !== undefined){
    196                 for(let i=0;i<this.props.dataSource.length;i++){
    197                     this.state.cacheList.push(<List title={this.props.dataSource[i].title} style={this.props.dataSource[i].style} index={index++}
    198                     styleSon={this.props.styleSon} animation={defV} formatHeight={formatHeight} formatWidth = {formatWidth} keys=
    199                     {this.props.dataSource[i].keys}/>);
    200                 }
    201             }
    202             //无dom绑定
    203             if(defV.domId ===undefined || defV.event ===undefined){
    204                 for(let i =0;i<this.state.cacheList.length;i++){
    205                     this.state.list.push(this.state.cacheList[i]);
    206                 }
    207                 
    208             }else{
    209                 //有dom绑定
    210                 if(this.props.val!=undefined && this.props.val.hideModel){
    211                     hideModel = "hidden";
    212                 }
    213                 //事件绑定
    214                 const _this  = this;
    215                 //切换菜单后window.onload不会执行,但dom已经重置
    216                 if(this.props.val != undefined && this.props.val.domId != undefined && this.props.val.event != undefined && 
    217                 document.getElementById(this.props.val.domId)==null){
    218                     let interval = window.setInterval(()=>{
    219                         let dom:any = null;
    220                         if(_this.props.val!=undefined && _this.props.val.domId != undefined){
    221                             dom = document.getElementById(_this.props.val.domId);
    222                         }
    223                         if(dom !== null && dom !==undefined && dom !=="null"){
    224                             _this.bindEvent(defV);
    225 
    226                             window.clearInterval(interval); 
    227                         } 
    228                     }, 100);        
    229                 }
    230             }
    231         }else {
    232             index = this.state.list.length;
    233         }
    234         
    235         //Father默认样式
    236 
    237         const defFatherStyle:any = {
    238             border:"1px solid #91D5FF",
    239             backgroundColor: "#E6F7FF",
    240             fontSize:"13px",
    241             color:"#000",
    242             paddimg:`${fontSize}px`,
    243             height: `${formatHeight*index+2}px`,
    244             `${formatWidth+2}px`,
    245             visibility:`${hideModel}`
    246         }
    247         const style = {...defFatherStyle,...this.props.style};
    248         return (
    249             <Fragment>
    250                 <div style={style} className={styles.fDiv}>
    251                     <ul className={styles.ul}>
    252                         {this.state.list}
    253                     </ul>
    254                 </div>
    255             </Fragment>
    256          );
    257     }
    258 }
    259 export class Son extends React.Component<{style?:any,keys?:any,onClick?:any,onMouseEnter?:any,onMouseLeave?:any}, {}> {
    260 }
    261 class List extends React.Component<{title:string,style?:any,styleSon?:any,animation:valFrom,keys:any,index:number,formatHeight:number,
    262     formatWidth:number,onClick?:any,onClickSon?:any,onMouseEnter?:any,onMouseEnterSon?:any,onMouseLeave?:any,onMouseLeaveSon?:any},{}> {
    263     click = (key:any,title:any)=>{
    264         if(this.props.onClick !== undefined){
    265             this.props.onClick(key,title);
    266         }else if(this.props.onClickSon !== undefined){
    267             this.props.onClickSon(key,title);
    268         }
    269     }
    270     mouseEnter = (key:any,title:any)=>{
    271         if(this.props.onMouseEnter !== undefined){
    272             this.props.onMouseEnter(key,title);
    273         }else if(this.props.onMouseEnterSon !== undefined){
    274             this.props.onMouseEnterSon(key,title);
    275         }
    276     }
    277     mouseLeave = (key:any,title:any)=>{
    278         if(this.props.onMouseLeave !== undefined){
    279             this.props.onMouseLeave(key,title);
    280         }else if(this.props.onMouseLeaveSon !== undefined){
    281             this.props.onMouseLeaveSon(key,title);
    282         }
    283     }
    284 
    285 
    286 
    287     render() {
    288         const val:valFrom = this.props.animation;
    289         const style = {animation:'',animationDelay:'0s'};
    290         
    291         //加载页面后直接执行
    292         if(val.type === TYPE.FADEIN && val.direction === DIRECTION.TOP || val.type === 'fadeIn' && val.direction === 'top'
    293         || val.type === TYPE.FADEIN && val.direction === 'top' || val.type === 'fadeIn' && val.direction === DIRECTION.TOP){
    294             style.animation= `${styles.fadeInTop} ${val.time}s forwards`;
    295         }else if(val.type === TYPE.FADEIN && val.direction === DIRECTION.BUTTOM || val.type === 'fadeIn' && val.direction === 'buttom'
    296         || val.type === TYPE.FADEIN && val.direction === 'buttom' || val.type === 'fadeIn' && val.direction === DIRECTION.BUTTOM){
    297             style.animation = `${styles.fadeInButtom} ${val.time}s forwards`;       
    298         }else if(val.type === TYPE.FADEIN && val.direction === DIRECTION.LEFT || val.type === 'fadeIn' && val.direction === 'left'
    299         || val.type === TYPE.FADEIN && val.direction === 'left' || val.type === 'fadeIn' && val.direction === DIRECTION.LEFT){
    300         style.animation = `${styles.fadeInLeft} ${val.time}s forwards`;
    301         }else if(val.type === TYPE.FADEIN && val.direction === DIRECTION.REGIST || val.type === 'fadeIn' && val.direction === 'regist'
    302         || val.type === TYPE.FADEIN && val.direction === 'regist' || val.type === 'fadeIn' && val.direction === DIRECTION.REGIST){
    303             style.animation = `${styles.fadeInRegist} ${val.time}s forwards`;
    304         }else if(val.type === TYPE.FADEIN && val.direction === DIRECTION.TOPLEFT || val.type === 'fadeIn' && val.direction === 'topLeft'
    305         || val.type === TYPE.FADEIN && val.direction === 'topLeft' || val.type === 'fadeIn' && val.direction === DIRECTION.TOPLEFT){
    306             style.animation = `${styles.fadeInTopLeft} ${val.time}s forwards`;
    307         }else if(val.type === TYPE.FADEIN && val.direction === DIRECTION.TOPREGIST || val.type === 'fadeIn' && val.direction === 'topRegist'
    308         || val.type === TYPE.FADEIN && val.direction === 'topRegist' || val.type === 'fadeIn' && val.direction === DIRECTION.TOPREGIST){
    309             style.animation = `${styles.fadeInTopRegist} ${val.time}s forwards`;
    310         }else if(val.type === TYPE.FADEIN && val.direction === DIRECTION.BUTTOMLEFT || val.type === 'fadeIn' && val.direction === 'buttomLeft'
    311         || val.type === TYPE.FADEIN && val.direction === 'buttomLeft' || val.type === 'fadeIn' && val.direction === DIRECTION.BUTTOMLEFT){
    312             style.animation = `${styles.fadeInButtomLeft} ${val.time}s forwards`;
    313         }else if(val.type === TYPE.FADEIN && val.direction === DIRECTION.BUTTOMREGIST || val.type === 'fadeIn' && val.direction === 'buttomRegist'
    314         || val.type === TYPE.FADEIN && val.direction === 'buttomRegist' || val.type === 'fadeIn' && val.direction === DIRECTION.BUTTOMREGIST){
    315             style.animation = `${styles.fadeInButtomRegist} ${val.time}s forwards`;
    316         }
    317         if(val.sonDelay !== undefined && val.delay !== undefined){
    318             style.animationDelay = `${this.props.index*val.sonDelay+val.delay}s`;
    319         }
    320         //Son默认样式
    321         const defStyle:any = {
    322             textAlign: "center",
    323             `${this.props.formatWidth}px`,
    324             height:`${this.props.formatHeight}px`,
    325             lineHeight:`${this.props.formatHeight}px`,
    326         }
    327         const sty = {...defStyle,...this.props.styleSon,...this.props.style,...style};
    328         return ( 
    329             <li className={styles.li} style={sty} key={this.props.keys} onClick={this.click.bind(this,this.props.keys,this.props.title)}
    330             onMouseEnter = {this.mouseEnter.bind(this,this.props.keys,this.props.title)} onMouseLeave=
    331             {this.mouseLeave.bind(this,this.props.keys,this.props.title)}>{this.props.title}</li>
    332          );
    333     }
    334 }

    index.less文件:

      1 @top:200px;
      2 @left:400px;
      3 .fDiv,.li,.ul,body,div{
      4     padding: 0px;
      5     margin: 0px;
      6     border: 0px;
      7 }
      8 .fDiv{
      9     position: relative;
     10 }
     11 .li{
     12     list-style:none;
     13     visibility:hidden;
     14     cursor: pointer; 
     15 }
     16 li:hover{
     17     background-color: #A1E5FF;
     18 }
     19 .ul{
     20     position: absolute;
     21     z-index: 999;
     22     display: inline-block;
     23 }
     24 @keyframes fadeInTop{
     25     0%{
     26         opacity: 0;
     27         margin-top: @top;
     28         visibility:visible;
     29     }
     30     100%{
     31         opacity: 1;
     32         margin-top: 0px;
     33         visibility:visible;
     34     }
     35 }
     36 @keyframes fadeInButtom{
     37     0%{
     38         opacity: 0;
     39         margin-top: -@top;
     40         visibility:visible;
     41     }
     42     100%{
     43         opacity: 1;
     44         margin-top: 0px;
     45         visibility:visible;
     46     }
     47 }
     48 @keyframes fadeInLeft{
     49     0%{
     50         opacity: 0;
     51         margin-left: @left;
     52         visibility:visible;
     53     }
     54     100%{
     55         opacity: 1;
     56         margin-left: 0px;
     57         visibility:visible;
     58     }
     59 }
     60 @keyframes fadeInRegist{
     61     0%{
     62         opacity: 0;
     63         margin-left: -@left;
     64         visibility:visible;
     65     }
     66     100%{
     67         opacity: 1;
     68         margin-left: 0px;
     69         visibility:visible;
     70     }
     71 }
     72 @keyframes fadeInTopLeft{
     73     0%{
     74         opacity: 0;
     75         margin-top: @top;
     76         margin-left: @left;
     77         visibility:visible;
     78     }
     79     100%{
     80         opacity: 1;
     81         margin-top: 0px;
     82         margin-left: 0px;
     83         visibility:visible;
     84     }
     85 }
     86 @keyframes fadeInTopRegist{
     87     0%{
     88         opacity: 0;
     89         margin-top: @top;
     90         margin-left: -@left;
     91         visibility:visible;
     92     }
     93     100%{
     94         opacity: 1;
     95         margin-top: 0px;
     96         margin-left: 0px;
     97         visibility:visible;
     98     }
     99 }
    100 @keyframes fadeInButtomLeft{
    101     0%{
    102         opacity: 0;
    103         margin-top: -@top;
    104         margin-left: @left;
    105         visibility:visible;
    106     }
    107     100%{
    108         opacity: 1;
    109         margin-top: 0px;
    110         margin-left: 0px;
    111         visibility:visible;
    112     }
    113 }
    114 @keyframes fadeInButtomRegist{
    115     0%{
    116         opacity: 0;
    117         margin-top: -@top;
    118         margin-left: -@left;
    119         visibility:visible;
    120     }
    121     100%{
    122         opacity: 1;
    123         margin-top: 0px;
    124         margin-left: 0px;
    125         visibility:visible;
    126     }
    127 }

    API如下:

    注意:动画进入选择的类型目前只有fadeIn(渐入),有人可能会说这个可以不要,但是如果要继续拓展的话这个属性就必不可少了,比如拓展增强、轨迹、旋转、无效果等。这些拓展稍显有些麻烦,由于我只是当练习react与typescript来写就没有拓展,但不是不能拓展。

  • 相关阅读:
    robotframework安装与配置--学习第一天
    Google chrome浏览器打不开网页,显示ERR_Failed...等问题的解决方法
    解决dos窗口乱码问题
    打印风车旋转效果
    spring Security 得到认证用户名的方法
    spring requestmapping 拦截多个请求
    github多人协同使用。
    Spring boot Security 用于权限管理,用户添加等。
    spring boot上传 下载图片。
    mysql修改数据库编码(数据库字符集)和表的字符编码的方法
  • 原文地址:https://www.cnblogs.com/chengpu/p/web1.html
Copyright © 2011-2022 走看看