ContentEditable image resize in chrome, what is the best solution? - javascript

I'm trying to integrate image resizing using contentEditable on Chrome. I know there are problems with webkit about the normal operation of this feature, so I was wondering what is the best alternative method for the integration of image resizing in case a user uses Google Chrome (jQuery plugins? Javascript methods?).
<div contenteditable>
<img src="http://www.thebrandbite.com/wp-content/media/2015/07/apple-7.jpg" width=200 />
</div>
Here is how it works out-of-the-box with Firefox:

Your options are:
Use a library. They definitely exist: YUI has an image resize module, for example. I've never used it but the demo works in all the desktop browsers I tried.
Write your own: add some draggable positioned elements for the resize handles. I've done this before and it's not too hard if you know what you're doing.

#Tim-Down Answer is probably the better solution.
But I want to throw out there, that you can resize images with just CSS, if you don't want to do anything further with it:
http://codepen.io/anon/pen/JEEKqO
resize: both;
background-size: contain;
background-repeat: no-repeat;
background-image: url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/4273/photoshop-face-after.jpg);
body {
background-color: #1D1F1F;
}
section {
display: table;
margin: 0 auto;
}
div {
resize: both;
background-color: white;
overflow: scroll;
background-image: url('https://s3-us-west-2.amazonaws.com/s.cdpn.io/4273/photoshop-face-after.jpg');
background-size: cover;
background-repeat: no-repeat;
}
<section>
<button>both</button>
<button>horizontal</button>
<button>vertical</button>
<button>none</button>
<div class="resize"></div>
</section>

Try this one (source):
function enableImageResizeInDiv(id) {
if (!(/chrome/i.test(navigator.userAgent) && /google/i.test(window.navigator.vendor))) {
return;
}
var editor = document.getElementById(id);
var resizing = false;
var currentImage;
var createDOM = function (elementType, className, styles) {
let ele = document.createElement(elementType);
ele.className = className;
setStyle(ele, styles);
return ele;
};
var setStyle = function (ele, styles) {
for (key in styles) {
ele.style[key] = styles[key];
}
return ele;
};
var removeResizeFrame = function () {
document.querySelectorAll(".resize-frame,.resizer").forEach((item) => item.parentNode.removeChild(item));
};
var offset = function offset(el) {
const rect = el.getBoundingClientRect(),
scrollLeft = window.pageXOffset || document.documentElement.scrollLeft,
scrollTop = window.pageYOffset || document.documentElement.scrollTop;
return { top: rect.top + scrollTop, left: rect.left + scrollLeft }
};
var clickImage = function (img) {
removeResizeFrame();
currentImage = img;
const imgHeight = img.offsetHeight;
const imgWidth = img.offsetWidth;
const imgPosition = { top: img.offsetTop, left: img.offsetLeft };
const editorScrollTop = editor.scrollTop;
const editorScrollLeft = editor.scrollLeft;
const top = imgPosition.top - editorScrollTop - 1;
const left = imgPosition.left - editorScrollLeft - 1;
editor.append(createDOM('span', 'resize-frame', {
margin: '10px',
position: 'absolute',
top: (top + imgHeight - 10) + 'px',
left: (left + imgWidth - 10) + 'px',
border: 'solid 3px blue',
width: '6px',
height: '6px',
cursor: 'se-resize',
zIndex: 1
}));
editor.append(createDOM('span', 'resizer top-border', {
position: 'absolute',
top: (top) + 'px',
left: (left) + 'px',
border: 'dashed 1px grey',
width: imgWidth + 'px',
height: '0px'
}));
editor.append(createDOM('span', 'resizer left-border', {
position: 'absolute',
top: (top) + 'px',
left: (left) + 'px',
border: 'dashed 1px grey',
width: '0px',
height: imgHeight + 'px'
}));
editor.append(createDOM('span', 'resizer right-border', {
position: 'absolute',
top: (top) + 'px',
left: (left + imgWidth) + 'px',
border: 'dashed 1px grey',
width: '0px',
height: imgHeight + 'px'
}));
editor.append(createDOM('span', 'resizer bottom-border', {
position: 'absolute',
top: (top + imgHeight) + 'px',
left: (left) + 'px',
border: 'dashed 1px grey',
width: imgWidth + 'px',
height: '0px'
}));
document.querySelector('.resize-frame').onmousedown = () => {
resizing = true;
return false;
};
editor.onmouseup = () => {
if (resizing) {
currentImage.style.width = document.querySelector('.top-border').offsetWidth + 'px';
currentImage.style.height = document.querySelector('.left-border').offsetHeight + 'px';
refresh();
currentImage.click();
resizing = false;
}
};
editor.onmousemove = (e) => {
if (currentImage && resizing) {
let height = e.pageY - offset(currentImage).top;
let width = e.pageX - offset(currentImage).left;
height = height < 1 ? 1 : height;
width = width < 1 ? 1 : width;
const top = imgPosition.top - editorScrollTop - 1;
const left = imgPosition.left - editorScrollLeft - 1;
setStyle(document.querySelector('.resize-frame'), {
top: (top + height - 10) + 'px',
left: (left + width - 10) + "px"
});
setStyle(document.querySelector('.top-border'), { width: width + "px" });
setStyle(document.querySelector('.left-border'), { height: height + "px" });
setStyle(document.querySelector('.right-border'), {
left: (left + width) + 'px',
height: height + "px"
});
setStyle(document.querySelector('.bottom-border'), {
top: (top + height) + 'px',
width: width + "px"
});
}
return false;
};
};
var bindClickListener = function () {
editor.querySelectorAll('img').forEach((img, i) => {
img.onclick = (e) => {
if (e.target === img) {
clickImage(img);
}
};
});
};
var refresh = function () {
bindClickListener();
removeResizeFrame();
if (!currentImage) {
return;
}
var img = currentImage;
var imgHeight = img.offsetHeight;
var imgWidth = img.offsetWidth;
var imgPosition = { top: img.offsetTop, left: img.offsetLeft };
var editorScrollTop = editor.scrollTop;
var editorScrollLeft = editor.scrollLeft;
const top = imgPosition.top - editorScrollTop - 1;
const left = imgPosition.left - editorScrollLeft - 1;
editor.append(createDOM('span', 'resize-frame', {
position: 'absolute',
top: (top + imgHeight) + 'px',
left: (left + imgWidth) + 'px',
border: 'solid 2px red',
width: '6px',
height: '6px',
cursor: 'se-resize',
zIndex: 1
}));
editor.append(createDOM('span', 'resizer', {
position: 'absolute',
top: (top) + 'px',
left: (left) + 'px',
border: 'dashed 1px grey',
width: imgWidth + 'px',
height: '0px'
}));
editor.append(createDOM('span', 'resizer', {
position: 'absolute',
top: (top) + 'px',
left: (left + imgWidth) + 'px',
border: 'dashed 1px grey',
width: '0px',
height: imgHeight + 'px'
}));
editor.append(createDOM('span', 'resizer', {
position: 'absolute',
top: (top + imgHeight) + 'px',
left: (left) + 'px',
border: 'dashed 1px grey',
width: imgWidth + 'px',
height: '0px'
}));
};
var reset = function () {
if (currentImage != null) {
currentImage = null;
resizing = false;
removeResizeFrame();
}
bindClickListener();
};
editor.addEventListener('scroll', function () {
reset();
}, false);
editor.addEventListener('mouseup', function (e) {
if (!resizing) {
const x = (e.x) ? e.x : e.clientX;
const y = (e.y) ? e.y : e.clientY;
let mouseUpElement = document.elementFromPoint(x, y);
if (mouseUpElement) {
let matchingElement = null;
if (mouseUpElement.tagName === 'IMG') {
matchingElement = mouseUpElement;
}
if (!matchingElement) {
reset();
} else {
clickImage(matchingElement);
}
}
}
});
}
enableImageResizeInDiv('edt');
#edt {
padding: 2px;
width: 100%;
height: 500px;
border: 1px solid black;
overflow: scroll;
}
<!doctype html>
<html>
<body>
How to enable image resizing inside contenteditable DIV (aka WYSIWYG editor) in Chrome?<br><hr>
<div id="edt" contenteditable="true">
<p><b>Green</b><img
src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIQAAABeCAYAAADi4bzuAAABh0lEQVR4Ae3SMRXAIBAFQYKV6InYKISGgvUwV91v983z/t8aToFTYCqhwF0AiLuGfwABQQoAkRwGEAykABDJYQDBQAoAkRwGEAykABDJYQDBQAoAkRwGEAykABDJYQDBQAoAkRwGEAykABDJYQDBQAoAkRwGEAykABDJYQDBQAoAkRwGEAykABDJYQDBQAoAkRwGEAykABDJYQDBQAoAkRwGEAykABDJYQDBQAoAkRwGEAykABDJYQDBQAoAkRwGEAykABDJYQDBQAoAkRwGEAykABDJYQDBQAoAkRwGEAykABDJYQDBQAoAkRwGEAykABDJYQDBQAoAkRwGEAykABDJYQDBQAoAkRwGEAykABDJYQDBQAoAkRwGEAykABDJYQDBQAoAkRwGEAykABDJYQDBQAoAkRwGEAykABDJYQDBQAoAkRwGEAykABDJYQDBQAoAkRwGEAykABDJYQDBQAoAkRwGEAykABDJYQDBQAoAkRwGEAykABDJYQDBQAoAkRwGEAykwAbutgLcDSwO9gAAAABJRU5ErkJggg==">Red
<img
src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIQAAABeCAYAAADi4bzuAAAEQElEQVR4Ae2cPXLcMAyFn0TJXk8mXVKlzY1S5ghpcy3fKCdIxl1+7JVIZsAV1oJ3xg3cEPuYWfNHQsZ47xNIbeHh4dPnCjYqsCkwUgkqsFeAQOzV4BgEghAYBQiEkYMTAkEGjAIEwsjBCYEgA0YBAmHk4IRAkAGjAIEwcnBCIMiAUYBAGDk4IRBkwChAIIwcnBAIMmAUIBBGDk4IBBkwChAIIwcnBIIMGAUIhJGDEwJBBowCBMLIwQmBIANGAQJh5OCEQJABowCBMHJwQiDIgFGAQBg5OCEQZMAoQCCMHJyEB6IMgHy07Ya6xH6nwLQbdzncmz2++EsXcq0qARWQodwj63lbfxnTpQhv+Et3XSHUcDFdjBWP1X+99oZaXcV/1X2FEJeGCiQBop4qgjz9AkkDpTzDIveyMrzOddcVQmFo1UErxNbrtdZvW4VWEVmTCiIfNqtA1xVC93/dKnSOAshxQg3Xo4VUEHkC9ttJ2WCxslzvrGsg1DY1X4zWbUMgEUBkra3LXAO2beZ84NytX/uwayDEaGllBJ62sZ4nkjz6WxPj1w0WOWtIk75q6djuY2cfmi71ELPVewFE5m1tA0SSEki07YbnNxK9xr5zINohsY44jDdIjwW3T8D78YC6nGwfptS2DakGUjF0C9E3DQJwqUDXW0ZLJxfUsuLdfIthGPD49x8O84xjXZBzRtpy3hWMtrKvFJeyXO9K90BM04S8rMgVrU9TAkrBKP+GERXZbA1aJa7X8tcz7x6IY14x3844lgJMM9ZaMaWEYc3nzLUayBlDgJCPNKkaeu1885UP9m9i3UnRXidvZ/xGwUNa8OH7N3z8+gV/UsFSC+r2GpFH4JiAJQEyljaV07ni5VbSnQhv/At3DYRosSwZa8443N0Bv37ix/096jBgupnPQMh98uax72VMGE6a7H8OPf81fKkQaTpgQcG6HjHK+UFaqcCSkcYRadsU9JVULut3FXqe4LZxkk1+dn2GEEPX5elkfBmQ8tDeLOoopKT21oFyOlS2c8P2zaUkLhA0SJ614Kh3IMTBVgFKbvW/lBVD+0Zye+Zt1wzXA6VMWBkun4HuzxCXKXHFowCB8KgXMJZABDTVkxKB8KgXMJZABDTVkxKB8KgXMJZABDTVkxKB8KgXMJZABDTVkxKB8KgXMJZABDTVkxKB8KgXMJZABDTVkxKB8KgXMJZABDTVkxKB8KgXMJZABDTVkxKB8KgXMJZABDTVkxKB8KgXMJZABDTVkxKB8KgXMJZABDTVkxKB8KgXMJZABDTVkxKB8KgXMJZABDTVkxKB8KgXMJZABDTVkxKB8KgXMJZABDTVkxKB8KgXMJZABDTVkxKB8KgXMJZABDTVkxKB8KgXMJZABDTVkxKB8KgXMJZABDTVkxKB8KgXMJZABDTVkxKB8KgXMJZABDTVkxKB8KgXMJZABDTVk9J/bM/jwqGSC8IAAAAASUVORK5CYII=">
</p>
</div>
</body>
</html>

Related

Not able to get the input text box editable inside animated javascript

I have added the code snippet over here. I was trying to do some random exercise. Can someone look why my textbox is not editable. There is falling leaf animation over here. Along with I have added one textbox on top of it. But currently I am not able to add any text to the textbox.
I am just adding more text in order to overcome the error message that the post is mostly having code and not much explanation.
var LeafScene = function(el) {
this.viewport = el;
this.world = document.createElement('div');
this.leaves = [];
this.options = {
numLeaves: 20,
wind: {
magnitude: 1.2,
maxSpeed: 12,
duration: 300,
start: 0,
speed: 0
},
};
this.width = this.viewport.offsetWidth;
this.height = this.viewport.offsetHeight;
// animation helper
this.timer = 0;
this._resetLeaf = function(leaf) {
// place leaf towards the top left
leaf.x = this.width * 2 - Math.random()*this.width*1.75;
leaf.y = -10;
leaf.z = Math.random()*200;
if (leaf.x > this.width) {
leaf.x = this.width + 10;
leaf.y = Math.random()*this.height/2;
}
// at the start, the leaf can be anywhere
if (this.timer == 0) {
leaf.y = Math.random()*this.height;
}
// Choose axis of rotation.
// If axis is not X, chose a random static x-rotation for greater variability
leaf.rotation.speed = Math.random()*10;
var randomAxis = Math.random();
if (randomAxis > 0.5) {
leaf.rotation.axis = 'X';
} else if (randomAxis > 0.25) {
leaf.rotation.axis = 'Y';
leaf.rotation.x = Math.random()*180 + 90;
} else {
leaf.rotation.axis = 'Z';
leaf.rotation.x = Math.random()*360 - 180;
// looks weird if the rotation is too fast around this axis
leaf.rotation.speed = Math.random()*3;
}
// random speed
leaf.xSpeedVariation = Math.random() * 0.8 - 0.4;
leaf.ySpeed = Math.random() + 1.5;
return leaf;
}
this._updateLeaf = function(leaf) {
var leafWindSpeed = this.options.wind.speed(this.timer - this.options.wind.start, leaf.y);
var xSpeed = leafWindSpeed + leaf.xSpeedVariation;
leaf.x -= xSpeed;
leaf.y += leaf.ySpeed;
leaf.rotation.value += leaf.rotation.speed;
var t = 'translateX( ' + leaf.x + 'px ) translateY( ' + leaf.y + 'px ) translateZ( ' + leaf.z + 'px ) rotate' + leaf.rotation.axis + '( ' + leaf.rotation.value + 'deg )';
if (leaf.rotation.axis !== 'X') {
t += ' rotateX(' + leaf.rotation.x + 'deg)';
}
leaf.el.style.webkitTransform = t;
leaf.el.style.MozTransform = t;
leaf.el.style.oTransform = t;
leaf.el.style.transform = t;
// reset if out of view
if (leaf.x < -10 || leaf.y > this.height + 10) {
this._resetLeaf(leaf);
}
}
this._updateWind = function() {
// wind follows a sine curve: asin(b*time + c) + a
// where a = wind magnitude as a function of leaf position, b = wind.duration, c = offset
// wind duration should be related to wind magnitude, e.g. higher windspeed means longer gust duration
if (this.timer === 0 || this.timer > (this.options.wind.start + this.options.wind.duration)) {
this.options.wind.magnitude = Math.random() * this.options.wind.maxSpeed;
this.options.wind.duration = this.options.wind.magnitude * 50 + (Math.random() * 20 - 10);
this.options.wind.start = this.timer;
var screenHeight = this.height;
this.options.wind.speed = function(t, y) {
// should go from full wind speed at the top, to 1/2 speed at the bottom, using leaf Y
var a = this.magnitude/2 * (screenHeight - 2*y/3)/screenHeight;
return a * Math.sin(2*Math.PI/this.duration * t + (3 * Math.PI/2)) + a;
}
}
}
}
LeafScene.prototype.init = function() {
for (var i = 0; i < this.options.numLeaves; i++) {
var leaf = {
el: document.createElement('div'),
x: 0,
y: 0,
z: 0,
rotation: {
axis: 'X',
value: 0,
speed: 0,
x: 0
},
xSpeedVariation: 0,
ySpeed: 0,
path: {
type: 1,
start: 0,
},
image: 1
};
this._resetLeaf(leaf);
this.leaves.push(leaf);
this.world.appendChild(leaf.el);
}
this.world.className = 'leaf-scene';
this.viewport.appendChild(this.world);
// set perspective
this.world.style.webkitPerspective = "400px";
this.world.style.MozPerspective = "400px";
this.world.style.oPerspective = "400px";
this.world.style.perspective = "400px";
// reset window height/width on resize
var self = this;
window.onresize = function(event) {
self.width = self.viewport.offsetWidth;
self.height = self.viewport.offsetHeight;
};
}
LeafScene.prototype.render = function() {
this._updateWind();
for (var i = 0; i < this.leaves.length; i++) {
this._updateLeaf(this.leaves[i]);
}
this.timer++;
requestAnimationFrame(this.render.bind(this));
}
// start up leaf scene
var leafContainer = document.querySelector('.falling-leaves'),
leaves = new LeafScene(leafContainer);
leaves.init();
leaves.render();
body, html {
height: 100%;
}
form {
width: 600px;
margin: 0px auto;
padding: 15px;
}
input[type=text] {
display: block;
padding: 10px;
box-sizing: border-box;
font-size: x-large;
margin-top: 25%;
}
input[type=text] {
width: 100%;
margin-bottom: 15px;
}
.falling-leaves {
position: absolute;
top: 0;
bottom: 0;
left: 50%;
width: 100%;
max-width: 880px;
max-height: 880px; /* image is only 880x880 */
transform: translate(-50%, 0);
border: 20px solid #fff;
border-radius: 50px;
background: url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/125707/sidebar-bg.png) no-repeat center center;
background-size: cover;
overflow: hidden;
}
.leaf-scene {
position: absolute;
top: 0;
left: 0;
bottom: 0;
width: 100%;
transform-style: preserve-3d;
}
.leaf-scene div {
position: absolute;
top: 0;
left: 0;
width: 20px;
height: 20px;
background: url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/125707/leaf.svg) no-repeat;
background-size: 100%;
transform-style: preserve-3d;
backface-visibility: visible;
}
<html>
<head>
<link rel="stylesheet" type="text/css" href="style/style.css">
</head>
<body>
<div class="falling-leaves">
<form id="frmContact">
<input type="text" id="txtName" name="txtName" placeholder="Text goes here">
</form>
</div>
<script src="script/script.js"></script>
</body>
</html>

how do I make this element move backwards?

how do I stop the following interval and make the alien move backwards when it reaches 700px? I know I can do this with CSS but I want to do this strictly with JS. I don't understand how to stop the interval once it reaches the 700px left...
var game = document.querySelector(".game");
var character = document.createElement("div");
character.setAttribute("class", "character");
game.appendChild(character);
character.style.height = 20 + "px";
character.style.width = 20 + "px";
character.style.background = "gold";
var alien = document.createElement("div");
alien.setAttribute("class", "alien");
game.appendChild(alien);
alien.style.height = 20 + "px";
alien.style.width = 20 + "px";
alien.style.background = "red";
alien.style.position = "absolute";
function flow() {
var left = parseInt(window.getComputedStyle(alien).getPropertyValue("left"));
alien.style.left = left + 2 + "px";
}
interval = setInterval(flow, 10);
function stop() {
var left = parseInt(window.getComputedStyle(alien).getPropertyValue("left"));
if (left > 700) {
clearInterval(interval);
alien.style.left = left - 10 + "px";
}
};
setInterval(stop, 10);
* {
padding: 0;
margin: 0;
}
.game {
background: black;
height: 100vh;
}
.character {
position: absolute;
top: 490px;
left: 440px;
}
<div class="game">
</div>
Any help?
Introduce a speed variable which will switch from 2 to -2 when it reaches the right limit. You should then do the same at the left side, and switch the speed from -2 to 2 again.
As you want to keep moving, the stop function is no longer needed.
var game = document.querySelector(".game");
var character = document.createElement("div");
character.setAttribute("class", "character");
game.appendChild(character);
character.style.height = 20 + "px";
character.style.width = 20 + "px";
character.style.background = "gold";
var alien = document.createElement("div");
alien.setAttribute("class", "alien");
game.appendChild(alien);
alien.style.height = 20 + "px";
alien.style.width = 20 + "px";
alien.style.background = "red";
alien.style.position = "absolute";
let speed = 2;
function flow() {
var left = parseInt(window.getComputedStyle(alien).getPropertyValue("left"));
if (left > 700) speed = -2;
else if (left <= 0) speed = 2;
alien.style.left = left + speed + "px";
}
interval = setInterval(flow, 10);
* {
padding: 0;
margin: 0;
}
.game {
background: black;
height: 100vh;
}
.character {
position: absolute;
top: 490px;
left: 440px;
}
<div class="game">
</div>
To move your element you use left + 2 so it always is moving to one direction.
So when reaching 700px mark you should reverse it to be left - 2 until it's 0.
I have modified your code adding currentDirection variable
var game = document.querySelector(".game");
var character = document.createElement("div");
character.setAttribute("class", "character");
game.appendChild(character);
var alien = document.createElement("div");
alien.setAttribute("class", "alien");
game.appendChild(alien);
var currentDirection = 1;
var hasMoved = false;
function flow() {
var left = parseInt(window.getComputedStyle(alien).getPropertyValue("left"));
alien.style.left = (left + 2 * currentDirection) + "px";
}
interval = setInterval(flow, 10);
function stop() {
var left = parseInt(window.getComputedStyle(alien).getPropertyValue("left"));
if (left > 700) {
currentDirection = -1;
} else if (left < 0) {
currentDirection = 1;
}
};
setInterval(stop, 10);
* {
padding: 0;
margin: 0;
}
.game {
background: black;
height: 100vh;
}
.character {
position: absolute;
top: 490px;
left: 440px;
background: gold;
height: 20px;
width: 20px;
}
.alien {
background: red;
height: 20px;
width: 20px;
position: absolute;
}
<div class="game">
</div>

div Resizing with inner content and maintain aspect ratio

I have made a code pen example for complete understanding please checkout this link
https://codepen.io/hasan-irshad/pen/bGpPZzB
this is the code which i am using for bottom right corner
if (currentResizer.classList.contains('bottom-right')) {
const width = original_width + (e.pageX - original_mouse_x);
const height = original_height + (e.pageY - original_mouse_y)
if (width > minimum_size) {
element.style.width = width + 'px'
element.style.height = 'max-content';
let Textdiv = document.getElementById('Text');
let relFontsizew = Textdiv.offsetWidth * 0.25;
Textdiv.style.fontSize = relFontsizew + 'px';
}
}
if you resize div from bottom right corner it works fine as I want it to work, from bottom right corner it increases/decreases width of div according to the mouse-X, and height of div according to the inner content height. This is the behavior which I want to implement on all the corners.
for example if I drag from bottom right corner so the top left corner stays at it's position
just like that if I resize it from top right corner so bottom left corner should maintain it's position.
expected behavior
1 width of outer element should depend on mouse-X
2 font size should be dependent on width of outer div
3 height of outer div should depend on inner content height
4 div element should not lose its position
below is a link of video for demonstration of end result which I want to implement.
drive.google.com/file/d/1Wgh3GhEOhv1syk_WFmcCGp0UJUyGzS5u/view
can anybody please help me complete this task?
Thanks a lot in advance!!!!!
I comment the things out you dont need, and inserted the things you should add, it was mainly that you dont need to set the realtive position and you needed to set the height to "max-content", and the only time you add a script to change your font-size was in the right-bottom corner.
let Textdiv = document.getElementById('Text');
let relFontsizew = Textdiv.offsetWidth * 0.25;
Textdiv.style.fontSize = relFontsizew + 'px';
/*Make resizable div by Hung Nguyen*/
function makeResizableDiv(div) {
const element = document.querySelector(div);
const resizers = document.querySelectorAll(div + ' .resizer')
const minimum_size = 20;
let original_width = 0;
let original_height = 0;
let original_x = 0;
let original_y = 0;
let original_mouse_x = 0;
let original_mouse_y = 0;
for (let i = 0;i < resizers.length; i++) {
const currentResizer = resizers[i];
currentResizer.addEventListener('mousedown', function(e) {
e.preventDefault()
original_width = parseFloat(getComputedStyle(element, null).getPropertyValue('width').replace('px', ''));
original_height = parseFloat(getComputedStyle(element, null).getPropertyValue('height').replace('px', ''));
original_x = element.getBoundingClientRect().left;
original_y = element.getBoundingClientRect().top;
original_mouse_x = e.pageX;
original_mouse_y = e.pageY;
window.addEventListener('mousemove', resize)
window.addEventListener('mouseup', stopResize)
})
function resize(e) {
if (currentResizer.classList.contains('bottom-right')) {
const width = original_width + (e.pageX - original_mouse_x);
const height = original_height + (e.pageY - original_mouse_y)
if (width > minimum_size) {
element.style.width = width + 'px'
element.style.height = 'max-content';
let Textdiv = document.getElementById('Text');
let relFontsizew = Textdiv.offsetWidth * 0.25;
Textdiv.style.fontSize = relFontsizew + 'px';
}
}
else if (currentResizer.classList.contains('bottom-left')) {
const height = original_height + (e.pageY - original_mouse_y)
const width = original_width - (e.pageX - original_mouse_x)
if (height > minimum_size) {
element.style.height = "max-content"
}
if (width > minimum_size) {
element.style.width = width + 'px'
element.style.left = original_x + (e.pageX - original_mouse_x) + 'px'
let Textdiv = document.getElementById('Text');
let relFontsizew = Textdiv.offsetWidth * 0.25;
Textdiv.style.fontSize = relFontsizew + 'px';
}
}
else if (currentResizer.classList.contains('top-right')) {
const width = original_width + (e.pageX - original_mouse_x)
const height = original_height - (e.pageY - original_mouse_y)
if (width > minimum_size) {
element.style.width = width + 'px'
element.style.height = "max-content"
//element.style.top = original_y + (e.pageY - original_mouse_y) + 'px'
let Textdiv = document.getElementById('Text');
let relFontsizew = Textdiv.offsetWidth * 0.25;
Textdiv.style.fontSize = relFontsizew + 'px';
}
}
else {
const width = original_width - (e.pageX - original_mouse_x)
const height = original_height - (e.pageY - original_mouse_y)
if (width > minimum_size) {
element.style.width = width + 'px'
element.style.left = original_x + (e.pageX - original_mouse_x) + 'px'
}
if (height > minimum_size) {
element.style.height = "max-content"
//element.style.top = original_y + (e.pageY - original_mouse_y) + 'px'
}
let Textdiv = document.getElementById('Text');
let relFontsizew = Textdiv.offsetWidth * 0.25;
Textdiv.style.fontSize = relFontsizew + 'px';
}
}
function stopResize() {
window.removeEventListener('mousemove', resize)
}
}
}
makeResizableDiv('.resizable')
body,
html {
background: black;
}
.resizable {
background: white;
width: 100px;
height: 100px;
position: absolute;
top: 100px;
left: 100px;
}
.resizable .resizers{
width: 100%;
height: 100%;
border: 3px solid #4286f4;
box-sizing: border-box;
}
.resizable .resizers .resizer{
width: 10px;
height: 10px;
border-radius: 50%; /*magic to turn square into circle*/
background: white;
border: 3px solid #4286f4;
position: absolute;
}
.resizable .resizers .resizer.top-left {
left: -5px;
top: -5px;
cursor: nwse-resize; /*resizer cursor*/
}
.resizable .resizers .resizer.top-right {
right: -5px;
top: -5px;
cursor: nesw-resize;
}
.resizable .resizers .resizer.bottom-left {
left: -5px;
bottom: -5px;
cursor: nesw-resize;
}
.resizable .resizers .resizer.bottom-right {
right: -5px;
bottom: -5px;
cursor: nwse-resize;
}
<div class='resizable'>
<div class='resizers'>
<div class='resizer top-left'></div>
<div class='resizer top-right'></div>
<div class='resizer bottom-left'></div>
<div class='resizer bottom-right'></div>
<article id="Text" style=" width:100%; font-size:22px; color:black">Any Text</article>
</div>
</div>

How to build a resizable DIV that works with overflow: auto?

I have a resizable DIV that is resizable in the 4 sides. How ever, in some cases the content of this DIV may exceed its size. So I've added the option overflow: auto, but when I use this option, the component responsible to resize the DIV moves with the scroll.
Here's the code:
https://codesandbox.io/s/23kt1?file=/index.html
How can I fix the component always on the edges of the DIV in such a way that it's not moved when the user scroll the div?
You need an extra container for the dots to align to.
function resizeable() {
var resizers = document.querySelectorAll('.n, .s, .w, .e, .nw, .ne, .se, .sw');
const min = 40;
for (let i = 0; i < resizers.length; i++) {
const currentResizer = resizers[i];
const element = currentResizer.parentElement;
const parent = currentResizer.parentElement.parentElement;
let p;
let c;
let original_w = 0;
let original_h = 0;
let parent_x = 0;
let parent_y = 0;
let parent_sx = 0;
let parent_sy = 0;
let child_x = 0;
let child_y = 0;
let mouse_x = 0;
let mouse_y = 0;
let scale_x = 0;
let scale_y = 0;
let scroll_x = 0;
let scroll_y = 0;
// Mouse events
currentResizer.addEventListener('mousedown', function(e) {
first(e);
document.addEventListener('mousemove', resize);
document.addEventListener('mouseup', stopResize);
e.preventDefault();
});
// First location & width
function first(e) {
c = element.getBoundingClientRect();
child_y = c.top;
child_x = c.left;
p = parent.getBoundingClientRect();
parent_y = p.top;
parent_x = p.left;
parent_sy = parent.scrollTop;
parent_sx = parent.scrollLeft;
scroll_y = window.scrollY;
scroll_x = window.scrollX;
original_w = parseFloat(c.width).toFixed(2);
original_h = parseFloat(c.height).toFixed(2);
scale_y = parseFloat(c.height / element.offsetHeight).toFixed(2);
scale_x = parseFloat(c.width / element.offsetWidth).toFixed(2);
mouse_y = e.pageY - scroll_y;
mouse_x = e.pageX - scroll_x;
}
// Resize process
function resize(e) {
element.style.position = "absolute";
if (currentResizer.classList.contains('se')) {
const width = e.pageX - scroll_x - child_x;
const height = e.pageY - scroll_y - child_y;
if (width > min) {
element.style.width = (width / scale_x) + 'px';
}
if (height > min) {
element.style.height = (height / scale_y) + 'px';
}
if (parent.scrollTop < parent.scrollHeight) {
parent.scrollTop = parent.scrollHeight;
}
if (parent.scrollLeft < parent.scrollWidth) {
parent.scrollLeft = parent.scrollWidth;
}
} else if (currentResizer.classList.contains('sw')) {
const width = original_w - (e.pageX - scroll_x - child_x);
const height = e.pageY - scroll_y - child_y;
if (height > min) {
element.style.height = (height / scale_y) + 'px';
}
if (width > min) {
element.style.left = e.pageX - scroll_x - parent_x + parent_sx + 'px';
element.style.width = (width / scale_x) + 'px';
}
if (parent.scrollTop < parent.scrollHeight) {
parent.scrollTop = parent.scrollHeight;
}
} else if (currentResizer.classList.contains('ne')) {
const width = e.pageX - child_x - scroll_x;
const height = original_h - (e.pageY - mouse_y - scroll_y);
if (width > min) {
element.style.width = (width / scale_x) + 'px';
}
if (height > min) {
element.style.height = (height / scale_y) + 'px';
element.style.top = e.pageY - parent_y - scroll_y + parent_sy + 'px';
}
if (parent.scrollLeft < parent.scrollWidth) {
parent.scrollLeft = parent.scrollWidth;
}
} else if (currentResizer.classList.contains('nw')) {
const width = original_w - (e.pageX - scroll_x - child_x);
const height = original_h - (e.pageY - scroll_y - mouse_y);
if (width > min) {
element.style.left = e.pageX - parent_x - scroll_x + parent_sx + 'px';
element.style.width = (width / scale_x) + 'px';
}
if (height > min) {
element.style.height = (height / scale_y) + 'px';
element.style.top = e.pageY - parent_y - scroll_y + parent_sy + 'px';
}
} else if (currentResizer.classList.contains('e')) {
const width = e.pageX - scroll_x - child_x;
if (width > min) {
element.style.width = (width / scale_x) + 'px';
}
if (parent.scrollLeft < parent.scrollWidth) {
parent.scrollLeft = parent.scrollWidth;
}
} else if (currentResizer.classList.contains('s')) {
const height = e.pageY - scroll_y - child_y;
if (height > min) {
element.style.height = (height / scale_y) + 'px';
}
if (parent.scrollTop < parent.scrollHeight) {
parent.scrollTop = parent.scrollHeight;
}
} else if (currentResizer.classList.contains('w')) {
const width = original_w - (e.pageX - scroll_x - child_x);
if (width > min) {
element.style.width = (width / scale_x) + 'px';
element.style.left = (e.pageX - scroll_x - parent_x + parent_sx) + 'px';
}
} else if (currentResizer.classList.contains('n')) {
const height = original_h - (e.pageY - scroll_y - mouse_y);
if (height > min) {
element.style.height = (height / scale_y) + 'px';
element.style.top = e.pageY - parent_y - scroll_y + parent_sy + 'px';
}
}
}
// When mouse released stop
function stopResize(e) {
first(e);
document.removeEventListener('mousemove', resize);
}
}
}
resizeable();
body {
width: 1200px;
}
div {
position: absolute;
background-color: grey;
}
.regular {
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: red;
overflow: auto;
position: absolute;
}
.n,
.s,
.w,
.e,
.nw,
.ne,
.se,
.sw {
position: absolute;
width: 18px;
height: 18px;
border: 1px solid grey;
border-radius: 20px;
background-color: #fff;
z-index: 1;
}
.n:hover,
.s:hover,
.w:hover,
.e:hover,
.nw:hover,
.ne:hover,
.se:hover,
.sw:hover {
background-color: red;
}
.nw {
top: -10px;
left: -10px;
cursor: nw-resize;
}
.ne {
top: -10px;
left: calc(100% - 10px);
cursor: ne-resize;
}
.sw {
top: calc(100% - 10px);
left: -10px;
cursor: sw-resize;
}
.se {
top: calc(100% - 10px);
left: calc(100% - 10px);
cursor: se-resize;
}
.n {
top: -10px;
left: calc(50% - 10px);
cursor: n-resize;
}
.w {
top: calc(50% - 10px);
left: -10px;
cursor: w-resize;
}
.e {
top: calc(50% - 10px);
left: calc(100% - 10px);
cursor: e-resize;
}
.s {
top: calc(100% - 10px);
left: calc(50% - 10px);
cursor: s-resize;
}
.container {
position: relative;
width: 300px;
height: 300px;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="/src/styles.css" />
</head>
<body>
<div class="container">
<div class="nw"></div>
<div class="ne"></div>
<div class="sw"></div>
<div class="se"></div>
<div class="n"></div>
<div class="s"></div>
<div class="w"></div>
<div class="e"></div>
<div class="regular">
<p>SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS</p>
<p>SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS</p>
<p>SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS</p>
<p>SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS</p>
<p>SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS</p>
<p>SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS</p>
<p>SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS</p>
<p>SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS</p>
<p>SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS</p>
<p>SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS</p>
</div>
</div>
<script src="/src/index.js"></script>
</body>
</html>

how to resize div after rotating it (is it possible to modify the mouse event coordinates based on the rotation?)

there are 8 nodes around a div which can resize the div in 8 directions, when the div is not rotated, they can resize properly. However, when the div is rotated, for example, 90 degrees clockwise, then the behavior is weird, since the mouse event is different with the rotated div.
i've checked these but didn't help:
Logic to set fixed corner while resize after rotate?
How to resize with fixed corner after rotate?
i made a demo here: https://output.jsbin.com/nobasavaza
any ideas?
```
<!DOCTYPE html>
<html>
<head>
<title></title>
<style>
#cut {
opacity: 0.6;
height: 150px;
width: 150px;
position: absolute;
top: 150px;
left: 150px;
cursor: pointer;
border: 1px dotted red;
}
.box-resize {
border: 1px solid black;
width: 4px;
height: 4px;
position: absolute;
}
.box-top-left {
top: -3px;
left: -3px;
cursor: nw-resize;
}
.box-top-right {
top: -3px;
right: -3px;
cursor: ne-resize;
}
.box-left-center {
top: 50%;
left: -3px;
cursor: w-resize;
}
.box-right-center {
top: 50%;
right: -3px;
cursor: e-resize;
}
.box-bottom-left {
left: -3px;
bottom: -3px;
cursor: sw-resize;
}
.box-bottom-right {
right: -3px;
bottom: -3px;
cursor: se-resize;
}
.box-top-center {
left: 50%;
top: -3px;
cursor: n-resize;
}
.box-bottom-center {
left: 50%;
bottom: -3px;
cursor: s-resize;
}
</style>
</head>
<body>
<input type="text" id="rotate_degree" placeholder="degree in closewise">
<button id="rotate_submit">rorate</button>
<div id="cut">
hello
<div class="box-resize box-top-left"></div>
<div class="box-resize box-top-right"></div>
<div class="box-resize box-left-center"></div>
<div class="box-resize box-right-center"></div>
<div class="box-resize box-bottom-left"></div>
<div class="box-resize box-bottom-right"></div>
<div class="box-resize box-top-center"></div>
<div class="box-resize box-bottom-center"></div>
</div>
<script>
window.onload = function () {
var resize = document.getElementsByClassName("box-resize");
var cut = document.getElementById("cut");
var cutWidth = 0;
var cutHeight = 0;
var startX = 0;
var startY = 0;
var top = 0;
var left = 0;
var dir = "";
for (var i = 0; i < resize.length; i++) {
resize[i].onmousedown = function (e) {
startX = e.clientX;
startY = e.clientY;
cutWidth = cut.offsetWidth;
cutHeight = cut.offsetHeight;
top = cut.offsetTop;
left = cut.offsetLeft;
var className = this.className;
if (className.indexOf("box-right-center") > -1) {
dir = "E";
}
else if (className.indexOf("box-top-left") > -1) {
dir = "NW";
}
else if (className.indexOf("box-top-right") > -1) {
dir = "NE";
}
else if (className.indexOf("box-left-center") > -1) {
dir = "W";
}
else if (className.indexOf("box-bottom-left") > -1) {
dir = "SW";
}
else if (className.indexOf("box-bottom-right") > -1) {
dir = "SE";
}
else if (className.indexOf("box-bottom-center") > -1) {
dir = "S";
}
else if (className.indexOf("box-top-center") > -1) {
dir = "N";
}
document.addEventListener('mousemove', test);
e.preventDefault();
}
}
document.onmouseup = function (e) {
dir = "";
document.removeEventListener('mousemove', test);
e.preventDefault();
}
function test(e) {
var width = e.clientX - startX;
var height = e.clientY - startY;
if (dir == "E") {
cut.style.width = cutWidth + width + "px";
}
else if (dir == "S") {
cut.style.height = cutHeight + height + "px";
}
else if (dir == "N") {
if (height < cutHeight) {
cut.style.height = cutHeight - height + "px";
cut.style.top = top + height + "px";
}
}
else if (dir == "W") {
if (width < cutWidth) {
cut.style.width = cutWidth - width + "px";
cut.style.left = left + width + "px";
}
}
else if (dir == "NW") {
if (width < cutWidth && height < cutHeight) {
cut.style.width = cutWidth - width + "px";
cut.style.height = cutHeight - height + "px";
cut.style.top = top + height + "px";
cut.style.left = left + width + "px";
}
}
else if (dir == "NE") {
if (height < cutHeight) {
cut.style.width = cutWidth + width + "px";
cut.style.height = cutHeight - height + "px";
cut.style.top = top + height + "px";
}
}
else if (dir == "SW") {
if (width < cutWidth) {
cut.style.width = cutWidth - width + "px";
cut.style.height = cutHeight + height + "px";
cut.style.left = left + width + "px";
}
}
else if (dir == "SE") {
if (width < cutWidth) {
cut.style.width = cutWidth + width + "px";
cut.style.height = cutHeight + height + "px";
}
}
}
}
document.getElementById('rotate_submit').addEventListener('click', function () {
const degree = document.getElementById('rotate_degree');
document.getElementById("cut").style.transform = 'rotate(' + degree.value + 'deg)';
})
</script>
</body>
</html>
```

Categories

Resources