react+ts仿浏览器

index.tsx中

import React, { Component, createRef } from 'react';
import './index.less'
interface Props{
 
}
interface State{
    ButtonList:List[]
    Index:number
}
interface List{
    id:string,
    txt:string
}
export default class ImitationBrowser extends Component<Props,State> {
    constructor(props:Props){
        super(props);
        this.state={
            ButtonList:[
                {
                    id:"内容1",
                    txt:"内容1"
                }
            ],
            Index:0
        }
    }
    // 最后的坐标
    x: number = 0;
    y: number = 0;
    parent = createRef<HTMLDivElement>();
    // 按下元素
    box?: HTMLDivElement;
    // 父元素宽高
    oldWidth: number = 0;
    oldHeight: number = 0;
    // 鼠标坐标
    oldX: number = 0;
    oldY: number = 0;
    // 父元素坐标
    oldLeft: number = 0;
    oldTop: number = 0;
    // 删除时要用到的数组
    arr:List[]=[];
    // 判断鼠标按下时是什么元素
    tl:boolean=false;
    bl:boolean=false;
    tr:boolean=false;
    br:boolean=false;
    t:boolean=false;
    b:boolean=false;
    l:boolean=false;
    r:boolean=false;
    IfHeader:boolean=false;
 
    
    FnDown(ev: MouseEvent) {
        this.box = ev.target as HTMLDivElement;
        ev.stopPropagation();
        ev.preventDefault();
        this.oldWidth = this.getParent().offsetWidth;
        this.oldHeight = this.getParent().offsetHeight;
        this.oldX = ev.clientX;
        this.oldY = ev.clientY;
        this.oldLeft = this.getParent().offsetLeft;
        this.oldTop = this.getParent().offsetTop;
        this.tl=this.box.classList.contains('tl');
        this.bl=this.box.classList.contains('bl');
        this.tr=this.box.classList.contains('tr');
        this.br=this.box.classList.contains('br');
        this.t=this.box.classList.contains('t');
        this.b=this.box.classList.contains('b');
        this.l=this.box.classList.contains('l');
        this.r=this.box.classList.contains('r');
        this.IfHeader=this.box.classList.contains('header');
 
        document.onmousemove = this.FnMove.bind(this);
        document.onmouseup = this.FnUp.bind(this);
    }
    FnMove(ev: MouseEvent) {
        ev.stopPropagation();
        ev.preventDefault();
        this.box = ev.target as HTMLDivElement;
        // 最终的位置=(之前的盒子坐标+(现在鼠标坐标-以前鼠标坐标))
        this.y = (this.oldTop + (ev.clientY - this.oldY));
        this.x = (this.oldLeft + (ev.clientX - this.oldX));
        
        if (this.tl) {
            this.getParent().style.width = this.oldWidth - (ev.clientX - this.oldX) + 'px';
            this.getParent().style.height = this.oldHeight - (ev.clientY - this.oldY) + 'px';
            this.getParent().style.left = this.x + 'px';
            this.getParent().style.top = this.y + 'px';
        }
        else if (this.bl) {
            this.getParent().style.width = this.oldWidth - (ev.clientX - this.oldX) + 'px';
            this.getParent().style.height = this.oldHeight + (ev.clientY - this.oldY) + 'px';
            this.getParent().style.left = this.x + 'px';
            this.getParent().style.bottom = this.oldTop + (ev.clientY + this.oldY) + 'px';
        }
        else if (this.tr) {
            this.getParent().style.width = this.oldWidth + (ev.clientX - this.oldX) + 'px';
            this.getParent().style.height = this.oldHeight - (ev.clientY - this.oldY) + 'px';
            this.getParent().style.right = this.oldLeft - (ev.clientX - this.oldX) + 'px';
            this.getParent().style.top = this.y + 'px';
        }
        else if (this.br) {
            this.getParent().style.width = this.oldWidth + (ev.clientX - this.oldX) + 'px';
            this.getParent().style.height = this.oldHeight + (ev.clientY - this.oldY) + 'px';
            this.getParent().style.right = this.oldLeft - (ev.clientX - this.oldX) + 'px';
            this.getParent().style.bottom = this.oldTop + (ev.clientY + this.oldY) + 'px';
        }
        else if (this.t) {
            this.getParent().style.height = this.oldHeight - (ev.clientY - this.oldY) + 'px';
            this.getParent().style.top = this.y + 'px';
        }
        else if (this.b) {
            this.getParent().style.height = this.oldHeight + (ev.clientY - this.oldY) + 'px';
            this.getParent().style.bottom = this.y + 'px';
        }
        else if (this.l) {
            this.getParent().style.height = this.oldHeight + 'px';
            this.getParent().style.width = this.oldWidth - (ev.clientX - this.oldX) + 'px';
            this.getParent().style.left = this.x + 'px';
        }
        else if (this.r) {
            this.getParent().style.height = this.oldHeight + 'px';
            this.getParent().style.width = this.oldWidth + (ev.clientX - this.oldX) + 'px';
            this.getParent().style.right = this.x + 'px';
        }
        if (this.IfHeader) {
            this.getParent().style.left = this.x + 'px';
            this.getParent().style.top = this.y + 'px';
        }
    }
    FnUp() {
        document.onmousemove = null;
        document.onmouseup = null;
    }
    componentDidMount() {
        this.getParent().onmousedown = this.FnDown.bind(this);
    }
 
    getParent() {
        return this.parent.current as HTMLDivElement
    }
   
  
 
    AddPage(){
        this.arr=this.state.ButtonList;
        
        let num =this.state.ButtonList.length+1;
        let obj:List={id:'内容'+num,txt:'内容'+num};
        
        this.arr.push(obj);
 
        this.setState({
            ButtonList:this.arr,
            Index:num-1
        })
    }
    Cut(index:number){
        this.setState({
            Index:index
        })
    }
    close(id:string) {
        let arr = [...this.state.ButtonList]
        arr = arr.filter((item) => {
            return item.id !== id
        })
        let num=this.state.ButtonList.length;
        this.setState({ 
            ButtonList:arr,
            Index:num-2   //这里有点问题
        })
    }
    allClose(){
        this.getParent().remove();
    }
    render() {
        return (
            <div className="box" ref={this.parent}>
                {/* 可以拖动的头部区域 */}
                <div className="header">
                    <div className="left">
                    {this.state.ButtonList.map((item,index)=>
                        <div className={this.state.Index===index?"button-list ac":"button-list"} onClick={this.Cut.bind(this,index)} key={item.id}>
                            <div className="text">{item.txt}</div>
                            <div className="del" onClick={this.close.bind(this,item.id)}>x</div>
                        </div>
                    )}
                    <div className="add" onClick={this.AddPage.bind(this)}>+</div>
                    </div>
                    <div className="right" onClick={this.allClose.bind(this)}>x</div>
                </div>
                {/* 边框与角 */}
                <span className="r"></span>
                <span className="l"></span>
                <span className="t"></span>
                <span className="b"></span>
                <span className="br"></span>
                <span className="bl"></span>
                <span className="tr"></span>
                <span className="tl"></span>
                {/* 内容区域 */}
                <div className="inner">
                    {this.state.ButtonList.map((item,index)=>
                        <div className="content-list" style={{display:this.state.Index===index?"block":"none"}} key={index}>
                            {item.txt}
                        </div>
                    )}
                </div>
            </div>
        )
    }
}
 

index.less中

.box {
    width: 1000px;
    height: 800px;
    // border: 1px solid #ccc;
    position: absolute;
    box-sizing: border-box;
    //位置的值必须加上,不然定位可能会不准确
    top: 0;
    left: 0;
    .header {
        height: 100px;
        text-align: center;
        border-bottom: 1px solid #ccc;
        padding-right: 20px;
        display: flex;
        align-items: center;
        overflow-x: scroll;
        justify-content: space-between;
        .left {
            display: flex;
            align-items: center;
            .button-list {
                font-size: 30px;
                padding: 5px;
                min-width: 200px;
                height: 90px;
                line-height: 90px;
                text-align: center;
                background-color: #fff;
                border: 1px solid #ccc;
                border-top-left-radius: 50px;
                border-top-right-radius: 50px;
                display: flex;
                align-items: center;
                justify-content: space-around;

                .del {
                    font-size: 30px;
                }
            }
        }
        .right{
            font-size: 50px;
        }

        .button-list.ac {
            font-size: 30px;
            padding: 5px;
            min-width: 200px;
            height: 90px;
            line-height: 90px;
            text-align: center;
            background-color: pink;
            border-top-left-radius: 50px;
            border-top-right-radius: 50px;
        }

        .add {
            font-size: 60px;
            color: #ccc;
        }
    }
    .header::-webkit-scrollbar {display:none}

    /*四边*/
    .t,
    .b,
    .l,
    .r {
        position: absolute;
        z-index: 1;
        background: #666;
    }

    .l,
    .r {
        width: 10px;
        height: 100%;
        top: -5px;
        cursor: col-resize;
    }

    .t,
    .b {
        width: 100%;
        height: 10px;
        cursor: row-resize;
    }

    .t {
        top: 0;
    }

    .b {
        bottom: 0;
    }

    .l {
        left: -5px;
    }

    .r {
        right: 0;
    }

    /*四角*/
    .tl,
    .bl,
    .br,
    .tr {
        width: 20px;
        height: 20px;
        position: absolute;
        background: #fff;
        border: 1px solid #666;
        z-index: 2;
        cursor: nwse-resize
    }

    .tl,
    .bl {
        left: -5px;
    }

    .tr,
    .br {
        right: -5px;
    }

    .br,
    .bl {
        bottom: -5px;
    }

    .tl,
    .tr {
        top: -5px;
    }

    .tr,
    .bl {
        cursor: nesw-resize;
    }

    /*内核*/
    .inner {
        width: 100%;
        height: 90%;

        .content-list {
            font-size: 50px;
            width: 100%;
            height: 100%;
            text-align: center;
            line-height: 100%;
        }
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值