How to make HTML element resizable using pure Javascript?

故事扮演 提交于 2019-12-27 10:33:01

问题


I was wondering how we can make a HTML element like <div> or <p> tag element resizable when clicked using pure JavaScript, not the jQuery library or any other library.


回答1:


I really recommend using some sort of library, but you asked for it, you get it:

var p = document.querySelector('p'); // element to make resizable

p.addEventListener('click', function init() {
    p.removeEventListener('click', init, false);
    p.className = p.className + ' resizable';
    var resizer = document.createElement('div');
    resizer.className = 'resizer';
    p.appendChild(resizer);
    resizer.addEventListener('mousedown', initDrag, false);
}, false);

var startX, startY, startWidth, startHeight;

function initDrag(e) {
   startX = e.clientX;
   startY = e.clientY;
   startWidth = parseInt(document.defaultView.getComputedStyle(p).width, 10);
   startHeight = parseInt(document.defaultView.getComputedStyle(p).height, 10);
   document.documentElement.addEventListener('mousemove', doDrag, false);
   document.documentElement.addEventListener('mouseup', stopDrag, false);
}

function doDrag(e) {
   p.style.width = (startWidth + e.clientX - startX) + 'px';
   p.style.height = (startHeight + e.clientY - startY) + 'px';
}

function stopDrag(e) {
    document.documentElement.removeEventListener('mousemove', doDrag, false);
    document.documentElement.removeEventListener('mouseup', stopDrag, false);
}

Demo

Remember that this may not run in all browsers (tested only in Firefox, definitely not working in IE <9).




回答2:


what about a pure css3 solution?

div {
    resize: both;
    overflow: auto;
} 

MDN Web Docs

W3Schools example

Browser support




回答3:


Is simple:

Example:https://jsfiddle.net/RainStudios/mw786v1w/

var element = document.getElementById('element');
//create box in bottom-left
var resizer = document.createElement('div');
resizer.style.width = '10px';
resizer.style.height = '10px';
resizer.style.background = 'red';
resizer.style.position = 'absolute';
resizer.style.right = 0;
resizer.style.bottom = 0;
resizer.style.cursor = 'se-resize';
//Append Child to Element
element.appendChild(resizer);
//box function onmousemove
resizer.addEventListener('mousedown', initResize, false);

//Window funtion mousemove & mouseup
function initResize(e) {
   window.addEventListener('mousemove', Resize, false);
   window.addEventListener('mouseup', stopResize, false);
}
//resize the element
function Resize(e) {
   element.style.width = (e.clientX - element.offsetLeft) + 'px';
   element.style.height = (e.clientY - element.offsetTop) + 'px';
}
//on mouseup remove windows functions mousemove & mouseup
function stopResize(e) {
    window.removeEventListener('mousemove', Resize, false);
    window.removeEventListener('mouseup', stopResize, false);
}



回答4:


See my cross browser compatible resizer.

    <!doctype html>
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <title>resizer</title>
        <meta name="author" content="Andrej Hristoliubov anhr@mail.ru">
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
        <script type="text/javascript" src="https://rawgit.com/anhr/resizer/master/Common.js"></script>
        <script type="text/javascript" src="https://rawgit.com/anhr/resizer/master/resizer.js"></script>
        <style>
            .element {
                border: 1px solid #999999;
                border-radius: 4px;
                margin: 5px;
                padding: 5px;
            }
        </style>
        <script type="text/javascript">
            function onresize() {
                var element1 = document.getElementById("element1");
                var element2 = document.getElementById("element2");
                var element3 = document.getElementById("element3");
                var ResizerY = document.getElementById("resizerY");
                ResizerY.style.top = element3.offsetTop - 15 + "px";
                var topElements = document.getElementById("topElements");
                topElements.style.height = ResizerY.offsetTop - 20 + "px";
                var height = topElements.clientHeight - 32;
                if (height < 0)
                    height = 0;
                height += 'px';
                element1.style.height = height;
                element2.style.height = height;
            }
            function resizeX(x) {
                //consoleLog("mousemove(X = " + e.pageX + ")");
                var element2 = document.getElementById("element2");
                element2.style.width =
                    element2.parentElement.clientWidth
                    + document.getElementById('rezizeArea').offsetLeft
                    - x
                    + 'px';
            }
            function resizeY(y) {
                //consoleLog("mousemove(Y = " + e.pageY + ")");
                var element3 = document.getElementById("element3");
                var height =
                    element3.parentElement.clientHeight
                    + document.getElementById('rezizeArea').offsetTop
                    - y
                ;
                //consoleLog("mousemove(Y = " + e.pageY + ") height = " + height + " element3.parentElement.clientHeight = " + element3.parentElement.clientHeight);
                if ((height + 100) > element3.parentElement.clientHeight)
                    return;//Limit of the height of the elemtnt 3
                element3.style.height = height + 'px';
                onresize();
            }
            var emailSubject = "Resizer example error";
        </script>
    </head>
    <body>
        <div id='Message'></div>
        <h1>Resizer</h1>
        <p>Please see example of resizing of the HTML element by mouse dragging.</p>
        <ul>
            <li>Drag the red rectangle if you want to change the width of the Element 1 and Element 2</li>
            <li>Drag the green rectangle if you want to change the height of the Element 1 Element 2 and Element 3</li>
            <li>Drag the small blue square at the left bottom of the Element 2, if you want to resize of the Element 1 Element 2 and Element 3</li>
        </ul>
        <div id="rezizeArea" style="width:1000px; height:250px; overflow:auto; position: relative;" class="element">
            <div id="topElements" class="element" style="overflow:auto; position:absolute; left: 0; top: 0; right:0;">
                <div id="element2" class="element" style="width: 30%; height:10px; float: right; position: relative;">
                    Element 2
                    <div id="resizerXY" style="width: 10px; height: 10px; background: blue; position:absolute; left: 0; bottom: 0;"></div>
                    <script type="text/javascript">
                        resizerXY("resizerXY", function (e) {
                                resizeX(e.pageX + 10);
                                resizeY(e.pageY + 50);
                            });
                    </script>
                </div>
                <div id="resizerX" style="width: 10px; height:100%; background: red; float: right;"></div>
                <script type="text/javascript">
                    resizerX("resizerX", function (e) {
                        resizeX(e.pageX + 25);
                    });
                </script>
                <div id="element1" class="element" style="height:10px; overflow:auto;">Element 1</div>
            </div>
            <div id="resizerY" style="height:10px; position:absolute; left: 0; right:0; background: green;"></div>
            <script type="text/javascript">
                resizerY("resizerY", function (e) {
                    resizeY(e.pageY + 25);
                });
            </script>
            <div id="element3" class="element" style="height:100px; position:absolute; left: 0; bottom: 0; right:0;">Element 3</div>
        </div>
        <script type="text/javascript">
            onresize();
        </script>
    </body>
    </html>

Also see my example of resizer




回答5:


I just created a CodePen that shows how this can be done pretty easily using ES6.

http://codepen.io/travist/pen/GWRBQV

Basically, here is the class that does this.

let getPropertyValue = function(style, prop) {
  let value = style.getPropertyValue(prop);
  value = value ? value.replace(/[^0-9.]/g, '') : '0';
  return parseFloat(value);
}

let getElementRect = function(element) {
  let style = window.getComputedStyle(element, null);
  return {
    x: getPropertyValue(style, 'left'),
    y: getPropertyValue(style, 'top'),
    width: getPropertyValue(style, 'width'),
    height: getPropertyValue(style, 'height')
  }
}

class Resizer {
    constructor(wrapper, element, options) {
        this.wrapper = wrapper;
        this.element = element;
        this.options = options;
        this.offsetX = 0;
        this.offsetY = 0;
        this.handle = document.createElement('div');
        this.handle.setAttribute('class', 'drag-resize-handlers');
        this.handle.setAttribute('data-direction', 'br');
        this.wrapper.appendChild(this.handle);
        this.wrapper.style.top = this.element.style.top;
        this.wrapper.style.left = this.element.style.left;
        this.wrapper.style.width = this.element.style.width;
        this.wrapper.style.height = this.element.style.height;
        this.element.style.position = 'relative';
        this.element.style.top = 0;
        this.element.style.left = 0;
        this.onResize = this.resizeHandler.bind(this);
        this.onStop = this.stopResize.bind(this);
        this.handle.addEventListener('mousedown', this.initResize.bind(this));
    }

    initResize(event) {
        this.stopResize(event, true);
        this.handle.addEventListener('mousemove', this.onResize);
        this.handle.addEventListener('mouseup', this.onStop);
    }

    resizeHandler(event) {
        this.offsetX = event.clientX - (this.wrapper.offsetLeft + this.handle.offsetLeft);
        this.offsetY = event.clientY - (this.wrapper.offsetTop + this.handle.offsetTop);
        let wrapperRect = getElementRect(this.wrapper);
        let elementRect = getElementRect(this.element);
        this.wrapper.style.width = (wrapperRect.width + this.offsetX) + 'px';
        this.wrapper.style.height = (wrapperRect.height + this.offsetY) + 'px';
        this.element.style.width = (elementRect.width + this.offsetX) + 'px';
        this.element.style.height = (elementRect.height + this.offsetY) + 'px';
    }

    stopResize(event, nocb) {
        this.handle.removeEventListener('mousemove', this.onResize); 
        this.handle.removeEventListener('mouseup', this.onStop);
    }
}

class Dragger {
    constructor(wrapper, element, options) {
        this.wrapper = wrapper;
        this.options = options;
        this.element = element;
        this.element.draggable = true;
        this.element.setAttribute('draggable', true);
        this.element.addEventListener('dragstart', this.dragStart.bind(this));
    }

    dragStart(event) {
        let wrapperRect = getElementRect(this.wrapper);
        var x = wrapperRect.x - parseFloat(event.clientX);
        var y = wrapperRect.y - parseFloat(event.clientY);
        event.dataTransfer.setData("text/plain", this.element.id + ',' + x + ',' + y);
    }

    dragStop(event, prevX, prevY) {
        var posX = parseFloat(event.clientX) + prevX;
        var posY = parseFloat(event.clientY) + prevY;
        this.wrapper.style.left = posX + 'px';
        this.wrapper.style.top = posY + 'px';
    }
}

class DragResize {
    constructor(element, options) {
        options = options || {};
        this.wrapper = document.createElement('div');
        this.wrapper.setAttribute('class', 'tooltip drag-resize');
        if (element.parentNode) {
          element.parentNode.insertBefore(this.wrapper, element);
        }
        this.wrapper.appendChild(element);
        element.resizer = new Resizer(this.wrapper, element, options);
        element.dragger = new Dragger(this.wrapper, element, options);
    }
}

document.body.addEventListener('dragover', function (event) {
    event.preventDefault();
    return false;
});

document.body.addEventListener('drop', function (event) {
    event.preventDefault();
    var dropData = event.dataTransfer.getData("text/plain").split(',');
    var element = document.getElementById(dropData[0]);
    element.dragger.dragStop(event, parseFloat(dropData[1]), parseFloat(dropData[2]));
    return false;
});



回答6:


I have created a function that recieve an id of an html element and adds a border to it's right side the function is general and just recieves an id so you can copy it as it is and it will work

var myoffset;
function resizeE(elem){
    var borderDiv = document.createElement("div");
    borderDiv.className = "border";
    borderDiv.addEventListener("mousedown",myresize = function myrsize(e) {
	    myoffset = e.clientX - (document.getElementById(elem).offsetLeft + parseInt(window.getComputedStyle(document.getElementById(elem)).getPropertyValue("width")));
	    window.addEventListener("mouseup",mouseUp);
	    document.addEventListener("mousemove",mouseMove = function mousMove(e) {
	   	 document.getElementById(elem).style.width = `${e.clientX -  myoffset - document.getElementById(elem).offsetLeft}px`;
		});
	});
    document.getElementById(elem).appendChild(borderDiv);
}

function mouseUp() {
    document.removeEventListener("mousemove", mouseMove);
    window.removeEventListener("mouseup",mouseUp);
}

function load() 
{
	resizeE("resizeableDiv");
	resizeE("anotherresizeableDiv");
  resizeE("anotherresizeableDiv1");
}
.border {

  position: absolute;
  cursor: e-resize;
  width: 9px;
  right: -5px;
  top: 0;
  height: 100%;
}

#resizeableDiv {
  width: 30vw;
  height: 30vh;
  background-color: #84f4c6;
  position: relative;
}
#anotherresizeableDiv {
  width: 30vw;
  height: 30vh;
  background-color: #9394f4;
  position: relative;
}
#anotherresizeableDiv1 {
  width: 30vw;
  height: 30vh;
  background-color: #43f4f4;
  position: relative;
}
#anotherresizeableDiv1 .border{
  background-color: black;
}
#anotherresizeableDiv .border{
  width: 30px;
  right: -200px;
  background-color: green;
}
<body onload="load()">

  <div id="resizeableDiv">change my size with the east border</div>
  <div id="anotherresizeableDiv1">with visible border</div>
</body>
  <div id="anotherresizeableDiv">with editted outside border</div>
</body>
resizeE("resizeableDiv"); //this calls a function that does the magic to the id inserted



回答7:


There are very good examples here to start trying with, but all of them are based on adding some extra or external element like a "div" as a reference element to drag it, and calculate the new dimensions or position of the original element.

Here's an example that doesn't use any extra elements. We could add borders, padding or margin without affecting its operation. In this example we have not added color, nor any visual reference to the borders nor to the lower right corner as a clue where you can enlarge or reduce dimensions, but using the cursor around the resizable elements the clues appears!

let resizerForCenter = new Resizer('center')  
resizerForCenter.initResizer()

See it in action with CodeSandbox:

In this example we use ES6, and a module that exports a class called Resizer. An example is worth a thousand words:

Or with the code snippet:

const html = document.querySelector('html')

class Resizer {
	constructor(elemId) {
		this._elem = document.getElementById(elemId)
		/**
		 * Stored binded context handlers for method passed to eventListeners!
		 * 
		 * See: https://stackoverflow.com/questions/9720927/removing-event-listeners-as-class-prototype-functions
		 */
		this._checkBorderHandler	= this._checkBorder.bind(this)
		this._doResizeHandler		= this._doResize.bind(this)
		this._initResizerHandler	= this.initResizer.bind(this)
		this._onResizeHandler		= this._onResize.bind(this)
	}

	initResizer() {
		this.stopResizer()
		this._beginResizer()
	}

	_beginResizer() {
		this._elem.addEventListener('mousemove', this._checkBorderHandler, false)
	}

	stopResizer() {
		html.style.cursor	= 'default'
		this._elem.style.cursor = 'default'
		
		window.removeEventListener('mousemove', this._doResizeHandler, false)
		window.removeEventListener('mouseup', this._initResizerHandler, false)

		this._elem.removeEventListener('mousedown', this._onResizeHandler, false)
		this._elem.removeEventListener('mousemove', this._checkBorderHandler, false)
	}

	_doResize(e) {
		let elem = this._elem

		let boxSizing = getComputedStyle(elem).boxSizing
		let borderRight = 0
		let borderLeft = 0
		let borderTop = 0
		let borderBottom = 0

		let paddingRight = 0
		let paddingLeft = 0
		let paddingTop = 0
		let paddingBottom = 0

		switch (boxSizing) {
			case 'content-box':
					paddingRight = parseInt(getComputedStyle(elem).paddingRight)
					paddingLeft = parseInt(getComputedStyle(elem).paddingLeft)
					paddingTop = parseInt(getComputedStyle(elem).paddingTop)
					paddingBottom = parseInt(getComputedStyle(elem).paddingBottom)
				break
			case 'border-box':
					borderRight = parseInt(getComputedStyle(elem).borderRight)
					borderLeft = parseInt(getComputedStyle(elem).borderLeft)
					borderTop = parseInt(getComputedStyle(elem).borderTop)
					borderBottom = parseInt(getComputedStyle(elem).borderBottom)
				break
			default: break
		}

		let horizontalAdjustment	= (paddingRight + paddingLeft) - (borderRight + borderLeft)
		let verticalAdjustment		= (paddingTop + paddingBottom) - (borderTop + borderBottom)

		let newWidth	= elem.clientWidth  + e.movementX - horizontalAdjustment + 'px'
		let newHeight	= elem.clientHeight + e.movementY - verticalAdjustment   + 'px'
		
		let cursorType = getComputedStyle(elem).cursor
		switch (cursorType) {
			case 'all-scroll':
					elem.style.width = newWidth
					elem.style.height = newHeight
				break
			case 'col-resize':
					elem.style.width = newWidth
				break
			case 'row-resize':
					elem.style.height = newHeight
				break
			default: break
		}
	}

	_onResize(e) {
		// On resizing state!
		let elem = e.target
		let newCursorType = undefined
		let cursorType = getComputedStyle(elem).cursor
		switch (cursorType) {
			case 'nwse-resize':
				newCursorType = 'all-scroll'
				break
			case 'ew-resize':
				newCursorType = 'col-resize'
				break
			case 'ns-resize':
				newCursorType = 'row-resize'
				break
			default: break
		}
		
		html.style.cursor	= newCursorType // Avoid cursor's flickering 
		elem.style.cursor	= newCursorType
		
		// Remove what is not necessary, and could have side effects!
		elem.removeEventListener('mousemove', this._checkBorderHandler, false);
		
		// Events on resizing state
		/**
		 * We do not apply the mousemove event on the elem to resize it, but to the window to prevent the mousemove from slippe out of the elem to resize. This work bc we calculate things based on the mouse position
		 */
		window.addEventListener('mousemove', this._doResizeHandler, false);
		window.addEventListener('mouseup', this._initResizerHandler, false);
	}

	_checkBorder(e) {
		const elem = e.target
		const borderSensitivity = 5
		const coor = getCoordenatesCursor(e)
		const onRightBorder		= ((coor.x + borderSensitivity) > elem.scrollWidth)
		const onBottomBorder	= ((coor.y + borderSensitivity) > elem.scrollHeight)
		const onBottomRightCorner = (onRightBorder && onBottomBorder)
		
		if (onBottomRightCorner) {
			elem.style.cursor = 'nwse-resize'
		} else if (onRightBorder) {
			elem.style.cursor = 'ew-resize'
		} else if (onBottomBorder) {
			elem.style.cursor = 'ns-resize'
		} else {
			elem.style.cursor = 'auto'
		}
		
		if (onRightBorder || onBottomBorder) {
			elem.addEventListener('mousedown', this._onResizeHandler, false)
		} else {
			elem.removeEventListener('mousedown', this._onResizeHandler, false)
		}
	}
}

function getCoordenatesCursor(e) {
	let elem = e.target;
	
	// Get the Viewport-relative coordinates of cursor.
	let viewportX = e.clientX
	let viewportY = e.clientY
	
	// Viewport-relative position of the target element.
	let elemRectangle = elem.getBoundingClientRect()
	
	// The  function returns the largest integer less than or equal to a given number.
	let x = Math.floor(viewportX - elemRectangle.left) // - elem.scrollWidth
	let y = Math.floor(viewportY - elemRectangle.top) // - elem.scrollHeight
	
	return {x, y}
}

let resizerForCenter = new Resizer('center')
resizerForCenter.initResizer()

let resizerForLeft = new Resizer('left')
resizerForLeft.initResizer()

setTimeout(handler, 10000, true); // 10s

function handler() {
  resizerForCenter.stopResizer()
}
body {
	background-color: white;
}

#wrapper div {
	/* box-sizing: border-box; */
	position: relative;
	float:left;
	overflow: hidden;
	height: 50px;
	width: 50px;
	padding: 3px;
}

#left {
	background-color: blueviolet;
}
#center {
	background-color:lawngreen ;
}
#right {
	background: blueviolet;
}
#wrapper {
	border: 5px solid hotpink;
	display: inline-block;
	
}
<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<meta http-equiv="X-UA-Compatible" content="ie=edge">
	<title>Resizer v0.0.1</title>
</head>
  <body>
    <div id="wrapper">
      <div id="left">Left</div>
      <div id="center">Center</div>
      <div id="right">Right</div>
    </div>
  </body>
</html>



回答8:


var resizeHandle = document.getElementById('resizable');
var box = document.getElementById('resize');
resizeHandle.addEventListener('mousedown', initialiseResize, false);

function initialiseResize(e) {
  window.addEventListener('mousemove', startResizing, false);
  window.addEventListener('mouseup', stopResizing, false);
}

function stopResizing(e) {
  window.removeEventListener('mousemove', startResizing, false);
  window.removeEventListener('mouseup', stopResizing, false);
}

function startResizing(e) {
  box.style.width = (e.clientX) + 'px';
  box.style.height = (e.clientY) + 'px';
}

function startResizing(e) {
  box.style.width = (e.clientX - box.offsetLeft) + 'px';
  box.style.height = (e.clientY - box.offsetTop) + 'px';
}
#resize {
  position: relative;
  width: 130px;
  height: 130px;
  border: 2px solid blue;
  color: white;
}

#resizable {
  background-color: white;
  width: 10px;
  height: 10px;
  cursor: se-resize;
  position: absolute;
  right: 0;
  bottom: 0;
}
<div id="resize">

  <div id="resizable">
  </div>


来源:https://stackoverflow.com/questions/8960193/how-to-make-html-element-resizable-using-pure-javascript

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!