Stay div in his actual position when zoom the map - javascript

I had done a multi-layer map, then I placed one div on it. But problem is that when I zoom an image that div should changed its position to anywhere else. For example if I placed div on India but when I zoom and drag it that div is USA or anywhere. But I want it placed in its actual position.
Here is my code:
window.wheelzoom = (function() {
var defaults = {
zoom: 0.10
};
var canvas1 = document.createElement('canvas');
var canvas = document.createElement('div');
var main = function(img1, options) {
//if (!img || !img.nodeName || img.nodeName !== 'IMG') { return; }
var settings = {};
var width;
var width1;
var height;
var height1;
var bgWidth;
var bgHeight;
var bgPosX;
var bgPosY;
var previousEvent;
var cachedDataUrl;
//console.log(img1.childNodes);
var img = img1.childNodes[1];
img1 = img1.childNodes[3]
function setSrcToBackground(img, id) {
img.style.backgroundImage = 'url("' + img.src + '")';
//$("#"+id).append("<h1 style='z-index:1;'>BHumoiraj</h1>")
canvas.width = img.naturalWidth;
canvas.id = "raj";
canvas.height = img.naturalHeight;
cachedDataUrl = canvas1.toDataURL();
img.src = cachedDataUrl;
}
function updateBgStyle() {
if (bgPosX > 0) {
bgPosX = 0;
} else if (bgPosX < width - bgWidth) {
bgPosX = width - bgWidth;
}
if (bgPosY > 0) {
bgPosY = 0;
} else if (bgPosY < height - bgHeight) {
bgPosY = height - bgHeight;
}
img.style.backgroundSize = bgWidth + 'px ' + bgHeight + 'px';
var bd = Math.abs(bgPosY);
var cd = Math.abs(bgPosX);
if (bgWidth < 1281) {
img.style.backgroundImage = 'url("http://blogs-images.forbes.com/trevornace/files/2016/02/political-map-world-1200x813.jpg")';
canvas.width = img.naturalWidth;
canvas.height = img.naturalHeight;
}
if (bgWidth > 1281 && bgWidth < 2283) {
img.style.backgroundImage = 'url("http://www.vector-eps.com/wp-content/gallery/administrative-europe-map-vector-and-images/administrative-europe-map-image2.jpg")';
img.style.border = "2px solid red";
}
if (bgWidth > 2283) {
img.style.backgroundImage = 'url("http://laraveldaily.com/wp-content/uploads/2016/08/World-Map-Blue.jpg")';
//img.style.backgroundSize = 2000+'px '+bgHeight+'px';
}
img.style.backgroundPosition = bgPosX + 'px ' + bgPosY + 'px';
// img1.style.top = bgPosY;//"-90px" ;
// img1.style.left = bgPosX;//"120px";
}
function reset() {
bgWidth = width;
bgHeight = height;
img1.style.top = height1 //"-90px" ;
img1.style.left = width1; //"120px";
bgPosX = bgPosY = 0;
updateBgStyle();
}
function onwheel(e) {
var deltaY = 0;
e.preventDefault();
if (e.deltaY) { // FireFox 17+ (IE9+, Chrome 31+?)
deltaY = e.deltaY;
} else if (e.wheelDelta) {
deltaY = -e.wheelDelta;
}
var rect = img.getBoundingClientRect();
var offsetX = e.pageX - rect.left - window.pageXOffset;
var offsetY = e.pageY - rect.top - window.pageYOffset;
var bgCursorX = offsetX - bgPosX;
var bgCursorY = offsetY - bgPosY;
var bgRatioX = bgCursorX / bgWidth;
var bgRatioY = bgCursorY / bgHeight;
if (deltaY < 0) {
bgWidth += bgWidth * settings.zoom;
bgHeight += bgHeight * settings.zoom;
} else {
bgWidth -= bgWidth * settings.zoom;
bgHeight -= bgHeight * settings.zoom;
}
// Take the percent offset and apply it to the new size:
bgPosX = offsetX - (bgWidth * bgRatioX);
bgPosY = offsetY - (bgHeight * bgRatioY);
// Prevent zooming out beyond the starting size
if (bgWidth <= width || bgHeight <= height) {
reset();
} else {
updateBgStyle();
}
}
function set(a, b, e) {
console.log("top=" + a + "left=" + b);
img1.style.top = b + "px"; //"-90px" ;
img1.style.left = a + "px"; //"120px";
}
function drag(e) {
e.preventDefault();
bgPosX += (e.pageX - previousEvent.pageX);
bgPosY += (e.pageY - previousEvent.pageY);
bgPosX += (e.pageX - previousEvent.pageX);
set(bgPosX, bgPosY, e);
previousEvent = e;
updateBgStyle();
}
function removeDrag() {
document.removeEventListener('mouseup', removeDrag);
document.removeEventListener('mousemove', drag);
}
// Make the background draggable
function draggable(e) {
e.preventDefault();
previousEvent = e;
document.addEventListener('mousemove', drag);
document.addEventListener('mouseup', removeDrag);
}
function load() {
if (img.src === cachedDataUrl)
return;
var computedStyle = window.getComputedStyle(img, null);
var computedStyle1 = window.getComputedStyle(img1, null);
width = parseInt(computedStyle.width, 10);
height = parseInt(computedStyle.height, 10);
width1 = parseInt(computedStyle1.top, 10);
height1 = parseInt(computedStyle1.top, 10);
bgWidth = width;
bgHeight = height;
bgPosX = 0;
bgPosY = 0;
setSrcToBackground(img);
img.style.backgroundSize = width + 'px ' + height + 'px';
img.style.backgroundPosition = '0 0';
img.addEventListener('wheelzoom.reset', reset);
img.addEventListener('wheel', onwheel);
img.addEventListener('mousedown', draggable);
img1.addEventListener('wheelzoom.reset', reset);
img1.addEventListener('wheel', onwheel);
img1.addEventListener('mousedown', draggable);
}
var destroy = function(originalProperties) {
img.removeEventListener('wheelzoom.destroy', destroy);
img.removeEventListener('wheelzoom.reset', reset);
img.removeEventListener('load', load);
img.removeEventListener('mouseup', removeDrag);
img.removeEventListener('mousemove', drag);
img.removeEventListener('mousedown', draggable);
img.removeEventListener('wheel', onwheel);
img1.removeEventListener('wheelzoom.destroy', destroy);
img1.removeEventListener('wheelzoom.reset', reset);
img1.removeEventListener('load', load);
img1.removeEventListener('mouseup', removeDrag);
img1.removeEventListener('mousemove', drag);
img1.removeEventListener('mousedown', draggable);
img1.removeEventListener('wheel', onwheel);
img.style.backgroundImage = originalProperties.backgroundImage;
img.style.backgroundRepeat = originalProperties.backgroundRepeat;
//img.src = originalProperties.src;
}.bind(null, {
backgroundImage: img.style.backgroundImage,
backgroundRepeat: img.style.backgroundRepeat
//src: img.src
});
img.addEventListener('wheelzoom.destroy', destroy);
options = options || {};
Object.keys(defaults).forEach(function(key) {
settings[key] = options[key] !== undefined ? options[key] : defaults[key];
});
if (img.complete) {
load();
}
img.addEventListener('load', load);
};
// Do nothing in IE8
if (typeof window.getComputedStyle !== 'function') {
return function(elements) {
return elements;
};
} else {
return function(elements, options) {
if (elements && elements.length) {
Array.prototype.forEach.call(elements, main, options);
} else if (elements && elements.nodeName) {
main(elements, options);
}
return elements;
};
}
}());
wheelzoom(document.querySelector('div.zoom', "id"));
<body>
<div class='zoom' style="width: 760px;height:520px;border: 1px solid red;overflow:hidden;" id="target">
<img class='zoom1' id="img" src='http://blogs-images.forbes.com/trevornace/files/2016/02/political-map-world-1200x813.jpg' alt='Daisy!' width='755px' height='520px' />
<div style="position: relative;border: 1px solid red; width: 200px; height: 100px;top:-190px;">
<img src='camera.png' alt='Daisy!' width='55px' height='20px' />
</div>
</div>
</body>

don't use width and height.you can use bootstrap with col-md-... class.use divs with this kind of classes.Its helpfull to responsive.

Related

want to style the all dots of pre built html canvas background

The code is different, I apologize may I didn't ask the question the right way, you can understand well in principle, When I'm hovering the dots get colours and connect to each other, other dots are invisible, I want that all dots should be visible all time. live example available on codepen, https://codepen.io/tati420/pen/RwBamQo?editors=1111
(function () {
var width,
height,
largeHeader,
canvas,
ctx,
points,
target,
animateHeader = true;
// Main
initHeader();
initAnimation();
addListeners();
function initHeader() {
width = window.innerWidth;
height = window.innerHeight;
target = { x: width / 2, y: height / 2 };
largeHeader = document.getElementById("large-header");
largeHeader.style.height = height + "px";
canvas = document.getElementById("demo-canvas");
canvas.width = width;
canvas.height = height;
ctx = canvas.getContext("2d");
// create points
points = [];
for (var x = 0; x < width; x = x + width / 20) {
for (var y = 0; y < height; y = y + height / 20) {
var px = x + (Math.random() * width) / 20;
var py = y + (Math.random() * height) / 20;
var p = { x: px, originX: px, y: py, originY: py };
points.push(p);
}
}
// for each point find the 5 closest points
for (var i = 0; i < points.length; i++) {
var closest = [];
var p1 = points[i];
for (var j = 0; j < points.length; j++) {
var p2 = points[j];
if (!(p1 == p2)) {
var placed = false;
for (var k = 0; k < 5; k++) {
if (!placed) {
if (closest[k] == undefined) {
closest[k] = p2;
placed = true;
}
}
}
for (var k = 0; k < 5; k++) {
if (!placed) {
if (getDistance(p1, p2) < getDistance(p1, closest[k])) {
closest[k] = p2;
placed = true;
}
}
}
}
}
p1.closest = closest;
}
// assign a circle to each point
for (var i in points) {
var c = new Circle(
points[i],
2 + Math.random() * 2,
"rgba(0,255,255,0.3)"
);
points[i].circle = c;
}
}
// Event handling
function addListeners() {
if (!("ontouchstart" in window)) {
window.addEventListener("mousemove", mouseMove);
}
window.addEventListener("scroll", scrollCheck);
window.addEventListener("resize", resize);
}
function mouseMove(e) {
var posx = (posy = 0);
if (e.pageX || e.pageY) {
posx = e.pageX;
posy = e.pageY;
} else if (e.clientX || e.clientY) {
posx =
e.clientX +
document.body.scrollLeft +
document.documentElement.scrollLeft;
posy =
e.clientY +
document.body.scrollTop +
document.documentElement.scrollTop;
}
target.x = posx;
target.y = posy;
}
function scrollCheck() {
if (document.body.scrollTop > height) animateHeader = false;
else animateHeader = true;
}
function resize() {
width = window.innerWidth;
height = window.innerHeight;
largeHeader.style.height = height + "px";
canvas.width = width;
canvas.height = height;
}
// animation
function initAnimation() {
animate();
for (var i in points) {
shiftPoint(points[i]);
}
}
function animate() {
if (animateHeader) {
ctx.clearRect(0, 0, width, height);
for (var i in points) {
// detect points in range
if (Math.abs(getDistance(target, points[i])) < 4000) {
points[i].active = 0.3;
points[i].circle.active = 0.6;
} else if (Math.abs(getDistance(target, points[i])) < 20000) {
points[i].active = 0.1;
points[i].circle.active = 0.3;
} else if (Math.abs(getDistance(target, points[i])) < 40000) {
points[i].active = 0.02;
points[i].circle.active = 0.1;
} else {
points[i].active = 0;
points[i].circle.active = 0;
}
drawLines(points[i]);
points[i].circle.draw();
}
}
requestAnimationFrame(animate);
}
function shiftPoint(p) {
TweenLite.to(p, 1 + 1 * Math.random(), {
x: p.originX - 50 + Math.random() * 100,
y: p.originY - 50 + Math.random() * 100,
ease: Circ.easeInOut,
onComplete: function () {
shiftPoint(p);
},
});
}
ctx.strokeStyle = "rgba(255,0,0," + p.active + ")";
// Canvas manipulation
function drawLines(p) {
if (!p.active) return;
for (var i in p.closest) {
ctx.beginPath();
ctx.moveTo(p.x, p.y);
ctx.lineTo(p.closest[i].x, p.closest[i].y);
ctx.strokeStyle = "rgba(0,255,255," + p.active + ")";
ctx.stroke();
}
}
function Circle(pos, rad, color) {
var _this = this;
// constructor
(function () {
_this.pos = pos || null;
_this.radius = rad || null;
_this.color = color || null;
})();
this.draw = function () {
if (!_this.active) return;
ctx.beginPath();
ctx.arc(_this.pos.x, _this.pos.y, _this.radius, 0, 2 * Math.PI, false);
ctx.fillStyle = "rgba(0,255,0," + _this.active + ")";
ctx.fill();
};
}
// Util
function getDistance(p1, p2) {
return Math.pow(p1.x - p2.x, 2) + Math.pow(p1.y - p2.y, 2);
}
})();
If I understand your question correctly, you just want to make sure that every point.active = 1 and point.circle.active = 1:
function animate() {
if (animateHeader) {
ctx.clearRect(0, 0, width, height);
for (var i in points) {
points[i].active = 1;
points[i].circle.active = 1;
drawLines(points[i]);
points[i].circle.draw();
}
}
requestAnimationFrame(animate);
}

How to position image on canvas same as overlaped div of same dimension

I have two div of same dimension which overlap each other using z-index.
Ist div contain image and 2nd div contain a canvas
I am trying to draw image on canvas same place as Ist div. I am using hammerjs library to zoomin/out , reposition and rotate image. I found these code somewhere else
function getMeta(url){
img = new Image();
var remoteImage = {}
img.src = url;
remoteImage.width = img.naturalWidth
remoteImage.height = img.naturalHeight
remoteImage.src = url;
return remoteImage
}
var urlImage = getMeta('https://www.penghu-nsa.gov.tw/FileDownload/Album/Big/20161012162551758864338.jpg')
var text = document.querySelector("#text");
var oImg=document.querySelector("#img_scan");
oImg.style['transition-duration'] = '100ms';
var timeInMs = 0;
var preAngle = 0;
var rotateAngle = 0;
var preRotation = 0;
var originalSize = {
width : oImg.offsetWidth,
height : oImg.offsetHeight,
}
var current = {
x : 0,
y : 0,
z : 1,
angle : 0,
width: originalSize.width,
height: originalSize.height,
}
var last = {
x : 0,
y : 0,
z : 1,
}
var oImgRec = oImg.getBoundingClientRect();
var cx = oImgRec.left + oImgRec.width * 0.5;
var cy = oImgRec.top + oImgRec.height * 0.5;
var imageCenter = {
x:cx,
y:cy
}
var pinchImageCenter = {}
var deltaIssue = { x: 0, y: 0 };
var pinchStart = { x: undefined, y: undefined, isPanend:false}
var panendDeltaFix = {x:0,y:0,isPanend:false}
var pinchZoomOrigin = undefined;
var lastEvent = ''
var hammer = new Hammer(oImg);
hammer.get('pinch').set({enable: true});
hammer.get('pan').set({direction: Hammer.DIRECTION_ALL}).recognizeWith(hammer.get('pinch'));
hammer.on("pinchstart", function(e) {
last.x = current.x;
last.y = current.y;
pinchStart.x = e.center.x;
pinchStart.y = e.center.y;
pinchImageCenter = {
x: imageCenter.x + last.x,
y: imageCenter.y + last.y
}
lastEvent = 'pinchstart';
});
hammer.on("pinchmove", function(e) {
if(preAngle == 0){
preAngle = Math.round(e.rotation);
preRotation = Math.round(e.rotation);
}else{
if(Math.abs(Math.round(e.rotation)-preRotation)>=300){
if(e.rotation > 0){
preAngle+=360;
}else if(e.rotation < 0){
preAngle-=360;
}
}
current.angle = rotateAngle + (Math.round(e.rotation)-preAngle);
preRotation = Math.round(e.rotation);
}
var newScale = (last.z * e.scale) >= 0.1 ? (last.z * e.scale) : 0.1;
var d = scaleCal(e.center, pinchImageCenter, last.z, newScale)
current.x = d.x + last.x;
current.y = d.y + last.y;
current.z = d.z + last.z;
update();
lastEvent = 'pinchmove';
});
hammer.on("pinchend", function(e) {
last.x = current.x;
last.y = current.y;
last.z = current.z;
rotateAngle = current.angle;
preAngle = 0;
lastEvent = 'pinchend';
});
hammer.on("panmove", function(e) {
var panDelta = {
x:e.deltaX,
y:e.deltaY
}
if (lastEvent !== 'panmove') {
deltaIssue = {
x: panDelta.x,
y: panDelta.y
}
}
current.x = (last.x+panDelta.x-deltaIssue.x);
current.y = (last.y+panDelta.y-deltaIssue.y);
lastEvent = 'panmove'
update();
});
hammer.on("panend", function(e) {
last.x = current.x;
last.y = current.y;
lastEvent = 'panend';
});
hammer.on('tap', function(e) {
if((Date.now()-timeInMs)<300){
if(last.z > 1){
last.z = 1;
current.z = 1;
update();
}else if(last.z <= 1){
last.z = 2;
current.z = 2;
update();
}
}
timeInMs = Date.now();
lastEvent = 'tap';
});
function scaleCal(eCenter, originCenter, currentScale, newScale) {
var zoomDistance = newScale - currentScale;
var x = (originCenter.x - eCenter.x)*(zoomDistance)/currentScale;
var y = (originCenter.y - eCenter.y)*(zoomDistance)/currentScale;
var output = {
x: x,
y: y,
z: zoomDistance
}
return output
}
function update() {
current.height = originalSize.height * current.z;
current.width = originalSize.width * current.z;
if(current.z < 0.1){
current.z = 0.1;
}
oImg.style.transform = " translate3d(" + current.x + "px, " + current.y + "px, 0)rotate("+current.angle+"deg)scale("+current.z+")"
}
So by above code user can zoomin/zoom out , rotate image . After they set image in their desired position i am putting that image on canvas so i can use dataurl method to save image later.
I tried below code to draw image on canvas same place as div ,same dimension and with same angle but sadly image is not getting exactly same positioned as div
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
$("#btn").click(copyoncanvas);
function copyoncanvas(){
var bound=objimg.getBoundingClientRect();
var objimg=new Image();
objimg.src="https://www.penghu-nsa.gov.tw/FileDownload/Album/Big/20161012162551758864338.jpg";
ctx.drawImage(objimg,bound.left,bound.top,current.width,current.height);
drawRotated(current.angle,bound.left,bound.top);
}
function drawRotated(degrees,l,t){
const objimg=document.getElementById("img_scan");
ctx.clearRect(0,0,canvas.width,canvas.height);
ctx.save();
var x=canvas.width/2;
var y=canvas.height/2;
ctx.translate(x,y);
ctx.rotate(degrees * Math.PI/180);
ctx.drawImage(objimg,-l,-t,current.width,current.height);
ctx.restore();
}
I think my problem is with drawrotated function because it work fine without using it but i want to rotate image on canvas too
HTML
<div id="container">
<div class="box"><canvas id="canvas"></canvas></div>
<div id="imgcont">
<img src="https://www.penghu-nsa.gov.tw/FileDownload/Album/Big/20161012162551758864338.jpg" id="img_scan" class="img-custom-img2"/>
</div>
</div>
<button id="btn">Copy on canvas</button>
CSS
#container{
position:relative;margin: 0px;
padding:0px;background:#ff0;
top:0px; overflow:hidden;
width:300px;
border:1px solid #000; height:250}
#img_scan,.box{
width:100%; height:100%;
position: absolute;
top: 0;
left: 0; margin:0; padding:0px
}
.box{z-index:98;height:250}
#canvas{width:100%;margin:0;
padding:0;
width:300;height:250}
#img_scan{width:300px;height:250px}
#imgcont{width:100%;height:250px;z-index:99}

How to resize a HTML5 Canvas with JavaScript by clik and drag? [duplicate]

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.
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).
what about a pure css3 solution?
div {
resize: both;
overflow: auto;
}
MDN Web Docs
W3Schools example
Browser support
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);
}
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
just using the mousemove event in vanilla js
steps
add the mousemove to your target
listen to the target move event
get the pointer position, resize your target
codes
const div = document.querySelector(`div.before`);
const box = document.querySelector(`div.container`);
box.addEventListener(`mousemove`, (e) => {
const {
offsetX,
offsetY,
} = e;
div.style.width = offsetX + `px`;
});
live demo
https://codepen.io/xgqfrms/full/wvMQqZL
refs
https://developer.mozilla.org/en-US/docs/Web/API/Element/mousemove_event
https://medium.com/the-z/making-a-resizable-div-in-js-is-not-easy-as-you-think-bda19a1bc53d
here is a example with resizer helpers in all sides and corners
element = document.getElementById("element")
makeResizable(element,10,10)
function makeResizable(element, minW = 100, minH = 100, size = 20)
{
const top = document.createElement('div');
top.style.width = '100%';
top.style.height = size + 'px';
top.style.backgroundColor = 'transparent';
top.style.position = 'absolute';
top.style.top = - (size/2) + 'px';
top.style.left = '0px';
top.style.cursor = 'n-resize';
top.addEventListener('mousedown',resizeYNegative())
element.appendChild(top);
const bottom = document.createElement('div');
bottom.style.width = '100%';
bottom.style.height = size + 'px';
bottom.style.backgroundColor = 'transparent';
bottom.style.position = 'absolute';
bottom.style.bottom = - (size/2) + 'px';
bottom.style.left = '0px';
bottom.style.cursor = 'n-resize';
bottom.addEventListener('mousedown',resizeYPositive())
element.appendChild(bottom);
const left = document.createElement('div');
left.style.width = size + 'px';
left.style.height = '100%';
left.style.backgroundColor = 'transparent';
left.style.position = 'absolute';
left.style.top = '0px';
left.style.left = - (size/2) + 'px';
left.style.cursor = 'e-resize';
left.addEventListener('mousedown',resizeXNegative())
element.appendChild(left);
const right = document.createElement('div');
right.style.width = size + 'px';
right.style.height = '100%';
right.style.backgroundColor = 'transparent';
right.style.position = 'absolute';
right.style.top = '0px';
right.style.right = - (size/2) + 'px';
right.style.cursor = 'e-resize';
right.addEventListener('mousedown',resizeXPositive())
element.appendChild(right);
const corner1 = document.createElement('div');
corner1.style.width = size + 'px';
corner1.style.height = size + 'px';
corner1.style.backgroundColor = 'transparent';
corner1.style.position = 'absolute';
corner1.style.top = - (size/2) + 'px';
corner1.style.left = - (size/2) + 'px';
corner1.style.cursor = 'nw-resize';
corner1.addEventListener('mousedown',resizeXNegative())
corner1.addEventListener('mousedown',resizeYNegative())
element.appendChild(corner1);
const corner2 = document.createElement('div');
corner2.style.width = size + 'px';
corner2.style.height = size + 'px';
corner2.style.backgroundColor = 'transparent';
corner2.style.position = 'absolute';
corner2.style.top = - (size/2) + 'px';
corner2.style.right = - (size/2) + 'px';
corner2.style.cursor = 'ne-resize';
corner2.addEventListener('mousedown',resizeXPositive())
corner2.addEventListener('mousedown',resizeYNegative())
element.appendChild(corner2);
const corner3 = document.createElement('div');
corner3.style.width = size + 'px';
corner3.style.height = size + 'px';
corner3.style.backgroundColor = 'transparent';
corner3.style.position = 'absolute';
corner3.style.bottom = - (size/2) + 'px';
corner3.style.left = - (size/2) + 'px';
corner3.style.cursor = 'sw-resize';
corner3.addEventListener('mousedown',resizeXNegative())
corner3.addEventListener('mousedown',resizeYPositive())
element.appendChild(corner3);
const corner4 = document.createElement('div');
corner4.style.width = size + 'px';
corner4.style.height = size + 'px';
corner4.style.backgroundColor = 'transparent';
corner4.style.position = 'absolute';
corner4.style.bottom = - (size/2) + 'px';
corner4.style.right = - (size/2) + 'px';
corner4.style.cursor = 'se-resize';
corner4.addEventListener('mousedown',resizeXPositive())
corner4.addEventListener('mousedown',resizeYPositive())
element.appendChild(corner4);
function get_int_style(key)
{
return parseInt(window.getComputedStyle(element).getPropertyValue(key));
}
function resizeXPositive()
{
let offsetX
function dragMouseDown(e) {
if(e.button !== 0) return
e = e || window.event;
e.preventDefault();
const {clientX} = e;
offsetX = clientX - element.offsetLeft - get_int_style('width');
document.addEventListener('mouseup', closeDragElement)
document.addEventListener('mousemove', elementDrag)
}
function elementDrag(e) {
const {clientX} = e;
let x = clientX - element.offsetLeft - offsetX
if(x < minW) x = minW;
element.style.width = x + 'px';
}
function closeDragElement() {
document.removeEventListener("mouseup", closeDragElement);
document.removeEventListener("mousemove", elementDrag);
}
return dragMouseDown
}
function resizeYPositive()
{
let offsetY
function dragMouseDown(e) {
if(e.button !== 0) return
e = e || window.event;
e.preventDefault();
const {clientY} = e;
offsetY = clientY - element.offsetTop - get_int_style('height');
document.addEventListener('mouseup',closeDragElement)
document.addEventListener('mousemove',elementDrag)
}
function elementDrag(e) {
const {clientY} = e;
let y = clientY - element.offsetTop - offsetY;
if(y < minH) y = minH;
element.style.height = y + 'px';
}
function closeDragElement() {
document.removeEventListener("mouseup", closeDragElement);
document.removeEventListener("mousemove", elementDrag);
}
return dragMouseDown
}
function resizeXNegative()
{
let offsetX
let startX
let startW
let maxX
function dragMouseDown(e) {
if(e.button !== 0) return
e = e || window.event;
e.preventDefault();
const {clientX} = e;
startX = get_int_style('left')
startW = get_int_style('width')
offsetX = clientX - startX;
maxX = startX + startW - minW
document.addEventListener('mouseup',closeDragElement)
document.addEventListener('mousemove',elementDrag)
}
function elementDrag(e) {
const {clientX} = e;
let x = clientX - offsetX
let w = startW + startX - x
if(w < minW) w = minW;
if(x > maxX) x = maxX;
element.style.left = x + 'px';
element.style.width = w + 'px';
}
function closeDragElement() {
document.removeEventListener("mouseup", closeDragElement);
document.removeEventListener("mousemove", elementDrag);
}
return dragMouseDown
}
function resizeYNegative()
{
let offsetY
let startY
let startH
let maxY
function dragMouseDown(e) {
if(e.button !== 0) return
e = e || window.event;
e.preventDefault();
const {clientY} = e;
startY = get_int_style('top')
startH = get_int_style('height')
offsetY = clientY - startY;
maxY = startY + startH - minH
document.addEventListener('mouseup',closeDragElement,false)
document.addEventListener('mousemove',elementDrag,false)
}
function elementDrag(e) {
const {clientY} = e;
let y = clientY - offsetY
let h = startH + startY - y
if(h < minH) h = minH;
if(y > maxY) y = maxY;
element.style.top = y + 'px';
element.style.height = h + 'px';
}
function closeDragElement() {
document.removeEventListener("mouseup", closeDragElement);
document.removeEventListener("mousemove", elementDrag);
}
return dragMouseDown
}
}
#element {
position: absolute;
background-color: #f1f1f1;
border: 1px solid #d3d3d3;
left: 40px;
top: 40px;
width: 100px;
height: 100px;
border-radius: 5px;
}
<div id="element"></div>
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;
});
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
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>
// import
function get_difference(pre, mou) {
return {
x: mou.x - pre.x,
y: mou.y - pre.y
};
}
/*
if your panel is in a nested environment, which the parent container's width and height does not equa to document width
and height, for example, in an element `canvas`, then edit it to
function oMousePos(e) {
var rc = canvas.getBoundingClientRect();
return {
x: e.clientX - rc.left,
y: e.clientY - rc.top,
};
}
*/
function oMousePos(e) {
return {
x: e.clientX,
y: e.clientY,
};
}
function render_element(styles, el) {
for (const [kk, vv] of Object.entries(styles)) {
el.style[kk] = vv;
}
}
class MoveablePanel {
/*
prevent an element from moving out of window
*/
constructor(container, draggable, left, top) {
this.container = container;
this.draggable = draggable;
this.left = left;
this.top = top;
let rect = container.getBoundingClientRect();
this.width = rect.width;
this.height = rect.height;
this.status = false;
// initial position of the panel, should not be changed
this.original = {
left: left,
top: top
};
// current left and top postion
// {this.left, this.top}
// assign the panel to initial position
// initalize in registration
this.default();
if (!MoveablePanel._instance) {
MoveablePanel._instance = [];
}
MoveablePanel._instance.push(this);
}
mousedown(e) {
this.status = true;
this.previous = oMousePos(e)
}
mousemove(e) {
if (!this.status) {
return;
}
let pos = oMousePos(e);
let vleft = this.left + pos.x - this.previous.x;
let vtop = this.top + pos.y - this.previous.y;
let kleft, ktop;
if (vleft < 0) {
kleft = 0;
} else if (vleft > window.innerWidth - this.width) {
kleft = window.innerWidth - this.width;
} else {
kleft = vleft;
}
if (vtop < 0) {
ktop = 0;
} else if (vtop > window.innerHeight - this.height) {
ktop = window.innerHeight - this.height;
} else {
ktop = vtop;
}
this.container.style.left = `${kleft}px`;
this.container.style.top = `${ktop}px`;
}
/*
sometimes user move the cursor too fast which mouseleave is previous than mouseup
to prevent moving too fast and break the control, mouseleave is handled the same as mouseup
*/
mouseupleave(e) {
if (!this.status) {
return null;
}
this.status = false;
let pos = oMousePos(e);
let vleft = this.left + pos.x - this.previous.x;
let vtop = this.top + pos.y - this.previous.y;
if (vleft < 0) {
this.left = 0;
} else if (vleft > window.innerWidth - this.width) {
this.left = window.innerWidth - this.width;
} else {
this.left = vleft;
}
if (vtop < 0) {
this.top = 0;
} else if (vtop > window.innerHeight - this.height) {
this.top = window.innerHeight - this.height;
} else {
this.top = vtop;
}
this.show();
return true;
}
default () {
this.container.style.left = `${this.original.left}px`;
this.container.style.top = `${this.original.top}px`;
}
/*
panel with a higher z index will interupt drawing
therefore if panel is not displaying, set it with a lower z index that canvas
change index doesn't work, if panel is hiding, then we move it out
hide: record current position, move panel out
show: assign to recorded position
notice this position has nothing to do panel drag movement
they cannot share the same variable
*/
hide() {
// move to the right bottom conner
this.container.style.left = `${window.screen.width}px`;
this.container.style.top = `${window.screen.height}px`;
}
show() {
this.container.style.left = `${this.left}px`;
this.container.style.top = `${this.top}px`;
}
}
// end of import
class DotButton{
constructor(
width_px,
styles, // mainly pos, padding and margin, e.g. {top: 0, left: 0, margin: 0},
color,
color_hover,
border, // boolean
border_dismiss, // boolean: dismiss border when hover
){
this.width = width_px;
this.styles = styles;
this.color = color;
this.color_hover = color_hover;
this.border = border;
this.border_dismiss = border_dismiss;
}
create(_styles=null){
var el = document.createElement('div');
Object.keys(this.styles).forEach(kk=>{
el.style[kk] = `${this.styles[kk]}px`;
});
if(_styles){
Object.keys(_styles).forEach(kk=>{
el.style[kk] = `${this.styles[kk]}px`;
});
}
el.style.width = `${this.width}px`
el.style.height = `${this.width}px`
el.style.position = 'absolute';
el.style.left = `${this.left_px}px`;
el.style.top = `${this.top_px}px`;
el.style.background = this.color;
if(this.border){
el.style.border = '1px solid';
}
el.style.borderRadius = `${this.width}px`;
el.addEventListener('mouseenter', ()=>{
el.style.background = this.color_hover;
if(this.border_dismiss){
el.style.border = `1px solid ${this.color_hover}`;
}
});
el.addEventListener('mouseleave', ()=>{
el.style.background = this.color;
if(this.border_dismiss){
el.style.border = '1px solid';
}
});
return el;
}
}
function cursor_hover(el, default_cursor, to_cursor){
el.addEventListener('mouseenter', function(){
this.style.cursor = to_cursor;
}.bind(el));
el.addEventListener('mouseleave', function(){
this.style.cursor = default_cursor;
}.bind(el));
}
class FlexPanel extends MoveablePanel{
constructor(
parent_el,
top_px,
left_px,
width_px,
height_px,
background,
handle_width_px,
coner_vmin_ratio,
button_width_px,
button_margin_px,
){
super(
(()=>{
var el = document.createElement('div');
render_element(
{
position: 'fixed',
top: `${top_px}px`,
left: `${left_px}px`,
width: `${width_px}px`,
height: `${height_px}px`,
background: background,
},
el,
);
return el;
})(), // iife returns a container (panel el)
new DotButton(button_width_px, {top: 0, right: 0, margin: button_margin_px}, 'green', 'lightgreen', false, false).create(), // draggable
left_px, // left
top_px, // top
);
this.draggable.addEventListener('mousedown', e => {
e.preventDefault();
this.mousedown(e);
});
this.draggable.addEventListener('mousemove', e => {
e.preventDefault();
this.mousemove(e);
});
this.draggable.addEventListener('mouseup', e => {
e.preventDefault();
this.mouseupleave(e);
});
this.draggable.addEventListener('mouseleave', e => {
e.preventDefault();
this.mouseupleave(e);
});
this.parent_el = parent_el;
this.background = background;
// parent
this.width = width_px;
this.height = height_px;
this.handle_width_px = handle_width_px;
this.coner_vmin_ratio = coner_vmin_ratio;
this.panel_el = document.createElement('div');
// styles that won't change
this.panel_el.style.position = 'absolute';
this.panel_el.style.top = `${this.handle_width_px}px`;
this.panel_el.style.left = `${this.handle_width_px}px`;
this.panel_el.style.background = this.background;
this.handles = [
this.handle_top,
this.handle_left,
this.handle_bottom,
this.handle_right,
this.handle_lefttop,
this.handle_topleft,
this.handle_topright,
this.handle_righttop,
this.handle_rightbottom,
this.handle_bottomright,
this.handle_bottomleft,
this.handle_leftbottom,
] = Array.from({length: 12}, i => document.createElement('div'));
this.handles.forEach(el=>{
el.style.position = 'absolute';
});
this.handle_topleft.style.top = '0';
this.handle_topleft.style.left = `${this.handle_width_px}px`;
this.handle_righttop.style.right = '0';
this.handle_righttop.style.top = `${this.handle_width_px}px`;
this.handle_bottomright.style.bottom = '0';
this.handle_bottomright.style.right = `${this.handle_width_px}px`;
this.handle_leftbottom.style.left = '0';
this.handle_leftbottom.style.bottom = `${this.handle_width_px}px`;
this.handle_lefttop.style.left = '0';
this.handle_lefttop.style.top = '0';
this.handle_topright.style.top = '0';
this.handle_topright.style.right = '0';
this.handle_rightbottom.style.right = '0';
this.handle_rightbottom.style.bottom = '0';
this.handle_bottomleft.style.bottom = '0';
this.handle_bottomleft.style.left = '0';
this.update_ratio();
[
'ns-resize', // |
'ew-resize', // -
'ns-resize', // |
'ew-resize', // -
'nwse-resize', // \
'nwse-resize', // \
'nesw-resize', // /
'nesw-resize', // /
'nwse-resize', // \
'nwse-resize', // \
'nesw-resize', // /
'nesw-resize', // /
].map((dd, ii)=>{
cursor_hover(this.handles[ii], 'default', dd);
});
this.vtop = this.top;
this.vleft = this.left;
this.vwidth = this.width;
this.vheight = this.height;
this.update_ratio();
this.handles.forEach(el=>{
this.container.appendChild(el);
});
cursor_hover(this.draggable, 'default', 'move');
this.panel_el.appendChild(this.draggable);
this.container.appendChild(this.panel_el);
this.parent_el.appendChild(this.container);
[
this.edgemousedown,
this.verticalmousemove,
this.horizontalmousemove,
this.nwsemousemove,
this.neswmousemove,
this.edgemouseupleave,
] = [
this.edgemousedown.bind(this),
this.verticalmousemove.bind(this),
this.horizontalmousemove.bind(this),
this.nwsemousemove.bind(this),
this.neswmousemove.bind(this),
this.edgemouseupleave.bind(this),
];
this.handle_top.addEventListener('mousedown', e=>{this.edgemousedown(e, 'top')});
this.handle_left.addEventListener('mousedown', e=>{this.edgemousedown(e, 'left')});
this.handle_bottom.addEventListener('mousedown', e=>{this.edgemousedown(e, 'bottom')});
this.handle_right.addEventListener('mousedown', e=>{this.edgemousedown(e, 'right')});
this.handle_lefttop.addEventListener('mousedown', e=>{this.edgemousedown(e, 'lefttop')});
this.handle_topleft.addEventListener('mousedown', e=>{this.edgemousedown(e, 'topleft')});
this.handle_topright.addEventListener('mousedown', e=>{this.edgemousedown(e, 'topright')});
this.handle_righttop.addEventListener('mousedown', e=>{this.edgemousedown(e, 'righttop')});
this.handle_rightbottom.addEventListener('mousedown', e=>{this.edgemousedown(e, 'rightbottom')});
this.handle_bottomright.addEventListener('mousedown', e=>{this.edgemousedown(e, 'bottomright')});
this.handle_bottomleft.addEventListener('mousedown', e=>{this.edgemousedown(e, 'bottomleft')});
this.handle_leftbottom.addEventListener('mousedown', e=>{this.edgemousedown(e, 'leftbottom')});
this.handle_top.addEventListener('mousemove', this.verticalmousemove);
this.handle_left.addEventListener('mousemove', this.horizontalmousemove);
this.handle_bottom.addEventListener('mousemove', this.verticalmousemove);
this.handle_right.addEventListener('mousemove', this.horizontalmousemove);
this.handle_lefttop.addEventListener('mousemove', this.nwsemousemove);
this.handle_topleft.addEventListener('mousemove', this.nwsemousemove);
this.handle_topright.addEventListener('mousemove', this.neswmousemove);
this.handle_righttop.addEventListener('mousemove', this.neswmousemove);
this.handle_rightbottom.addEventListener('mousemove', this.nwsemousemove);
this.handle_bottomright.addEventListener('mousemove', this.nwsemousemove);
this.handle_bottomleft.addEventListener('mousemove', this.neswmousemove);
this.handle_leftbottom.addEventListener('mousemove', this.neswmousemove);
this.handle_top.addEventListener('mouseup', e=>{this.verticalmousemove(e); this.edgemouseupleave()});
this.handle_left.addEventListener('mouseup', e=>{this.horizontalmousemove(e); this.edgemouseupleave()});
this.handle_bottom.addEventListener('mouseup', e=>{this.verticalmousemove(e); this.edgemouseupleave()});
this.handle_right.addEventListener('mouseup', e=>{this.horizontalmousemove(e); this.edgemouseupleave()});
this.handle_lefttop.addEventListener('mouseup', e=>{this.nwsemousemove(e); this.edgemouseupleave()});
this.handle_topleft.addEventListener('mouseup', e=>{this.nwsemousemove(e); this.edgemouseupleave()});
this.handle_topright.addEventListener('mouseup', e=>{this.neswmousemove(e); this.edgemouseupleave()});
this.handle_righttop.addEventListener('mouseup', e=>{this.neswmousemove(e); this.edgemouseupleave()});
this.handle_rightbottom.addEventListener('mouseup', e=>{this.nwsemousemove(e); this.edgemouseupleave()});
this.handle_bottomright.addEventListener('mouseup', e=>{this.nwsemousemove(e); this.edgemouseupleave()});
this.handle_bottomleft.addEventListener('mouseup', e=>{this.neswmousemove(e); this.edgemouseupleave()});
this.handle_leftbottom.addEventListener('mouseup', e=>{this.neswmousemove(e); this.edgemouseupleave()});
this.handle_top.addEventListener('mouseleave', this.edgemouseupleave);
this.handle_left.addEventListener('mouseleave', this.edgemouseupleave);
this.handle_bottom.addEventListener('mouseleave', this.edgemouseupleave);
this.handle_right.addEventListener('mouseleave', this.edgemouseupleave);
this.handle_lefttop.addEventListener('mouseleave', this.edgemouseupleave);
this.handle_topleft.addEventListener('mouseleave', this.edgemouseupleave);
this.handle_topright.addEventListener('mouseleave', this.edgemouseupleave);
this.handle_righttop.addEventListener('mouseleave', this.edgemouseupleave);
this.handle_rightbottom.addEventListener('mouseleave', this.edgemouseupleave);
this.handle_bottomright.addEventListener('mouseleave', this.edgemouseupleave);
this.handle_bottomleft.addEventListener('mouseleave', this.edgemouseupleave);
this.handle_leftbottom.addEventListener('mouseleave', this.edgemouseupleave);
}
// box size change triggers corner handler size change
update_ratio(){
this.container.style.top = `${this.vtop}px`;
this.container.style.left = `${this.vleft}px`;
this.container.style.width = `${this.vwidth}px`;
this.container.style.height = `${this.vheight}px`;
this.panel_el.style.width = `${this.vwidth - 2 * this.handle_width_px}px`;
this.panel_el.style.height = `${this.vheight - 2 * this.handle_width_px}px`;
this.ratio = this.vwidth < this.vheight ? this.coner_vmin_ratio * this.vwidth : this.coner_vmin_ratio * this.vheight;
[
this.handle_top,
this.handle_bottom,
].forEach(el=>{
el.style.width = `${this.vwidth - 2 * this.ratio}px`;
el.style.height = `${this.handle_width_px}px`;
});
[
this.handle_left,
this.handle_right,
].forEach(el=>{
el.style.height = `${this.vheight - 2 * this.ratio}px`;
el.style.width = `${this.handle_width_px}px`;
});
this.handle_top.style.top = `0`;
this.handle_top.style.left = `${this.ratio}px`;
this.handle_left.style.top = `${this.ratio}px`;
this.handle_left.style.left = `0`;
this.handle_bottom.style.bottom = `0`;
this.handle_bottom.style.right = `${this.ratio}px`;
this.handle_right.style.bottom = `${this.ratio}px`;
this.handle_right.style.right = `0`;
[
this.handle_topright,
this.handle_bottomleft,
].forEach(el=>{
el.style.width = `${this.ratio}px`;
el.style.height = `${this.handle_width_px}px`;
});
[
this.handle_lefttop,
this.handle_rightbottom,
].forEach(el=>{
el.style.width = `${this.handle_width_px}px`;
el.style.height = `${this.ratio}px`;
});
[
this.handle_topleft,
this.handle_bottomright,
].forEach(el=>{
el.style.width = `${this.ratio - this.handle_width_px}px`;
el.style.height = `${this.handle_width_px}px`;
});
[
this.handle_righttop,
this.handle_leftbottom,
].forEach(el=>{
el.style.height = `${this.handle_width_px}px`;
el.style.width = `${this.ratio - this.handle_width_px}px`;
});
}
edgemousedown(e, flag){
this.previous = oMousePos(e);
this.flag = flag;
this.drag = true;
}
verticalmousemove(e){
if(this.drag){
// -
this.mouse = oMousePos(e);
var ydif = this.mouse.y - this.previous.y;
switch(this.flag){
case 'top':
this.vtop = this.top + ydif;
this.vheight = this.height - ydif;
this.vleft = this.left;
this.vwidth = this.width;
break;
case 'bottom':
this.vheight = this.height + ydif;
this.vtop = this.top;
this.vleft = this.left;
this.vwidth = this.width;
break;
}
this.update_ratio();
}
}
horizontalmousemove(e){
if(this.drag){
// |
this.mouse = oMousePos(e);
var xdif = this.mouse.x - this.previous.x;
switch(this.flag){
case 'left':
this.vleft = this.left + xdif;
this.vwidth = this.width - xdif;
this.vtop = this.top;
this.vheight = this.height;
break;
case 'right':
this.vwidth = this.width + xdif;
this.vtop = this.top;
this.vleft = this.left;
this.vheight = this.height;
break;
}
this.update_ratio();
}
}
nwsemousemove(e){
if(this.drag){
// \
this.mouse = oMousePos(e);
var ydif = this.mouse.y - this.previous.y;
var xdif = this.mouse.x - this.previous.x;
switch(this.flag){
case 'topleft':
this.vleft = this.left + xdif;
this.vtop = this.top + ydif;
this.vwidth = this.width - xdif;
this.vheight = this.height - ydif;
break;
case 'lefttop':
this.vleft = this.left + xdif;
this.vtop = this.top + ydif;
this.vwidth = this.width - xdif;
this.vheight = this.height - ydif;
break;
case 'bottomright':
this.vwidth = this.width + xdif;
this.vheight = this.height + ydif;
this.vtop = this.top;
this.vleft = this.left;
break;
case 'rightbottom':
this.vwidth = this.width + xdif;
this.vheight = this.height + ydif;
this.vtop = this.top;
this.vleft = this.left;
break;
}
this.update_ratio();
}
}
neswmousemove(e){
if(this.drag){
// /
this.mouse = oMousePos(e);
var ydif = this.mouse.y - this.previous.y;
var xdif = this.mouse.x - this.previous.x;
switch(this.flag){
case 'topright':
this.vtop = this.top + ydif;
this.vwidth = this.width + xdif;
this.vheight = this.height - ydif;
this.vleft = this.left;
break;
case 'righttop':
this.vtop = this.top + ydif;
this.vwidth = this.width + xdif;
this.vheight = this.height - ydif;
this.vleft = this.left;
break;
case 'bottomleft':
this.vleft = this.left + xdif;
this.vwidth = this.width - xdif;
this.vheight = this.height + ydif;
this.vtop = this.top;
break;
case 'leftbottom':
this.vleft = this.left + xdif;
this.vwidth = this.width - xdif;
this.vheight = this.height + ydif;
this.vtop = this.top;
break;
}
this.update_ratio();
}
}
edgemouseupleave(){
this.drag = false;
this.top = this.vtop;
this.left = this.vleft;
this.width = this.vwidth;
this.height = this.vheight;
}
mouseupleave(e){
if(super.mouseupleave(e)){
this.vtop = this.top;
this.vleft = this.left;
}
}
}
var fp = new FlexPanel(
document.body, // parent div container
20, // top margin
20, // left margin
200, // width
150, // height
'lightgrey', // background
20, // handle height when horizontal; handle width when vertical
0.2, // edge up and left resize bar width : top resize bar width = 1 : 5
35, // green move button width and height
2, // button margin
);
/*
this method creates an element for you
which you don't need to pass in a selected element
to manipuate dom element
fp.container -> entire panel
fp.panel_el -> inside panel
*/
Achieving functionalities fully requires a lot of hard coding. Please refer to the documentation, it will show you how to use each class as element.
const onMouseDownEvent=(ev: React.DragEvent)=>{
let imgElem = (ev.target as HTMLImageElement);
let childElem = (ev.currentTarget && ev.currentTarget.childNodes && ev.currentTarget.childNodes[0]);
let original_height = parseFloat(getComputedStyle(imgElem, null).getPropertyValue('height').replace('px', ''));
let original_width = parseFloat(getComputedStyle(imgElem, null).getPropertyValue('width').replace('px', ''));
let original_Y = imgElem.getBoundingClientRect().top;
let original_X = imgElem.getBoundingClientRect().right;
ev.preventDefault();
var original_mouse_y = ev.pageY;
var original_mouse_x = ev.pageX;
document.addEventListener('mousemove', resize);
document.addEventListener('mouseup', stopResize);
function resize(mouseMoveEvent) {
const height = original_height + (mouseMoveEvent.pageY - original_mouse_y);
const width = original_width + (mouseMoveEvent.pageX - original_mouse_x);
imgElem.style.height = height + 'px';
mouseMoveEvent.target.childNodes[0].innerHTML = imgElem.style.height;
imgElem.style.width = width + 'px';
mouseMoveEvent.target.childNodes[0].innerHTML = imgElem.style.width;
}
function stopResize() {
document.removeEventListener('mousemove', resize)
}
}
<div onMouseDown={onMouseDownEvent} id="imgInCanvas" onDragStart={ onDragStartFromContainer } draggable="true"/>
I'm not sure if this is what you are looking for, but you can always use CSS resize property and add it to an element using javascript; For example lets say you have a div element with the id myDiv and you want to make it resizable:
document.getElementById("myDiv").style.resize = "both";
here's the related links:
Style resize Property
CSS resize Property
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>

Zoom based on cursor using javascript

I've both tried to solve the problem as well as search StackOverflow for multiple solutions, none that seemed to work properly. I have what appears to be a close but not quite the end result I'm looking for. I'm trying to make it so when the user zooms using the mousewheel, the zoom being based on the cursor's position.
Could someone explain what I'm doing wrong here. Somewhere in my calculation for the image offset im doing something wrong which you'll see when you test it.
// offset image based on cursor position
var width = img_ele.getBoundingClientRect().width;
var height = img_ele.getBoundingClientRect().height;
var x_cursor = window.event.clientX;
var y_cursor = window.event.clientY;
var x = img_ele.offsetLeft;
var y = img_ele.offsetTop;
// Calculate displacement of zooming position.
var dx = x - ((x_cursor - x) * (factor - 1.0));
var dy = y - ((y_cursor - y) * (factor - 1.0));
img_ele.style.left = dx + 'px';
img_ele.style.top = dy + 'px';
Below is the full code. Just change the src image to one of your liking.
<!DOCTYPE html>
<html>
<body>
<div id="container">
<img ondragstart="return false" id="drag-img" src="map.jpg" />
</div>
<input type="button" id="zoomout" class="button" value="Zoom out">
<input type="button" id="zoomin" class="button" value="Zoom in">
<input type="button" id="zoomfit" class="button" value="Zoom fit">
</body>
</html>
<script>
var img_ele = null,
x_cursor = 0,
y_cursor = 0,
x_img_ele = 0,
y_img_ele = 0;
function zoom(factor) {
img_ele = document.getElementById('drag-img');
// Zoom into the image.
var width = img_ele.getBoundingClientRect().width;
var height = img_ele.getBoundingClientRect().height;
img_ele.style.width = (width * factor) + 'px';
img_ele.style.height = (height * factor) + 'px';
// offset image based on cursor position
var width = img_ele.getBoundingClientRect().width;
var height = img_ele.getBoundingClientRect().height;
var x_cursor = window.event.clientX;
var y_cursor = window.event.clientY;
var x = img_ele.offsetLeft;
var y = img_ele.offsetTop;
// Calculate displacement of zooming position.
var dx = x - ((x_cursor - x) * (factor - 1.0));
var dy = y - ((y_cursor - y) * (factor - 1.0));
img_ele.style.left = dx + 'px';
img_ele.style.top = dy + 'px';
console.log('MAP SIZE : ' + width, height);
console.log('MAP TOP/LEFT : ' + x, y, 'NEW:', dx, dy);
console.log('CURSOR : ' + x_cursor, y_cursor);
img_ele = null;
}
function zoom_fit() {
bb_el = document.getElementById('container')
img_el = document.getElementById('drag-img');
var width = bb_el.getBoundingClientRect().width;
var height = bb_el.getBoundingClientRect().height;
img_el.style.width = width + 'px';
img_el.style.height = height + 'px';
img_el.style.left = '0px';
img_el.style.top = '0px';
img_el = null;
}
document.getElementById('zoomout').addEventListener('click', function() {
zoom(0.9);
});
document.getElementById('zoomin').addEventListener('click', function() {
zoom(1.1);
});
document.getElementById('zoomfit').addEventListener('click', function() {
zoom_fit();
});
document.addEventListener('mousewheel', function(event) {
event.preventDefault();
x_cursor = window.event.clientX;
y_cursor = window.event.clientY;
// console.log('ZOOM : ' + 'X:', x_cursor, 'Y:', y_cursor);
if (event.deltaY < 0) {
// console.log('scrolling up');
zoom(1.1);
}
if (event.deltaY > 0) {
// console.log('scrolling down');
zoom(0.9);
}
});
function start_drag() {
img_ele = this;
// console.log('inside start_drag var img_ele set to : ' + this);
x_img_ele = window.event.clientX - document.getElementById('drag-img').offsetLeft;
y_img_ele = window.event.clientY - document.getElementById('drag-img').offsetTop;
// console.log('start_drag : ' + 'x_img_ele:', x_img_ele, 'y_img_ele:', y_img_ele);
}
function stop_drag() {
// console.log('stop drag');
img_ele = null;
}
function while_drag() {
// console.log('while_drag: ', window.event);
var x_cursor = window.event.clientX;
var y_cursor = window.event.clientY;
if (img_ele !== null) {
img_ele.style.left = (x_cursor - x_img_ele) + 'px';
img_ele.style.top = ( window.event.clientY - y_img_ele) + 'px';
// console.log('while_drag: ','x_cursor', x_cursor, 'x_img_ele', x_img_ele, 'y_cursor', y_cursor, 'y_img_ele', y_img_ele,'Image left and top', img_ele.style.left+' - '+img_ele.style.top);
}
}
document.getElementById('drag-img').addEventListener('mousedown', start_drag);
document.getElementById('container').addEventListener('mousemove', while_drag);
document.getElementById('container').addEventListener('mouseup', stop_drag);
function while_drag() {
var x_cursor = window.event.clientX;
var y_cursor = window.event.clientY;
if (img_ele !== null) {
img_ele.style.left = (x_cursor - x_img_ele) + 'px';
img_ele.style.top = ( window.event.clientY - y_img_ele) + 'px';
// console.log(img_ele.style.left+' - '+img_ele.style.top);
}
}
document.getElementById('drag-img').addEventListener('mousedown', start_drag);
document.getElementById('container').addEventListener('mousemove', while_drag);
document.getElementById('container').addEventListener('mouseup', stop_drag);
</script>
<style>
#drag-img {
cursor: move;
position: relative;
width: 400px;
height: 400px;
}
#container {
overflow: hidden;
background: red;
width: 400px;
height: 400px;
}
.button {
width: 80px;
height: 25px;
}
</style>

Move canvas position in HTML5 puzzle game

I have downloaded a ready-made HTML5 tile-swapping puzzle, but I am not getting how to change the canvas position.
If we change the canvas position by giving a margin to the body, the puzzle doesn't work. I'd like to align the puzzle to the middle of the page.
Here is a JSFiddle with the code for the puzzle:
https://jsfiddle.net/kilobyte/0ej6cv6w/
Here is an excerpt of the code you should examine, where I'm changing the margin:
function Add(){
alert("Congratulation...! You have Won...!!");
var btn=document.createElement("input");
btn.type="button";
btn.id="mybutton";
btn.value="Submit";
btn.style.width="100px";
btn.style.height="50px";
btn.style.background="green";
btn.style.margin="100px";
document.body.appendChild(btn);
var buttonid =document.getElementById("mybutton");
buttonid.addEventListener('click', ButtonClick,false);
}
function gameOver(){
document.onmousedown = null;
document.onmousemove = null;
document.onmouseup = null;
Add();
//initPuzzle();
}
Edit: Ok, seems like Firefox works, but chrome has a different behaviour. Im not going to rewrite the game, but i can give you a pointer on what to do. You need to edit the function called onPuzzleClick(), its located on on line 103 in the code. Thats where the click position is set (_mouse.x and _mouse.y). You need to find out whats different in chrome and set the correct position there, id advise looking at the left-margin and top-margin or some absolute position or similar
The code that you quote in your question doesn't actually change the margin of the canvas. It assigns a margin to a button at the end of the game. But never mind that. In my demonstration below, I've removed the unnecessary button and I set the canvas margin with CSS.
We can fix the problem of the shifted canvas with the help of a function that calculates the offset of an HTML element with respect to an HTML element that encloses it:
function getOffset(element, ancestor) {
var left = 0,
top = 0;
while (element != ancestor) {
left += element.offsetLeft;
top += element.offsetTop;
element = element.parentNode;
}
return { left: left, top: top };
}
We also need a function that computes the mouse position with respect to the upper left corner of the page:
function getMousePosition (event) {
event = event || window.event;
if (event.pageX) {
return { x: event.pageX, y: event.pageY };
}
return {
x: event.clientX + document.body.scrollLeft +
document.documentElement.scrollLeft,
y: event.clientY + document.body.scrollTop +
document.documentElement.scrollTop
};
}
In setCanvas(), we calculate and save the offset of the canvas relative to the page:
_canvas.offset = getOffset(_canvas, document.body);
Subsequently, when we need the mouse coordinates in onPuzzleClick() and updatePuzzle(), we take the canvas offset into account:
var position = getMousePosition(e);
_mouse.x = position.x - _canvas.offset.left;
_mouse.y = position.y - _canvas.offset.top;
Now the puzzle works correctly regardless of where the canvas is positioned:
const PUZZLE_DIFFICULTY = 4;
const PUZZLE_HOVER_TINT = '#009900';
var _canvas;
var _stage;
var _img;
var _pieces;
var _puzzleWidth;
var _puzzleHeight;
var _pieceWidth;
var _pieceHeight;
var _currentPiece;
var _currentDropPiece;
var _mouse;
function getOffset(element, ancestor) {
var left = 0,
top = 0;
while (element != ancestor) {
left += element.offsetLeft;
top += element.offsetTop;
element = element.parentNode;
}
return { left: left, top: top };
}
function getMousePosition (event) {
event = event || window.event;
if (event.pageX) {
return { x: event.pageX, y: event.pageY };
}
return {
x: event.clientX + document.body.scrollLeft +
document.documentElement.scrollLeft,
y: event.clientY + document.body.scrollTop +
document.documentElement.scrollTop
};
}
function init(){
_img = new Image();
_img.addEventListener('load',onImage,false);
_img.src = "http://www.justvape247.com/ekmps/shops/justvape247/images/red-apple-natural-f.w-16946-p.jpg";
}
function onImage(e){
_pieceWidth = Math.floor(_img.width / PUZZLE_DIFFICULTY)
_pieceHeight = Math.floor(_img.height / PUZZLE_DIFFICULTY)
_puzzleWidth = _pieceWidth * PUZZLE_DIFFICULTY;
_puzzleHeight = _pieceHeight * PUZZLE_DIFFICULTY;
setCanvas();
initPuzzle();
}
function setCanvas(){
_canvas = document.getElementById('gameCanvas');
_stage = _canvas.getContext('2d');
_canvas.width = _puzzleWidth;
_canvas.height = _puzzleHeight;
_canvas.style.border = "1px solid black";
_canvas.offset = getOffset(_canvas, document.body);
}
function initPuzzle(){
_pieces = [];
_mouse = {x:0,y:0};
_currentPiece = null;
_currentDropPiece = null;
_stage.drawImage(_img, 0, 0, _puzzleWidth, _puzzleHeight, 0, 0, _puzzleWidth, _puzzleHeight);
createTitle("Click to Start Puzzle");
buildPieces();
}
function createTitle(msg){
_stage.fillStyle = "#000000";
_stage.globalAlpha = .4;
_stage.fillRect(100,_puzzleHeight - 40,_puzzleWidth - 200,40);
_stage.fillStyle = "#FFFFFF";//text color
_stage.globalAlpha = 1;
_stage.textAlign = "center";
_stage.textBaseline = "middle";
_stage.font = "20px Arial";
_stage.fillText(msg,_puzzleWidth / 2,_puzzleHeight - 20);
}
function buildPieces(){
var i;
var piece;
var xPos = 0;
var yPos = 0;
for(i = 0;i < PUZZLE_DIFFICULTY * PUZZLE_DIFFICULTY;i++){
piece = {};
piece.sx = xPos;
piece.sy = yPos;
_pieces.push(piece);
xPos += _pieceWidth;
if(xPos >= _puzzleWidth){
xPos = 0;
yPos += _pieceHeight;
}
}
document.onmousedown = shufflePuzzle;
}
function shufflePuzzle(){
_pieces = shuffleArray(_pieces);
_stage.clearRect(0,0,_puzzleWidth,_puzzleHeight);
var i;
var piece;
var xPos = 0;
var yPos = 0;
for(i = 0;i < _pieces.length;i++){
piece = _pieces[i];
piece.xPos = xPos;
piece.yPos = yPos;
_stage.drawImage(_img, piece.sx, piece.sy, _pieceWidth, _pieceHeight, xPos, yPos, _pieceWidth, _pieceHeight);
_stage.strokeRect(xPos, yPos, _pieceWidth,_pieceHeight);
xPos += _pieceWidth;
if(xPos >= _puzzleWidth){
xPos = 0;
yPos += _pieceHeight;
}
}
document.onmousedown = onPuzzleClick;
}
function shuffleArray(o){
for(var j, x, i = o.length; i; j = parseInt(Math.random() * i), x = o[--i], o[i] = o[j], o[j] = x);
return o;
}
function onPuzzleClick(e){
var position = getMousePosition(e);
_mouse.x = position.x - _canvas.offset.left;
_mouse.y = position.y - _canvas.offset.top;
_currentPiece = checkPieceClicked();
if(_currentPiece != null){
_stage.clearRect(_currentPiece.xPos,_currentPiece.yPos,_pieceWidth,_pieceHeight);
_stage.save();
_stage.globalAlpha = .9;
_stage.drawImage(_img, _currentPiece.sx, _currentPiece.sy, _pieceWidth, _pieceHeight, _mouse.x - (_pieceWidth / 2), _mouse.y - (_pieceHeight / 2), _pieceWidth, _pieceHeight);
_stage.restore();
document.onmousemove = updatePuzzle;
document.onmouseup = pieceDropped;
}
}
function checkPieceClicked(){
var i;
var piece;
for(i = 0;i < _pieces.length;i++){
piece = _pieces[i];
if(_mouse.x < piece.xPos || _mouse.x > (piece.xPos + _pieceWidth) || _mouse.y < piece.yPos || _mouse.y > (piece.yPos + _pieceHeight)){
//PIECE NOT HIT
}
else{
return piece;
}
}
return null;
}
function updatePuzzle(e){
var position = getMousePosition(e);
_mouse.x = position.x - _canvas.offset.left;
_mouse.y = position.y - _canvas.offset.top;
_currentDropPiece = null;
_stage.clearRect(0,0,_puzzleWidth,_puzzleHeight);
var i;
var piece;
for(i = 0;i < _pieces.length;i++){
piece = _pieces[i];
if(piece == _currentPiece){
continue;
}
_stage.drawImage(_img, piece.sx, piece.sy, _pieceWidth, _pieceHeight, piece.xPos, piece.yPos, _pieceWidth, _pieceHeight);
_stage.strokeRect(piece.xPos, piece.yPos, _pieceWidth,_pieceHeight);
if(_currentDropPiece == null){
if(_mouse.x < piece.xPos || _mouse.x > (piece.xPos + _pieceWidth) || _mouse.y < piece.yPos || _mouse.y > (piece.yPos + _pieceHeight)){
//NOT OVER
}
else{
_currentDropPiece = piece;
_stage.save();
_stage.globalAlpha = .4;
_stage.fillStyle = PUZZLE_HOVER_TINT;
_stage.fillRect(_currentDropPiece.xPos,_currentDropPiece.yPos,_pieceWidth, _pieceHeight);
_stage.restore();
}
}
}
_stage.save();
_stage.globalAlpha = .6;
_stage.drawImage(_img, _currentPiece.sx, _currentPiece.sy, _pieceWidth, _pieceHeight, _mouse.x - (_pieceWidth / 2), _mouse.y - (_pieceHeight / 2), _pieceWidth, _pieceHeight);
_stage.restore();
_stage.strokeRect( _mouse.x - (_pieceWidth / 2), _mouse.y - (_pieceHeight / 2), _pieceWidth,_pieceHeight);
}
function pieceDropped(e){
document.onmousemove = null;
document.onmouseup = null;
if(_currentDropPiece != null){
var tmp = {xPos:_currentPiece.xPos,yPos:_currentPiece.yPos};
_currentPiece.xPos = _currentDropPiece.xPos;
_currentPiece.yPos = _currentDropPiece.yPos;
_currentDropPiece.xPos = tmp.xPos;
_currentDropPiece.yPos = tmp.yPos;
}
resetPuzzleAndCheckWin();
}
function resetPuzzleAndCheckWin(){
_stage.clearRect(0,0,_puzzleWidth,_puzzleHeight);
var gameWin = true;
var i;
var piece;
for(i = 0;i < _pieces.length;i++){
piece = _pieces[i];
_stage.drawImage(_img, piece.sx, piece.sy, _pieceWidth, _pieceHeight, piece.xPos, piece.yPos, _pieceWidth, _pieceHeight);
_stage.strokeRect(piece.xPos, piece.yPos, _pieceWidth,_pieceHeight);
if(piece.xPos != piece.sx || piece.yPos != piece.sy){
gameWin = false;
}
}
if(gameWin){
setTimeout(gameOver,500);
}
}
function gameOver(){
document.onmousedown = null;
document.onmousemove = null;
document.onmouseup = null;
alert("Congratulations...! You have Won...!!");
}
window.onload = init;
#gameCanvas {
margin: 20px 50px;
}
<canvas id="gameCanvas"></canvas>

Categories

Resources