Drag and drop rotated images javascript - javascript

so i have a code that allows me to drag and drop an img tag. The drag and drop works fine but when i added a rotation function, the drag and drop started acting weird (the coordinates changed and when i drag the element the rotation reset). Also when i try dragging again, it goes back to its initial position, do you please have any idea on how i can fix this?
This is my code and thank you in advance:
let rotate=0
function rot_plus() {
rotate=rotate+10
$("#test").css('transform',"rotate("+rotate+"deg)")
}
function rot_minus() {
rotate=rotate-10
$("#test").css('transform',"rotate("+rotate+"deg)")
}
var active = false;
var currentX;
var currentY;
var initialX;
var initialY;
var xOffset = 0;
var yOffset = 0;
let current_elem
var container = document.querySelector("#boite");
container.addEventListener("mousedown", dragStart, false);
container.addEventListener("mouseup", dragEnd, false);
container.addEventListener("mousemove", drag, false);
function dragStart(e) {
if(e.target.id=="test"){
dragItem1=e.target.id
dragItem = document.querySelector("#"+e.target.id);
initialX=e.clientX-xOffset
initialY=e.clientY-yOffset
active = true;
}
}
function drag(e) {
if (active) {
e.preventDefault();
currentX = e.clientX - initialX;
currentY = e.clientY - initialY;
xOffset = currentX;
yOffset = currentY;
setTranslate(currentX, currentY, dragItem);
}
}
function dragEnd(e) {
active = false;
initialX=currentX
initialY=currentY
selectedElement = null;
}
function setTranslate(xPos, yPos, el) {
el.style.transform = "translate3d(" + xPos + "px, " + yPos + "px, 0) rotate("+rotate+"deg)";
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.3/jquery.min.js" integrity="sha512-STof4xm1wgkfm7heWqFJVn58Hm3EtS31XFaagaa8VMReCXAkQnJZ+jEy8PCC/iT18dFy95WcExNHFTqLyp72eQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
</head>
<body>
<div id="boite">
<img src="https://static.vecteezy.com/system/resources/previews/009/342/282/original/cartoon-eyes-clipart-design-illustration-free-png.png" id="test" class="remove" style="position: absolute; width:150px; height:auto" >
<svg xmlns="http://www.w3.org/2000/svg" width="46" height="46" fill="currentColor" class="bi bi-plus-circle" id="rotplus" style="margin-top:120px" onclick="rot_plus()" viewBox="0 0 16 16">
<path fill-rule="evenodd" d="M8 3a5 5 0 1 0 4.546 2.914.5.5 0 0 1 .908-.417A6 6 0 1 1 8 2v1z"/>
<path d="M8 4.466V.534a.25.25 0 0 1 .41-.192l2.36 1.966c.12.1.12.284 0 .384L8.41 4.658A.25.25 0 0 1 8 4.466z"/>
</svg>
<svg xmlns="http://www.w3.org/2000/svg"width="46" height="46" fill="currentColor" class="bi bi-dash-circle" id="rotminus"
style="margin-top:120px" onclick="rot_minus()" viewBox="0 0 16 16">
<path fill-rule="evenodd" d="M8 3a5 5 0 1 1-4.546 2.914.5.5 0 0 0-.908-.417A6 6 0 1 0 8 2v1z"/>
<path d="M8 4.466V.534a.25.25 0 0 0-.41-.192L5.23 2.308a.25.25 0 0 0 0 .384l2.36 1.966A.25.25 0 0 0 8 4.466z"/>
</svg>
</div>
</body>
</html>

You are using $.css to change the transform in the rotation functions. But this removes the positional changes as both are defined in 'transform'. That is, to fix this you need to keep the position information when rotating.
To do this it is better not to use jquery as it will clean the information in transform. So what I did was just replicate the line where you define the position but instead of taking the positions defined in your function I take it directly from the variables where you store the values.
I also used a CSS to prevent items from being selected when dragging:
CSS:
#boite,
#boite * {
user-select: none;
}
JS:
function rot_plus() {
const el = lastItemDragged
rotate = rotate + 10;
el.style.transform = "translate3d(" + xOffset + "px, " + yOffset + "px, 0) rotate(" + rotate + "deg)";
}
function rot_minus() {
const el = lastItemDragged
rotate = rotate - 10;
el.style.transform = "translate3d(" + xOffset + "px, " + yOffset + "px, 0) rotate(" + rotate + "deg)";
}
function setTranslate(el) {
el.style.transform = "translate3d(" + xOffset + "px, " + yOffset + "px, 0) rotate(" + rotate + "deg)";
}
I also added the variable lastItemDragged to store the last item dragged (so that the rotation reaches the same)
full code:
let rotate = 0
function rot_plus() {
const el = lastItemDragged
rotate = rotate + 10;
el.style.transform = "translate3d(" + xOffset + "px, " + yOffset + "px, 0) rotate(" + rotate + "deg)";
}
function rot_minus() {
const el = lastItemDragged
rotate = rotate - 10;
el.style.transform = "translate3d(" + xOffset + "px, " + yOffset + "px, 0) rotate(" + rotate + "deg)";
}
var lastItemDragged = document.querySelector('#test')
var active = false;
var currentX;
var currentY;
var initialX;
var initialY;
var xOffset = 0;
var yOffset = 0;
let current_elem
var container = document.querySelector("#boite");
container.addEventListener("mousedown", dragStart, false);
container.addEventListener("mouseup", dragEnd, false);
container.addEventListener("mousemove", drag, false);
function dragStart(e) {
if (e.target.id == "test") {
dragItem1 = e.target.id
dragItem = document.querySelector("#" + e.target.id);
initialX = e.clientX - xOffset
initialY = e.clientY - yOffset
active = true;
}
}
function drag(e) {
if (active) {
e.preventDefault();
currentX = e.clientX - initialX;
currentY = e.clientY - initialY;
xOffset = currentX;
yOffset = currentY;
setTranslate(dragItem);
}
}
function dragEnd(e) {
active = false;
initialX = currentX
initialY = currentY
selectedElement = null;
}
function setTranslate(el) {
el.style.transform = "translate3d(" + xOffset + "px, " + yOffset + "px, 0) rotate(" + rotate + "deg)";
}
#boite,
#boite * {
user-select: none;
}
<div id="boite">
<img src="https://static.vecteezy.com/system/resources/previews/009/342/282/original/cartoon-eyes-clipart-design-illustration-free-png.png" id="test" class="remove" style="position: absolute; width:150px; height:auto">
<svg xmlns="http://www.w3.org/2000/svg" width="46" height="46" fill="currentColor" class="bi bi-plus-circle" id="rotplus" style="margin-top:120px" onclick="rot_plus()" viewBox="0 0 16 16">
<path fill-rule="evenodd" d="M8 3a5 5 0 1 0 4.546 2.914.5.5 0 0 1 .908-.417A6 6 0 1 1 8 2v1z" />
<path d="M8 4.466V.534a.25.25 0 0 1 .41-.192l2.36 1.966c.12.1.12.284 0 .384L8.41 4.658A.25.25 0 0 1 8 4.466z" />
</svg>
<svg xmlns="http://www.w3.org/2000/svg" width="46" height="46" fill="currentColor" class="bi bi-dash-circle" id="rotminus" style="margin-top:120px" onclick="rot_minus()" viewBox="0 0 16 16">
<path fill-rule="evenodd" d="M8 3a5 5 0 1 1-4.546 2.914.5.5 0 0 0-.908-.417A6 6 0 1 0 8 2v1z" />
<path d="M8 4.466V.534a.25.25 0 0 0-.41-.192L5.23 2.308a.25.25 0 0 0 0 .384l2.36 1.966A.25.25 0 0 0 8 4.466z" />
</svg>
</div>

Related

Multiple Draggable divs "tangle"

I'm trying to develop a maths game for kids that does not need the keyboard.
Round divs are draggable into blue boxes (also divs).
Dragging down quickly on any round div over the other round divs causes them to wander! (touch or slow mouse both work fine).
sample reference removed 21.2.2022 all relevant information is in the useful answer thanks to Oleg
My hunch is a 3D transform at the end of the script is to blame but I don't really understand it.
Any help Greatly appreciated
If I understood correctly, then in your example, you'd better use Pointer Events and Pointer capture. Your example with PointerEvents below:
const box1 = document.querySelector("#box1");
const box2 = document.querySelector("#box2");
const box3 = document.querySelector("#box3");
const box4 = document.querySelector("#box4");
const box5 = document.querySelector("#box5");
const item1 = document.querySelector("#item1");
const item2 = document.querySelector("#item2");
const item3 = document.querySelector("#item3");
const item4 = document.querySelector("#item4");
const item5 = document.querySelector("#item5");
let active = false;
let currentX;
let currentY;
let initialX;
let initialY;
let xOffset = 0;
let yOffset = 0;
//////////////////////////////////////////
// Moved from dragend
//////////////////////////////////////////
const box1Size = box1.getBoundingClientRect(); //the size of box1
const box2Size = box2.getBoundingClientRect(); //the size of box2
const box3Size = box3.getBoundingClientRect(); //the size of box2
const box4Size = box4.getBoundingClientRect(); //the size of box2
const box5Size = box5.getBoundingClientRect(); //the size of box2
//Add Event Listeners for Touchscreens
//container.addEventListener("touchstart", dragStart, false);
//container.addEventListener("touchend", dragEnd, false);
//container.addEventListener("touchmove", drag, false);
item1.addEventListener('pointerdown', dragStart);
item1.addEventListener('pointerup', dragEnd);
item2.addEventListener('pointerdown', dragStart);
item2.addEventListener('pointerup', dragEnd);
item3.addEventListener('pointerdown', dragStart);
item3.addEventListener('pointerup', dragEnd);
item4.addEventListener('pointerdown', dragStart);
item4.addEventListener('pointerup', dragEnd);
item5.addEventListener('pointerdown', dragStart);
item5.addEventListener('pointerup', dragEnd);
function dragStart(e) { //when the drag starts
this.addEventListener('pointermove', drag);
this.setPointerCapture(e.pointerId);
if (e.type === "touchstart") { //if its a touchscreen
initialX = e.touches[0].clientX - xOffset; //set initial x-cordinate to where it was before drag started
initialY = e.touches[0].clientY - yOffset; //set initial y-cordinate to where it was before drag started
} else { //if its not a touchscreen (mouse)
initialX = e.clientX - xOffset; //set initial x-cordinate to where it was before drag started
initialY = e.clientY - yOffset; //set initial y-cordinate to where it was before drag started
}
}
function dragEnd(e) { //when the drag ends
this.removeEventListener('pointermove', drag);
this.releasePointerCapture(e.pointerId);
const elementSize = e.target.getBoundingClientRect(); //the size of the circle
if (elementSize.left >= box1Size.left && elementSize.right <= box1Size.right && elementSize.top >= box1Size.top && elementSize.bottom <= box1Size.bottom) {
//if the circle is in box1
initialX = currentX; //set the initial x-cordinate to where it is now
initialY = currentY; //set the initial y-cordinate to where it is now
box1.innerHTML = box1.innerHTML + " " + e.target.innerHTML;
} else if (elementSize.left >= box2Size.left && elementSize.right <= box2Size.right && elementSize.top >= box2Size.top && elementSize.bottom <= box2Size.bottom) {
//if the circle is in box2
initialX = currentX; //set the initial x-cordinate to where it is now
initialY = currentY; //set the initial y-cordinate to where it is now
box2.innerHTML = box2.innerHTML + " " + e.target.innerHTML;
} else if (elementSize.left >= box3Size.left && elementSize.right <= box3Size.right && elementSize.top >= box3Size.top && elementSize.bottom <= box3Size.bottom) {
//if the circle is in box3
initialX = currentX; //set the initial x-cordinate to where it is now
initialY = currentY; //set the initial y-cordinate to where it is now
box3.innerHTML = box3.innerHTML + " " + e.target.innerHTML;
} else if (elementSize.left >= box4Size.left && elementSize.right <= box4Size.right && elementSize.top >= box4Size.top && elementSize.bottom <= box4Size.bottom) {
//if the circle is in box4
initialX = currentX; //set the initial x-cordinate to where it is now
initialY = currentY; //set the initial y-cordinate to where it is now
box4.innerHTML = box4.innerHTML + " " + e.target.innerHTML;
} else if (elementSize.left >= box5Size.left && elementSize.right <= box5Size.right && elementSize.top >= box5Size.top && elementSize.bottom <= box5Size.bottom) {
//if the circle is in box5
initialX = currentX; //set the initial x-cordinate to where it is now
initialY = currentY; //set the initial y-cordinate to where it is now
box5.innerHTML = box5.innerHTML + " " + e.target.innerHTML;
} else { //if the circle is in neither box1 nor box2
/*currentX = 0;
currentY = 0;
initialX = 0;
initialY = 0;
xOffset = 0;
yOffset = 0;
setTranslate(0, 0, e.target);*/
}
currentX = 0;
currentY = 0;
initialX = 0;
initialY = 0;
xOffset = 0;
yOffset = 0;
setTranslate(0, 0, e.target);
active = false; //the drag is no longer active
}
function drag(e) { //when the circle is being dragged
if (e.type === "touchmove") { //if its a touchscreen
currentX = e.touches[0].clientX - initialX; //set current x-cordinate to where it is now
currentY = e.touches[0].clientY - initialY; //set current y-cordinate to where it is now
} else { //if its not a touchscreen (mouse)
currentX = e.clientX - initialX; //set current x-cordinate to where it is now
currentY = e.clientY - initialY; //set current y-cordinate to where it is now
}
xOffset = currentX;
yOffset = currentY;
setTranslate(currentX, currentY, e.target);
}
function setTranslate(xPos, yPos, e) {
e.style.transform = "translate3d(" + xPos + "px, " + yPos + "px, 0)";
}
.flex-container {
display: flex;
}
[id^=i] {
width: 80px;
height: 80px;
margin: auto;
background-color: ivory;
border: 1px solid DarkRed;
border-radius: 50%;
touch-action: none;
user-select: none;
/*position: absolute;*/
font-size: 40px;
text-align: center;
}
[id^=b] {
/* this applies to all elements with ids beginning with "b" */
font-size: 40px;
border: 2px solid LightGrey;
width: 100px;
height: 100px;
background-color: blue;
color: ivory;
text-align: center;
}
<h2>Trial</h2>
<div>
<table>
<tr>
<td>
<div id="box1" class="box" ;></div>
</td>
<td>
<div id="item1" draggable="false">A</div>
</td>
</tr>
<tr>
<td>
<div id="box2" class="box"></div>
</td>
<td>
<div id="item2">B</div>
</td>
</tr>
<tr>
<td>
<div id="box3" class="box"></div>
</td>
<td>
<div id="item3">C</div>
</td>
</tr>
<tr>
<td>
<div id="box4" class="box"></div>
</td>
<td>
<div id="item4">D</div>
</td>
</tr>
<tr>
<td>
<div id="box5" class="box"></div>
</td>
<td>
<div id="item5">E</div>
</td>
</tr>
</table>
</div>

Animating attribute values with JavaScript | Zooming in the SVG viewBox

We have a SVG grid generated with JavaScript.
The goal is to 2X zoom the SVG grid when the user double clicks on any coordinate on the grid and have a short animation transition between the previous zoom state and current zoom state. This actually works almost 100% fine in my snippet below except one problem:
I can animate the level of zoom but cannot smoothly animate the X and Y coordinate transitions well.
View the snippet below ( preferably in full screen ) and double click on the grid a few times.
'use strict'
function zoom( evt ){
var loc = getCoords( evt ),
newX = loc.x / 0.8 - 12.5,
newY = loc.y / 0.8 - 12.5,
grid = document.getElementById( 'grid' ),
viewBoxAttr = grid.getAttribute( 'viewBox' ),
viewBoxAry = viewBoxAttr.split( ' ' ),
curX = viewBoxAry[ 0 ], curY = viewBoxAry[ 1 ],
curZm = viewBoxAry[ 2 ], dblZm = curZm / 2,
tweenZm = curZm, diffX = 0,
interval = setInterval(
function(){
if( tweenZm >= dblZm ){
tweenZm = tweenZm / 1.015625;
diffX = newX - curX;
}
else {
clearInterval( interval );
}
zmOnPt( newX, newY, tweenZm );
},
10
),
ary = [];
ary.push( curZm );
ary.push( dblZm );
}
var grid = document.getElementById( 'grid' );
grid.addEventListener( 'dblclick', zoom );
createLines( '.h-lns' ); createLines( '.v-lns' );
createLabels( '.h-num' ); createLabels( '.v-num' );
recalibrate();
<head>
<link id="main" rel="stylesheet"
href="https://codepen.io/basement/pen/brJLLZ.css"
>
<link id="animations" rel="stylesheet"
href="https://codepen.io/basement/pen/zdXRWo.css"
>
</head>
<body id="body">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" class="cntr" id="grid">
<script id="injectGrid" xlink:href="https://codepen.io/basement/pen/brJLLZ.js">
</script>
<g id="drawing">
<circle cx="60" cy="40" r="0.5" fill="#0dd" opacity="0.9" />
<circle cx="70" cy="40" r="0.5" fill="#0dd" opacity="0.9" />
<path
fill="none" opacity="0.5" stroke="#0dd" stroke-width="0.5"
d="
M60, 40
A10, 10
0,
0, 1
70, 50
C70, 55
65, 60
60, 60
Q50, 60
50, 50
T55, 35
T70, 40
"
/>
</g>
</svg>
<script id="sidebar" src="https://codepen.io/basement/pen/zdXRWo.js"></script>
<script id="main" src="https://codepen.io/basement/pen/yorjXq.js"></script>
</body>
Notice the smooth zoom animation coupled with the jarring x and y translation? The viewBox just skips to the X and Y coordinate you clicked without animating over to it. Then it zooms in on the now centered coordinates.
The goal is for the x and y to transition smoothly with the zoom.
I've hidden a lot of the code I think is irrelevant in separate files this snippet links to on codepen. If you want to see those without copy and pasting the source code though, here is a list:
MAIN CSS:
https://codepen.io/basement/pen/brJLLZ.css
ANIMATION CSS:
https://codepen.io/basement/pen/zdXRWo.css
GRID CREATION JS:
https://codepen.io/basement/pen/brJLLZ.js
SIDEBAR CODE:
https://codepen.io/basement/pen/zdXRWo.js
MAIN JAVASCRIPT:
https://codepen.io/basement/pen/yorjXq.js
Your zoom function seems unnecessarily complicated. It has seemingly arbitrary equation constants that I don't understand, and you are manipulating coordinates in a way that I don't see a purpose for.
For the version below, I am just halving the viewBox width and height, then centering that on the coordinates where you click the mouse. Then, for the animation, I just do a linear interpolation from the old viewBox values to the new ones.
function zoom( evt ) {
var loc = getCoords( evt ),
grid = document.getElementById( 'grid' ),
viewBoxAttr = grid.getAttribute( 'viewBox' ),
viewBoxAry = viewBoxAttr.split(' ');
var oldX = parseFloat(viewBoxAry[0]);
var oldY = parseFloat(viewBoxAry[1]);
var oldWidth = parseFloat(viewBoxAry[2]);
var oldHeight = parseFloat(viewBoxAry[3]);
var newWidth = oldWidth / 2; // Halving the view width => zoom X2
var newHeight = oldHeight / 2;
var newX = loc.x - newWidth / 2;
var newY = loc.y - newHeight / 2;
var animProgress = 0; // Goes from 0 to 1
var animStep = 0.02; // Change in animProgress per interval function invocation.
var interval = setInterval( function() {
animProgress += animStep;
if (animProgress > 1)
animProgress = 1;
// Calculate a new viewBox corresponding to our animation progress
var nextViewBox = [
oldX + animProgress * (newX - oldX),
oldY + animProgress * (newY - oldY),
oldWidth + animProgress * (newWidth - oldWidth),
oldHeight + animProgress * (newHeight - oldHeight)
];
grid.setAttribute("viewBox", nextViewBox.join(' '));
if (animProgress >= 1)
clearInterval( interval );
}, 10);
}
'use strict'
function zoom( evt ) {
var loc = getCoords( evt ),
grid = document.getElementById( 'grid' ),
viewBoxAttr = grid.getAttribute( 'viewBox' ),
viewBoxAry = viewBoxAttr.split(' ');
var oldX = parseFloat(viewBoxAry[0]);
var oldY = parseFloat(viewBoxAry[1]);
var oldWidth = parseFloat(viewBoxAry[2]);
var oldHeight = parseFloat(viewBoxAry[3]);
var newWidth = oldWidth / 2;
var newHeight = oldHeight / 2;
var newX = loc.x - newWidth / 2;
var newY = loc.y - newHeight / 2;
var animProgress = 0; // Goes from 0 to 1
var animStep = 0.02; // Change in animProgress per interval function invocation.
var interval = setInterval( function() {
animProgress += animStep;
if (animProgress > 1)
animProgress = 1;
// Calculate a new viewBox corresponding to our animation progress
var nextViewBox = [
oldX + animProgress * (newX - oldX),
oldY + animProgress * (newY - oldY),
oldWidth + animProgress * (newWidth - oldWidth),
oldHeight + animProgress * (newHeight - oldHeight)
];
grid.setAttribute("viewBox", nextViewBox.join(' '));
if (animProgress >= 1)
clearInterval( interval );
}, 10);
}
var grid = document.getElementById( 'grid' );
grid.addEventListener( 'dblclick', zoom );
createLines( '.h-lns' ); createLines( '.v-lns' );
createLabels( '.h-num' ); createLabels( '.v-num' );
recalibrate();
<head>
<link id="main" rel="stylesheet"
href="https://codepen.io/basement/pen/brJLLZ.css"
>
<link id="animations" rel="stylesheet"
href="https://codepen.io/basement/pen/zdXRWo.css"
>
</head>
<body id="body">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" class="cntr" id="grid">
<script id="injectGrid" xlink:href="https://codepen.io/basement/pen/brJLLZ.js">
</script>
<g id="drawing">
<circle cx="60" cy="40" r="0.5" fill="#0dd" opacity="0.9" />
<circle cx="70" cy="40" r="0.5" fill="#0dd" opacity="0.9" />
<path
fill="none" opacity="0.5" stroke="#0dd" stroke-width="0.5"
d="
M60, 40
A10, 10
0,
0, 1
70, 50
C70, 55
65, 60
60, 60
Q50, 60
50, 50
T55, 35
T70, 40
"
/>
</g>
</svg>
<script id="sidebar" src="https://codepen.io/basement/pen/zdXRWo.js"></script>
<script id="main" src="https://codepen.io/basement/pen/yorjXq.js"></script>
</body>

Translate += in jquery

Is there any easy way where we can add += for CSS.
var obj = $('#svg > g');
var x = parseInt(obj.attr('transform').split(/[()]/)[1].split(',')[0]);
var y = parseInt(obj.attr('transform').split(/[()]/)[1].split(',')[1]);
obj.attr('transform', 'translate(' + (x + 100) + ', ' + (y + 5) + ')');
$('#svg').css("width", "+=200");
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<svg id="svg" xmlns="http://www.w3.org/2000/svg" width="100" height="200">
<g transform="translate(10, 10)">
<rect x="0" y="0" rx="10" ry="10" width="100%" height="100%" pointer-events="all"></rect>
</g>
</svg>
Similar to styling the width. //css("width", "+=200");
i need for transform translate something like obj.attr('transform', 'translateX("+="'+100+')');.
You can use the jquery width attribute:
$('#svg').width($('#svg').width() + 200);
For the transforming the attribute, you can get the position
var x = $('#svg > g').position().left;
var y = $('#svg > g').position().top;
Then throw that to change the CSS of the object
$('#svg g').css({'transform': 'translate(' + (x + 100) +'px, ' + (y + 5) + 'px'});

Svg Draw flickering happening in Chrome browser

I need to allow user to draw a shape and I have used svg for same.
In other browser the code is working perfectly fine, but in case of chrome Version 52.0.2743.116 m it is flickering. When I created it it was working fine. But as chrome was updated the issue started happening
Issue is not replicable in chrome Version 49.0.2623.110 m
https://jsfiddle.net/2svxmgwu/1/
Try to drag and drop in yellow area from left top side to right bottom you will see barcode
Refer the attached image
The flickering does not happen if direction of creating shape is other then from top left to lower bottom.
Code
Html
<div class="thisComp">
<div class="svgElementDiv">
</div>
</div>
Js
var svgShape = $('<svg viewBox="0 0 640 480" preserveAspectRatio="none" xmlns="http://www.w3.org/2000/svg"><g><title>Layer 1</title> <rect stroke="#5B9BD5" id="svg_11" height="473.99998" width="635.99997" y="3" x="3" stroke-linecap="null" stroke-linejoin="null" preserveAspectRatio="none" vector-effect="non-scaling-stroke" stroke-dasharray="null" stroke-width="3" fill="#5B9BD5"/> </g></svg>');
var self = this;
//Added for chrome browser as without this flickering is very high
svgShape.find('[vector-effect="non-scaling-stroke"]').removeAttr('vector-effect');
var $ShapeWrapper = $(".svgElementDiv");
var $thisComp = $(".thisComp");
svgShape.css({
position: "absolute",
left: "0",
top: "0",
width: "100%",
height: "100%",
opacity: "0.5"
});
$ShapeWrapper.css({
position: "fixed"
});
$thisComp.mousedown(function (event) {
if ($ShapeWrapper.length > 0) {
$ShapeWrapper.html(svgShape);
$ShapeWrapper.css("left", event.clientX);
$ShapeWrapper.css("top", event.clientY);
self._selectorLeftPos = event.clientX;
self._selectorTopPos = event.clientY;
$ShapeWrapper.css({
width: "0",
height: "0"
});
self._dragged = false;
event.preventDefault();
}
});
var removeShape = function (event) {
if ($ShapeWrapper.find(svgShape).length > 0 && !(event.type=="mouseleave" && $(event.relatedTarget).closest('.guideWrapper').length>0)) {
var startX = (($ShapeWrapper.offset().left - $thisComp.offset().left) / self._transformRatio) / self._conversionFactor;
var startY = (($ShapeWrapper.offset().top - $thisComp.offset().top) / self._transformRatio) / self._conversionFactor;
var selectWidth = ($ShapeWrapper.width() / self._transformRatio) / self._conversionFactor;
var selectHeight = ($ShapeWrapper.height() / self._transformRatio) / self._conversionFactor;
self._shapeData = '{"left":"' + startX + '","top":"' + startY + '","height":"' + selectHeight + '","width":"' + selectWidth + '"}';
svgShape.remove();
}
}
$thisComp.mousemove(function (event) {
if ($ShapeWrapper.length > 0) {
var width = 0;
var height = 0;
if (event.clientX <= self._selectorLeftPos) {
width = $ShapeWrapper.offset().left - event.clientX + $ShapeWrapper.width();
$ShapeWrapper.css("left", event.clientX);
}
else {
width = event.clientX - $ShapeWrapper.offset().left;
}
if (event.clientY <= self._selectorTopPos) {
height = $ShapeWrapper.offset().top - event.clientY + $ShapeWrapper.height();
$ShapeWrapper.css("top", event.clientY);
}
else {
height = event.clientY - $ShapeWrapper.offset().top;
}
$ShapeWrapper.css("width", width);
$ShapeWrapper.css("height", height);
if (width > 3 || height > 3) {
self._dragged = true;
}
}
});
$thisComp.bind("mouseup", removeShape);
$thisComp.bind("mouseleave", removeShape);
Css
.thisComp{
height:400px;
width:400px;
background-color:yellow;
}

Change a div size on right-click hold and drag

I try to make a div resizable on right-click hold and drag.
What I want is a mouse's right-click to change a div's dimentions on drag.
I have a problem which seems like to be that the previous size of the div is not updated.
On the second attempt to drag the div, it starts with it's previous state.
My code:
$(document).ready(function() {
// right click event
$("#displayWindow")
// when the mouse is pressed, the div is appended to the displayWindow
.mousedown(function(e) {
if (e.button == 2) {
$('#div1').remove();
// append the div start at the location that we click
$("#displayWindow").append("<div id='div1'></div>");
// get the coordinate where we clicked and set the div begin with that position
var clickedX = e.pageX;
var clickedY = e.pageY;
$('#div1').css('top', clickedY);
$('#div1').css('left', clickedX);
// holding on the mouse button, change the size of the div
$("#displayWindow").on("mousemove", function(e) {
if (e.button == 2) {
var mouseOnX = e.pageX;
var mouseOnY = e.pageY;
// allow user drag the selection box in 4 different direction
if (mouseOnX > clickedX && mouseOnY > clickedY) {
$('#div1').css('top', clickedY);
$('#div1').css('left', clickedX);
$('#div1').css('height', mouseOnY - clickedY);
$('#div1').css('width', mouseOnX - clickedX);
} else if (clickedX > mouseOnX && mouseOnY > clickedY) {
$('#div1').css('top', clickedY);
$('#div1').css('left', mouseOnX);
$('#div1').css('height', mouseOnY - clickedY);
$('#div1').css('width', clickedX - mouseOnX);
} else if (clickedX > mouseOnX && clickedY > mouseOnY) {
$('#div1').css('top', mouseOnY);
$('#div1').css('left', mouseOnX);
$('#div1').css('height', clickedY - mouseOnY);
$('#div1').css('width', clickedX - mouseOnX);
} else if (mouseOnX > clickedX && clickedY > mouseOnY) {
$('#div1').css('top', mouseOnY);
$('#div1').css('left', clickedX);
$('#div1').css('height', clickedY - mouseOnY);
$('#div1').css('width', mouseOnX - clickedX);
}
}
}); // end on, while we move the mouse
return false;
}
return true;
});
// when clicked again, the menu fade out, and the div disappear
$(document).click(function(e) {
if (e.button == 0) {
// remove the selection box div
$('#div1').remove();
}
});
// prevent the default contextmenu on the display window
document.getElementById('displayWindow').oncontextmenu = function() {
return false;
}
}); // end ready
#displayWindow {
background-color: white;
border: 1px solid;
height: 600px;
width: 800px;
}
#div1 {
background-color: lightgreen;
position: absolute;
opacity: 0.3;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="displayWindow">
<svg height="130" width="150" style="position:absolute; left:200; top:200;" class="ui-widget-content">
<text fill="black" x=75 y=75 style="text-anchor: middle">1</text>
<path d="M38 0 L113 0 L150 65 L113 130 L38 130 L0 65 Z" / fill="none" stroke="blue">
</svg>
</div>
Just add this inside the if (e.button == 2) {. To reset the element added previously.
$('#div1').removeAttr('style').remove();
// right click event
$("#displayWindow")
// when the mouse is pressed, the div is appended to the displayWindow
.mousedown(function(e) {
if (e.button == 2) {
$('#div1').removeAttr('style').remove();
// append the div start at the location that we click
$("#displayWindow").append("<div id='div1'></div>");
// get the coordinate where we clicked and set the div begin with that position
var clickedX = e.pageX;
var clickedY = e.pageY;
$('#div1').css('top', clickedY);
$('#div1').css('left', clickedX);
// holding on the mouse button, change the size of the div
$("#displayWindow").on("mousemove", function(e) {
if (e.button == 2) {
var mouseOnX = e.pageX;
var mouseOnY = e.pageY;
// allow user drag the selection box in 4 different direction
if (mouseOnX > clickedX && mouseOnY > clickedY) {
$('#div1').css('top', clickedY);
$('#div1').css('left', clickedX);
$('#div1').css('height', mouseOnY - clickedY);
$('#div1').css('width', mouseOnX - clickedX);
} else if (clickedX > mouseOnX && mouseOnY > clickedY) {
$('#div1').css('top', clickedY);
$('#div1').css('left', mouseOnX);
$('#div1').css('height', mouseOnY - clickedY);
$('#div1').css('width', clickedX - mouseOnX);
} else if (clickedX > mouseOnX && clickedY > mouseOnY) {
$('#div1').css('top', mouseOnY);
$('#div1').css('left', mouseOnX);
$('#div1').css('height', clickedY - mouseOnY);
$('#div1').css('width', clickedX - mouseOnX);
} else if (mouseOnX > clickedX && clickedY > mouseOnY) {
$('#div1').css('top', mouseOnY);
$('#div1').css('left', clickedX);
$('#div1').css('height', clickedY - mouseOnY);
$('#div1').css('width', mouseOnX - clickedX);
}
}
}); // end on, while we move the mouse
return false;
}
return true;
});
// when clicked again, the menu fade out, and the div disappear
$(document).click(function(e) {
if (e.button == 0) {
// remove the selection box div
$('#div1').remove();
}
});
// prevent the default contextmenu on the display window
document.getElementById('displayWindow').oncontextmenu = function() {
return false;
}
#displayWindow {
background-color: white;
border: 1px solid;
height: 400px;
width: 800px;
}
#div1 {
background-color: lightgreen;
position: absolute;
opacity: 0.3;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="displayWindow">
<svg height="130" width="150" style="position:absolute; left:200; top:200;" class="ui-widget-content">
<text fill="black" x=75 y=75 style="text-anchor: middle">1</text>
<path d="M38 0 L113 0 L150 65 L113 130 L38 130 L0 65 Z" fill="none" stroke="blue" />
</svg>
</div>

Categories