<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
本文範例為大家分享了React拖拽調整大小的元件,供大家參考,具體內容如下
1.使用React.cloneElement
加強包裹元件,在包裹的元件設定絕對定位,並在元件內加上四個可調整大小的拖動條,在點選拖動條並進行拖動時會改變DragBox的大小,如下:
2.使用:
<DragBox dragAble={true} minWidth={350} minHeight={184} edgeDistance={[10, 10, 10, 10]} dragCallback={this.dragCallback} > {/* 使用DragBox拖動元件包裹需要調整大小的盒子 */} <div style={{ top: 100 + 'px', left: 100 + 'px', width: 350, height: 184, backgroundColor: "white" }}> <div style={{ backgroundColor: "yellow", width: "100%", height: 30 }}></div> <div style={{ backgroundColor: "green", width: "100%", height: 30 }}></div> <div style={{ backgroundColor: "blue", width: "100%", height: 30 }}></div> </div> </DragBox>
DragBox元件
import React, { Component, Fragment } from 'react'; import styles from "./DragBox.less"; /** * 拖拽的公共元件 * 接收引數: * dragAble:是否開啟拖拽 * minWidth:最小調整寬度 * minHeight:最小調整高度 * edgeDistance:陣列,拖拽盒子裡瀏覽器上下左右邊緣的距離,如果小於這個距離就不會再進行調整寬高 * dragCallback:拖拽回撥 * * 使用: * 在DragBox元件放需要實現拖拽的div,DragBox元件內會設定position:absolute(React.cloneElement) */ class DragBox extends Component { constructor(props) { super(props); // 父元件盒子 this.containerRef = React.createRef(); // 是否開啟尺寸修改 this.reSizeAble = false; // 滑鼠按下時的座標,並在修改尺寸時儲存上一個滑鼠的位置 this.clientX, this.clientY; // 滑鼠按下時的位置,使用n、s、w、e表示 this.direction = ""; // 拖拽盒子裡瀏覽器上下左右邊緣的距離,如果小於這個距離就不會再進行調整寬高 this.edgeTopDistance = props.edgeDistance[0] || 10; this.edgeBottomDistance = props.edgeDistance[1] || 10; this.edgeLeftDistance = props.edgeDistance[2] || 10; this.edgeRightDistance = props.edgeDistance[3] || 10; } componentDidMount(){ // body監聽移動事件 document.body.addEventListener('mousemove', this.move); // 滑鼠鬆開事件 document.body.addEventListener('mouseup', this.up); } /** * 清除調整寬高的監聽 */ clearEventListener() { document.body.removeEventListener('mousemove', this.move); document.body.removeEventListener('mouseup', this.up); } componentWillUnmount() { this.clearEventListener(); } /** * 滑鼠鬆開時結束尺寸修改 */ up = () => { this.reSizeAble = false; this.direction = ""; } /** * 滑鼠按下時開啟尺寸修改 * @param {*} e * @param {String} direction 記錄點選上下左右哪個盒子的標識 */ down = (e, direction) => { this.direction = direction; this.reSizeAble = true; this.clientX = e.clientX; this.clientY = e.clientY; } /** * 滑鼠按下事件 監聽滑鼠移動,修改父節dom位置 * @param {DocumentEvent} e 事件引數 * @param {Boolean} changeLeft 是否需要調整left * @param {Boolean} changeTop 是否需要調整top * @param {Number} delta 調整位置的距離差 */ changeLeftAndTop = (event, changeLeft, changeTop, delta) => { let ww = document.documentElement.clientWidth; let wh = window.innerHeight; if (event.clientY < 0 || event.clientX < 0 || event.clientY > wh || event.clientX > ww) { return false; } if (changeLeft) { this.containerRef.current.style.left = Math.max(this.containerRef.current.offsetLeft + delta, this.edgeLeftDistance) + 'px'; } if (changeTop) { this.containerRef.current.style.top = Math.max(this.containerRef.current.offsetTop + delta, this.edgeTopDistance) + 'px'; } } /** * 滑鼠移動事件 * @param {*} e */ move = (e) => { // 當開啟尺寸修改時,滑鼠移動會修改div尺寸 if (this.reSizeAble) { let finalValue; // 滑鼠按下的位置在上部,修改高度 if (this.direction === "top") { // 1.距離上邊緣10 不修改 // 2.因為按著頂部修改高度會修改top、height,所以需要判斷e.clientY是否在offsetTop和this.clientY之間(此時說明處於往上移動且滑鼠位置在盒子上邊緣之下),不應該移動和調整盒子寬高 if (e.clientY <= this.edgeTopDistance || (this.containerRef.current.offsetTop < e.clientY && e.clientY < this.clientY)){ this.clientY = e.clientY; return; } finalValue = Math.max(this.props.minHeight, this.containerRef.current.offsetHeight + (this.clientY - e.clientY)); // 移動的距離,如果移動的距離不為0需要調整高度和top let delta = this.containerRef.current.offsetHeight - finalValue; if(delta !== 0){ this.changeLeftAndTop(e, false, true, delta); this.containerRef.current.style.height = finalValue + "px"; } this.clientY = e.clientY; } else if (this.direction === "bottom") {// 滑鼠按下的位置在底部,修改高度 // 1.距離下邊緣10 不修改 // 2.判斷e.clientY是否處於往下移動且滑鼠位置在盒子下邊緣之上,不應該調整盒子寬高 if (window.innerHeight - e.clientY <= this.edgeBottomDistance || (this.containerRef.current.offsetTop + this.containerRef.current.offsetHeight > e.clientY && e.clientY > this.clientY)) { this.clientY = e.clientY; return; } finalValue = Math.max(this.props.minHeight, this.containerRef.current.offsetHeight + (e.clientY - this.clientY)); this.containerRef.current.style.height = finalValue + "px"; this.clientY = e.clientY; } else if (this.direction === "right") { // 滑鼠按下的位置在右邊,修改寬度 // 1.距離右邊緣10 不修改 // 2.判斷e.clientY是否處於往右移動且滑鼠位置在盒子右邊緣之左,不應該調整盒子寬高 if (document.documentElement.clientWidth - e.clientX <= this.edgeRightDistance || (this.containerRef.current.offsetLeft + this.containerRef.current.offsetWidth > e.clientX && e.clientX > this.clientX)) { this.clientX = e.clientX; return; } // 最小為UI設計this.props.minWidth,最大為 改邊距離螢幕邊緣-10,其他同此 let value = this.containerRef.current.offsetWidth + (e.clientX - this.clientX); finalValue = step(value, this.props.minWidth, document.body.clientWidth - this.edgeRightDistance - this.containerRef.current.offsetLeft); this.containerRef.current.style.width = finalValue + "px"; this.clientX = e.clientX; } else if (this.direction === "left") {// 滑鼠按下的位置在左邊,修改寬度 // 1.距離左邊緣10 不修改 // 2.因為按著頂部修改高度會修改left、height,所以需要判斷e.clientY是否在offsetLeft和this.clientY之間(此時說明處於往左移動且滑鼠位置在盒子左邊緣之左),不應該移動和調整盒子寬高 if (e.clientX <= this.edgeLeftDistance || (this.containerRef.current.offsetLeft < e.clientX && e.clientX < this.clientX)) { this.clientX = e.clientX; return; } let value = this.containerRef.current.offsetWidth + (this.clientX - e.clientX); finalValue = step(value, this.props.minWidth, this.containerRef.current.offsetWidth - this.edgeLeftDistance + this.containerRef.current.offsetLeft); // 移動的距離,如果移動的距離不為0需要調整寬度和left let delta = this.containerRef.current.offsetWidth - finalValue; if(delta !== 0){ // 需要修改位置,直接修改寬度只會向右增加 this.changeLeftAndTop(e, true, false, delta); this.containerRef.current.style.width = finalValue + "px"; } this.clientX = e.clientX; } this.props.dragCallback && this.props.dragCallback(this.direction, finalValue); } } render() { // 四個紅色盒子 用於滑鼠移動到上面按下進行拖動 const children = ( <Fragment key={"alphaBar"}> <div key={1} className={styles.alphaTopBar} onMouseDown={(e) => this.down(e, "top")}></div> <div key={2} className={styles.alphaBottomBar} onMouseDown={(e) => this.down(e, "bottom")}></div> <div key={3} className={styles.alphaLeftBar} onMouseDown={(e) => this.down(e, "left")}></div> <div key={4} className={styles.alphaRightBar} onMouseDown={(e) => this.down(e, "right")}></div> </Fragment> ); // 給傳進來的children進行加強:新增position:"absolute",新增四個用於拖動的透明盒子 const childrenProps = this.props.children.props; const cloneReactElement = React.cloneElement( this.props.children, { style: { // 複用原來的樣式 ...childrenProps.style, // 新增position:"absolute" position: "absolute" }, ref: this.containerRef }, // 複用children,新增四個用於拖動的紅色盒子 [childrenProps.children, children] ); return ( <Fragment> { cloneReactElement } </Fragment> ); } } /** * 取最大和最小值之間的值 * @param {*} value * @param {*} min * @param {*} max * @returns */ function step(value, min, max) { if (value < min) { return min; } else if (value > max) { return max; } else { return value; } } export default DragBox;
### DragBox元件拖動條的樣式
.alphaTopBar{ position: absolute; width: 100%; height: 8px; top: -5px; left: 0; background-color: red; cursor: row-resize; } .alphaBottomBar{ position: absolute; width: 100%; height: 8px; bottom: -5px; left: 0; background-color: red; cursor: row-resize; } .alphaLeftBar{ position: absolute; width: 8px; height: 100%; top: 0; left: -5px; background-color: red; cursor: col-resize; } .alphaRightBar{ position: absolute; width: 8px; height: 100%; top: 0; right: -5px; background-color: red; cursor: col-resize; }
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援it145.com。
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45